Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion resources/js/components/global-header/UserDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Avatar, Button, DropdownHeader, Badge, Dropdown, DropdownMenu, Dropdown
import useStatamicPageProps from '@/composables/page-props.js';

const { supportUrl } = useStatamicPageProps();
const logoutUrl = `${cp_url('auth/logout')}?redirect=${cp_url('/')}`;
const logoutUrl = `${cp_url('auth/logout')}?redirect=${cp_url('auth/login')}`;
const user = Statamic.user;
const isImpersonating = computed((() => user.is_impersonating));
</script>
Expand Down
9 changes: 4 additions & 5 deletions resources/js/pages/auth/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const props = defineProps([
'passkeyVerifyUrl',
'oauthEnabled',
'providers',
'referer',
'submitUrl',
'forgotPasswordUrl',
])
Expand All @@ -42,11 +41,11 @@ const submit = () => {
errors.value = {};
},
onSuccess: (page) => {
if (page.component === 'auth/two-factor/Challenge') {
return;
}
if (page.component === 'auth/two-factor/Challenge') {
return;
}

window.location.href = props.referer;
window.location.href = page.url;
},
onError: () => processing.value = false
});
Expand Down
3 changes: 1 addition & 2 deletions resources/js/pages/auth/Unauthorized.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import Head from '@/pages/layout/Head.vue';
import Outside from '@/pages/layout/Outside.vue';
import { AuthCard, Button } from '@ui';
import { Link } from '@inertiajs/vue3';

defineOptions({ layout: Outside });

Expand All @@ -19,7 +18,7 @@ defineProps(['isLoggedIn', 'loginUrl', 'logoutUrl']);
>
<div class="flex justify-center">
<Button
:as="Link"
as="a"
variant="primary"
:href="isLoggedIn ? logoutUrl : loginUrl"
class="w-full"
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptions/AuthenticationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ protected function handleRedirect()
: abort(401);
}

return redirect()->route('statamic.cp.login');
return redirect()->guest(route('statamic.cp.login'));
}
}
15 changes: 1 addition & 14 deletions src/Http/Controllers/CP/Auth/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Statamic\Http\Middleware\CP\RedirectIfAuthorized;
use Statamic\OAuth\Provider;
use Statamic\Statamic;
use Statamic\Support\Str;

use function Statamic\trans as __;

Expand Down Expand Up @@ -43,7 +42,6 @@ public function showLoginForm(Request $request)
'oauthEnabled' => $oauthEnabled,
'emailLoginEnabled' => $emailLoginEnabled,
'providers' => $oauthEnabled ? $this->oauthProviders() : [],
'referer' => $this->getReferrer($request),
'forgotPasswordUrl' => cp_route('password.request'),
'submitUrl' => cp_route('login'),
'passkeyOptionsUrl' => cp_route('passkeys.auth.options'),
Expand Down Expand Up @@ -107,11 +105,7 @@ protected function fireFailedEvent($request, $user = null)

public function redirectPath()
{
$cp = cp_route('index');
$referer = request('referer');
$referredFromCp = Str::startsWith($referer, $cp) && ! Str::startsWith($referer, $cp.'/auth/');

return $referredFromCp ? $referer : $cp;
return cp_route('index');
}

protected function authenticated(Request $request, $user)
Expand Down Expand Up @@ -144,13 +138,6 @@ public function logout(Request $request)
return redirect(URL::isExternalToApplication($redirect) ? '/' : $redirect);
}

protected function getReferrer()
{
$referrer = url()->previous();

return $referrer === cp_route('unauthorized') ? cp_route('index') : $referrer;
}

