Skip to content

Commit

Permalink
[5.x] Ability to disable CP authentication (#8960)
Browse files Browse the repository at this point in the history
Co-authored-by: edalzell <[email protected]>
Co-authored-by: Jason Varga <[email protected]>
  • Loading branch information
3 people authored Jun 27, 2024
1 parent a53391d commit 7ace3c1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 12 deletions.
15 changes: 15 additions & 0 deletions config/cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@

'route' => env('CP_ROUTE', 'cp'),

/*
|--------------------------------------------------------------------------
| Authentication
|--------------------------------------------------------------------------
|
| Whether the Control Panel's authentication pages should be enabled,
| and where users should be redirected in order to authenticate.
|
*/

'auth' => [
'enabled' => true,
'redirect_to' => null,
],

/*
|--------------------------------------------------------------------------
| Start Page
Expand Down
10 changes: 7 additions & 3 deletions resources/js/components/SessionExpiry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export default {
warnAt: Number,
lifetime: Number,
email: String,
oauthProvider: String
oauthProvider: String,
auth: Object,
},
data() {
Expand Down Expand Up @@ -102,7 +103,7 @@ export default {
watch: {
count(count) {
this.isShowingLogin = this.remaining <= 0;
this.isShowingLogin = this.auth.enabled && this.remaining <= 0;
// While we're in the warning period, we'll check every second so that any
// activity in another tab is picked up and the count will get restarted.
Expand Down Expand Up @@ -145,7 +146,10 @@ export default {
return this.$axios.get(cp_url('session-timeout')).then(response => {
this.count = this.remaining = response.data;
}).catch(e => {
if (e.response.status === 401) this.remaining = 0;
if (e.response.status === 401) {
this.remaining = 0;
if (!this.auth.enabled) window.location = this.auth.redirect_to || '/';
}
throw e;
}).finally(response => {
this.pinging = false;
Expand Down
3 changes: 2 additions & 1 deletion resources/views/partials/session-expiry.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
:warn-at="{{ $warnAt }}"
:lifetime="{{ $lifetime }}"
:oauth-provider="{{ json_encode($oauth) }}"
></session-expiry>
:auth="{{ json_encode($auth) }}"
></session-expiry>
17 changes: 10 additions & 7 deletions routes/cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,17 @@
use Statamic\Statamic;

Route::group(['prefix' => 'auth'], function () {
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);
Route::get('logout', [LoginController::class, 'logout'])->name('logout');
if (config('statamic.cp.auth.enabled', true)) {
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);

Route::get('password/reset', [ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request');
Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email');
Route::get('password/reset/{token}', [ResetPasswordController::class, 'showResetForm'])->name('password.reset');
Route::post('password/reset', [ResetPasswordController::class, 'reset'])->name('password.reset.action');
}

Route::get('password/reset', [ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request');
Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email');
Route::get('password/reset/{token}', [ResetPasswordController::class, 'showResetForm'])->name('password.reset');
Route::post('password/reset', [ResetPasswordController::class, 'reset'])->name('password.reset.action');
Route::get('logout', [LoginController::class, 'logout'])->name('logout');

Route::get('token', CsrfTokenController::class)->name('token');
Route::get('extend', ExtendSessionController::class)->name('extend');
Expand Down
13 changes: 12 additions & 1 deletion src/Exceptions/AuthenticationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ public function toResponse($request)
{
return $request->expectsJson()
? response()->json(['message' => $this->getMessage()], 401)
: redirect()->route('statamic.cp.login');
: $this->handleRedirect();
}

protected function handleRedirect()
{
if (! config('statamic.cp.auth.enabled', true)) {
return config('statamic.cp.auth.redirect_to')
? redirect()->guest(config('statamic.cp.auth.redirect_to'))
: abort(401);
}

return redirect()->route('statamic.cp.login');
}
}
1 change: 1 addition & 0 deletions src/Http/View/Composers/SessionExpiryComposer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function compose(View $view)
'lifetime' => config('session.lifetime') * 60,
'warnAt' => 60,
'oauth' => $this->oauth(),
'auth' => config('statamic.cp.auth'),
]);
}

Expand Down
37 changes: 37 additions & 0 deletions tests/Feature/AuthenticationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Tests\Feature;

use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class AuthenticationTest extends TestCase
{
#[Test]
public function it_responds_with_a_401_when_requesting_json()
{
$this->getJson('/cp/anything')->assertStatus(401)->assertJson(['message' => 'Unauthenticated.']);
}

#[Test]
public function redirects_to_login_page()
{
$this->get('/cp/anything')->assertRedirect('/cp/auth/login');
}

#[Test]
public function redirects_to_defined_login_page_when_auth_is_disabled()
{
config(['statamic.cp.auth' => ['enabled' => false, 'redirect_to' => '/my-login-page']]);

$this->get('/cp/anything')->assertRedirect('/my-login-page');
}

#[Test]
public function responds_with_401_when_auth_is_disabled_and_no_redirect_is_defined()
{
config(['statamic.cp.auth' => ['enabled' => false]]);

$this->get('/cp/anything')->assertStatus(401);
}
}

0 comments on commit 7ace3c1

Please sign in to comment.