Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.x] Ability to disable CP authentication #8960

Merged
merged 25 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e5e4a73
Introduce new config setting
duncanmcclean Feb 27, 2023
895bbcf
Only register login/reset password routes when auth is enabled
duncanmcclean Feb 27, 2023
3b0249d
`abort(401)` when CP Auth is disabled
duncanmcclean Feb 27, 2023
546ed77
Add test to ensure front-end login form still works
duncanmcclean Feb 27, 2023
66abbd1
Apply StyleCI changes
duncanmcclean Feb 27, 2023
0caa8cf
Merge branch '3.4' into feature/disable-login-and-reset-password-pages
duncanmcclean Apr 25, 2023
638e304
StyleCI fixes
duncanmcclean Apr 25, 2023
977f830
Merge branch '4.x' into feature/disable-login-and-reset-password-pages
edalzell May 20, 2023
0b2bd55
Merge branch '4.x' into pr/7617
duncanmcclean Nov 9, 2023
fc66e42
Pint
duncanmcclean Nov 9, 2023
8bffc14
Move logout route out of if statement
duncanmcclean Nov 9, 2023
e656efc
Ensure users can register via user:register_form tag when CP auth is …
duncanmcclean Nov 9, 2023
029ac6c
Ensure users can reset password via tags when CP auth is disabled
duncanmcclean Nov 9, 2023
80ccbf5
Allow specifying a redirect URL for when authentication is disabled
duncanmcclean Nov 9, 2023
b54cb0a
Reference updated config key
duncanmcclean Feb 24, 2024
e39db24
Merge branch '4.x' into pr/7617
duncanmcclean Feb 24, 2024
bc10aa2
Make sure `intended` is set
edalzell Apr 21, 2024
4711a50
use the helper instead
duncanmcclean Apr 22, 2024
3a3c403
Merge remote-tracking branch 'origin/5.x' into pr/7617
duncanmcclean May 13, 2024
54a3e83
Redirect to login page after session expires
duncanmcclean May 13, 2024
1f2fc1b
Merge branch '5.x' into pr/7617
jasonvarga Jun 27, 2024
047c97d
Dont redirect at zero ...
jasonvarga Jun 27, 2024
a5198ed
these tests dont really prove anything
jasonvarga Jun 27, 2024
d402365
words
jasonvarga Jun 27, 2024
710a191
add tests
jasonvarga Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
Loading