public function username()
{
return 'email';
Expand Down
11 changes: 2 additions & 9 deletions src/Http/Controllers/CP/Auth/PasskeyLoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@

namespace Statamic\Http\Controllers\CP\Auth;

use Illuminate\Http\Request;
use Statamic\Facades\URL;
use Statamic\Http\Controllers\User\PasskeyLoginController as Controller;
use Statamic\Support\Str;

class PasskeyLoginController extends Controller
{
protected function successRedirectUrl(Request $request): string
protected function defaultRedirectUrl(): string
{
$referer = $request->input('referer');

return Str::contains($referer, '/'.config('statamic.cp.route')) && ! URL::isExternalToApplication($referer)
? $referer
: cp_route('index');
return cp_route('index');
}
}
10 changes: 2 additions & 8 deletions src/Http/Controllers/CP/Auth/TwoFactorChallengeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

namespace Statamic\Http\Controllers\CP\Auth;

use Illuminate\Http\Request;
use Statamic\Http\Controllers\TwoFactorChallengeController as Controller;
use Statamic\Http\Middleware\CP\HandleInertiaRequests;
use Statamic\Http\Middleware\CP\RedirectIfAuthorized;
use Statamic\Support\Str;

class TwoFactorChallengeController extends Controller
{
Expand All @@ -22,13 +20,9 @@ protected function formAction()
return cp_route('two-factor-challenge');
}

protected function redirectPath(Request $request)
protected function defaultRedirectPath(): string
{
$cp = cp_route('index');
$referer = $request->input('referer');
$referredFromCp = Str::startsWith($referer, $cp) && ! Str::startsWith($referer, $cp.'/auth/');

return $referredFromCp ? $referer : $cp;
return cp_route('index');
}

protected function failedRedirectPath()
Expand Down
6 changes: 3 additions & 3 deletions src/Http/Controllers/CP/Auth/TwoFactorSetupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ public function __construct(Request $request)
protected function redirectPath()
{
$cp = cp_route('index');
$referer = request('referer');
$referredFromCp = Str::startsWith($referer, $cp) && ! Str::startsWith($referer, $cp.'/auth/');
$intended = redirect()->getIntendedUrl();
$isCpUrl = $intended && Str::startsWith($intended, $cp) && ! Str::startsWith($intended, $cp.'/auth/');

return $referredFromCp ? $referer : $cp;
return $isCpUrl ? $intended : $cp;
}

protected function routes($user): array
Expand Down
14 changes: 4 additions & 10 deletions src/Http/Controllers/Concerns/HandlesLogins.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,15 @@ protected function throwFailedAuthenticationException(Request $request)

protected function twoFactorChallengeResponse(Request $request, User $user)
{
$request->session()->forget('login.redirect');

$session = [
$request->session()->put([
'login.id' => $user->getKey(),
'login.remember' => $request->boolean('remember'),
];
]);

if ($redirect = $request->input('_redirect')) {
if (! URL::isExternalToApplication($redirect)) {
$session['login.redirect'] = $redirect;
}
if (($redirect = $request->input('_redirect')) && ! URL::isExternalToApplication($redirect)) {
redirect()->setIntendedUrl($redirect);
}

$request->session()->put($session);

TwoFactorAuthenticationChallenged::dispatch($user);

return $request->wantsJson()
Expand Down
23 changes: 12 additions & 11 deletions src/Http/Controllers/TwoFactorChallengeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ public function store(TwoFactorChallengeRequest $request)

$request->session()->regenerate();

$redirect = $this->redirectPath($request);

if ($request->inertia() || $request->expectsJson()) {
return $request->inertia()
? Inertia::location($this->redirectPath($request))
? Inertia::location($redirect)
: response('Authenticated');
}

return redirect()->intended($this->redirectPath($request));
return redirect($redirect);
}

protected function sendFailedResponse(TwoFactorChallengeRequest $request)
Expand All @@ -85,18 +87,17 @@ protected function formAction()

protected function redirectPath(Request $request)
{
if ($redirect = $request->input('_redirect')) {
if (! URL::isExternalToApplication($redirect)) {
return $redirect;
}
}
$intended = $request->session()->pull('url.intended', $this->defaultRedirectPath());

if ($redirect = $request->session()->pull('login.redirect')) {
if (! URL::isExternalToApplication($redirect)) {
return $redirect;
}
if (($redirect = $request->input('_redirect')) && ! URL::isExternalToApplication($redirect)) {
return $redirect;
}

return $intended;
}

protected function defaultRedirectPath(): string
{
return route('statamic.site');
}

Expand Down
14 changes: 3 additions & 11 deletions src/Http/Controllers/TwoFactorSetupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,11 @@ public function __invoke(Request $request)

protected function redirectPath()
{
if ($redirect = request('redirect')) {
if (! URL::isExternalToApplication($redirect)) {
return $redirect;
}
if (($redirect = request('redirect')) && ! URL::isExternalToApplication($redirect)) {
return $redirect;
}

if ($redirect = session()->get('login.redirect')) {
if (! URL::isExternalToApplication($redirect)) {
return $redirect;
}
}

return route('statamic.site');
return redirect()->getIntendedUrl() ?? route('statamic.site');
}

protected function routes($user): array
Expand Down
21 changes: 10 additions & 11 deletions src/Http/Controllers/User/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,20 @@ public function login(UserLoginRequest $request)
return $this->twoFactorChallengeResponse($request, $user);
}

$redirect = $request->input('_redirect');
$redirect = $redirect && ! URL::isExternalToApplication($redirect) ? $redirect : null;

// If 2FA setup is required, stash the redirect so the setup flow can use it after completion.
if (TwoFactor::enabled() && $user->isTwoFactorAuthenticationRequired() && ! $user->hasEnabledTwoFactorAuthentication()) {
$request->session()->forget('login.redirect');

if ($redirect) {
$request->session()->put('login.redirect', $redirect);
}
// An explicit form redirect overrides any URL stashed by the auth middleware.
if (($redirect = $request->input('_redirect')) && ! URL::isExternalToApplication($redirect)) {
redirect()->setIntendedUrl($redirect);
}

$this->authenticate($request, $user);

return redirect($redirect ?? route('statamic.site'))->withSuccess(__('Login successful.'));
// Preserve the intended URL for the setup flow to consume after the user completes setup.
if (TwoFactor::enabled() && $user->isTwoFactorAuthenticationRequired() && ! $user->hasEnabledTwoFactorAuthentication()) {
return redirect(redirect()->getIntendedUrl() ?? route('statamic.site'))
->withSuccess(__('Login successful.'));
}

return redirect()->intended(route('statamic.site'))->withSuccess(__('Login successful.'));
}

private function checkPasskeyEnforcement(Request $request)
Expand Down
11 changes: 9 additions & 2 deletions src/Http/Controllers/User/PasskeyLoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,15 @@ protected function authenticate(UserContract $user): void

protected function successRedirectUrl(Request $request): string
{
$redirect = $request->input('redirect', '/');
if (($redirect = $request->input('redirect')) && ! URL::isExternalToApplication($redirect)) {
return $redirect;
}

return URL::isExternalToApplication($redirect) ? '/' : $redirect;
return $request->session()->pull('url.intended', $this->defaultRedirectUrl());
}

protected function defaultRedirectUrl(): string
{
return '/';
}
}
14 changes: 3 additions & 11 deletions src/Http/Controllers/User/TwoFactorAuthenticationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,11 @@ private function formSuccessRedirect(Request $request, string $message, string $
{
$successKey = "{$formName}.success";

if ($redirect = $request->input('_redirect')) {
if (! URL::isExternalToApplication($redirect)) {
return redirect($redirect)->with($successKey, $message);
}
}

if ($loginRedirect = $request->session()->pull('login.redirect')) {
if (! URL::isExternalToApplication($loginRedirect)) {
return redirect($loginRedirect)->with($successKey, $message);
}
if (($redirect = $request->input('_redirect')) && ! URL::isExternalToApplication($redirect)) {
return redirect($redirect)->with($successKey, $message);
}

return back()->with($successKey, $message);
return redirect()->intended(back()->getTargetUrl())->with($successKey, $message);
}

protected function confirmUrl()
Expand Down
7 changes: 2 additions & 5 deletions src/Http/Middleware/CP/RedirectIfTwoFactorSetupIncomplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Statamic\Http\Middleware\CP;

use Illuminate\Http\Request;
use Statamic\Http\Middleware\RedirectIfTwoFactorSetupIncomplete as Middleware;

class RedirectIfTwoFactorSetupIncomplete extends Middleware
Expand All @@ -12,10 +11,8 @@ protected function redirectRoute(): string
return 'statamic.cp.two-factor-setup';
}

protected function redirectUrl(Request $request): string
protected function redirectUrl(): string
{
return route($this->redirectRoute(), [
'referer' => $request->fullUrl(),
]);
return route($this->redirectRoute());
}
}
14 changes: 5 additions & 9 deletions src/Http/Middleware/RedirectIfTwoFactorSetupIncomplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public function handle(Request $request, Closure $next)
app(EnableTwoFactorAuthentication::class)($user);
}

return redirect($this->redirectUrl($request));
redirect()->setIntendedUrl($request->fullUrl());

return redirect($this->redirectUrl());
}

return $next($request);
Expand All @@ -41,15 +43,9 @@ protected function isSetupUrl(Request $request): bool
return $currentPath === $customPath;
}

protected function redirectUrl(Request $request): string
protected function redirectUrl(): string
{
if ($url = config('statamic.users.two_factor_setup_url')) {
return $url;
}

return route($this->redirectRoute(), [
'referer' => $request->fullUrl(),
]);
return config('statamic.users.two_factor_setup_url') ?? route($this->redirectRoute());
}

protected function redirectRoute(): string
Expand Down
Loading
Loading