From 8f63b57c0cb9a93591e504373bbdfa11a18401a5 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sun, 2 Feb 2025 19:50:54 +0000 Subject: [PATCH] Improved flow for using OAuth2 while logged out. --- VERSION | 2 +- assets/oauth2.js/authorise.js | 8 ++++- assets/oauth2.js/verify.js | 7 ++-- public-legacy/auth/login.php | 4 ++- src/LegacyRoutes.php | 2 +- src/OAuth2/OAuth2ApiRoutes.php | 1 + src/OAuth2/OAuth2WebRoutes.php | 36 +++++++------------- templates/auth/login.twig | 6 ++++ templates/oauth2/login.twig | 62 ---------------------------------- 9 files changed, 35 insertions(+), 93 deletions(-) delete mode 100644 templates/oauth2/login.twig diff --git a/VERSION b/VERSION index ad51826f..8839305d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -20250202 +20250202.1 diff --git a/assets/oauth2.js/authorise.js b/assets/oauth2.js/authorise.js index 7b4f4556..1a61babe 100644 --- a/assets/oauth2.js/authorise.js +++ b/assets/oauth2.js/authorise.js @@ -161,8 +161,14 @@ const MszOAuth2Authorise = async () => { const { body } = await $x.get(`/oauth2/resolve-authorise-app?${resolveParams}`, { authed: true, csrf: true, type: 'json' }); if(!body) throw 'authorisation resolve failed'; - if(typeof body.error === 'string') + if(typeof body.error === 'string') { + if(body.error === 'auth') { + window.location.assign(`/auth/login.php?oauth2=1&redirect=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}`); + return; + } + return translateError(body.error, body); + } const userHeader = new MszOAuth2UserHeader(body.user); header.setElement(userHeader); diff --git a/assets/oauth2.js/verify.js b/assets/oauth2.js/verify.js index 5c5c09fa..5b8ddb2c 100644 --- a/assets/oauth2.js/verify.js +++ b/assets/oauth2.js/verify.js @@ -104,9 +104,10 @@ const MszOAuth2Verify = () => { if(typeof body.error === 'string') { // TODO: nicer errors - if(body.error === 'auth') - alert('You are not logged in.'); - else if(body.error === 'csrf') + if(body.error === 'auth') { + window.location.assign(`/auth/login.php?oauth2=1&redirect=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}`); + return; + } else if(body.error === 'csrf') alert('Request verification failed, please refresh and try again.'); else if(body.error === 'code') alert('This code is not associated with any authorisation request.'); diff --git a/public-legacy/auth/login.php b/public-legacy/auth/login.php index 35c319a0..84bbdb1a 100644 --- a/public-legacy/auth/login.php +++ b/public-legacy/auth/login.php @@ -120,7 +120,7 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) { if($userInfo->hasTOTP) { $tfaToken = $msz->authCtx->tfaSessions->createToken($userInfo); - Tools::redirect($msz->urls->format('auth-two-factor', ['token' => $tfaToken])); + Tools::redirect($msz->urls->format('auth-two-factor', ['token' => $tfaToken, 'redirect' => $loginRedirect])); return; } @@ -149,6 +149,7 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) { } $welcomeMode = !empty($_GET['welcome']); +$oauth2Mode = !empty($_GET['oauth2']); $loginUsername = !empty($_POST['login']['username']) && is_string($_POST['login']['username']) ? $_POST['login']['username'] : ( !empty($_GET['username']) && is_string($_GET['username']) ? $_GET['username'] : '' ); @@ -163,6 +164,7 @@ Template::render('auth.login', [ 'login_can_register' => $canRegisterAccount, 'login_attempts_remaining' => $remainingAttempts, 'login_welcome' => $welcomeMode, + 'login_oauth2' => $oauth2Mode, 'login_private' => [ 'enabled' => $siteIsPrivate, 'message' => $sitePrivateMessage, diff --git a/src/LegacyRoutes.php b/src/LegacyRoutes.php index dfa205f7..1f901915 100644 --- a/src/LegacyRoutes.php +++ b/src/LegacyRoutes.php @@ -26,7 +26,7 @@ class LegacyRoutes implements RouteHandler, UrlSource { $urls->register('auth-reset', '/auth/password.php', ['user' => '']); $urls->register('auth-logout', '/auth/logout.php', ['csrf' => '']); $urls->register('auth-resolve-user', '/auth/login.php', ['resolve' => '1', 'name' => '']); - $urls->register('auth-two-factor', '/auth/twofactor.php', ['token' => '']); + $urls->register('auth-two-factor', '/auth/twofactor.php', ['token' => '', 'redirect' => '']); $urls->register('auth-revert', '/auth/revert.php', ['csrf' => '']); $urls->register('forum-leaderboard', '/forum/leaderboard.php', ['id' => '', 'mode' => '']); diff --git a/src/OAuth2/OAuth2ApiRoutes.php b/src/OAuth2/OAuth2ApiRoutes.php index 15a42654..fe2242a5 100644 --- a/src/OAuth2/OAuth2ApiRoutes.php +++ b/src/OAuth2/OAuth2ApiRoutes.php @@ -48,6 +48,7 @@ final class OAuth2ApiRoutes implements RouteHandler { * }|array{ error: string, error_description: string } */ #[HttpPost('/oauth2/request-authorise')] + #[HttpPost('/oauth2/request-authorize')] public function postRequestAuthorise(HttpResponseBuilder $response, HttpRequest $request): array { $response->setHeader('Cache-Control', 'no-store'); diff --git a/src/OAuth2/OAuth2WebRoutes.php b/src/OAuth2/OAuth2WebRoutes.php index bb2e48db..62909582 100644 --- a/src/OAuth2/OAuth2WebRoutes.php +++ b/src/OAuth2/OAuth2WebRoutes.php @@ -24,12 +24,6 @@ final class OAuth2WebRoutes implements RouteHandler { #[HttpGet('/oauth2/authorise')] #[HttpGet('/oauth2/authorize')] public function getAuthorise(HttpResponseBuilder $response, HttpRequest $request): string { - if(!$this->authInfo->loggedIn) - return Template::renderRaw('oauth2.login', [ - 'login_url' => $this->urls->format('auth-login'), - 'register_url' => $this->urls->format('auth-register'), - ]); - return Template::renderRaw('oauth2.authorise'); } @@ -50,14 +44,14 @@ final class OAuth2WebRoutes implements RouteHandler { // TODO: RATE LIMITING - if(!$this->authInfo->loggedIn) - return ['error' => 'auth']; - if(!CSRF::validate($request->getHeaderLine('X-CSRF-token'))) return ['error' => 'csrf']; $response->setHeader('X-CSRF-Token', CSRF::token()); + if(!$this->authInfo->loggedIn) + return ['error' => 'auth']; + $codeChallengeMethod = 'plain'; if($request->content->hasParam('ccm')) { $codeChallengeMethod = $request->content->getParam('ccm'); @@ -164,14 +158,14 @@ final class OAuth2WebRoutes implements RouteHandler { public function getResolveAuthorise(HttpResponseBuilder $response, HttpRequest $request): array { // TODO: RATE LIMITING - if(!$this->authInfo->loggedIn) - return ['error' => 'auth']; - if(!CSRF::validate($request->getHeaderLine('X-CSRF-token'))) return ['error' => 'csrf']; $response->setHeader('X-CSRF-Token', CSRF::token()); + if(!$this->authInfo->loggedIn) + return ['error' => 'auth']; + try { $appInfo = $this->oauth2Ctx->appsCtx->apps->getAppInfo( clientId: (string)$request->getParam('client'), @@ -235,12 +229,6 @@ final class OAuth2WebRoutes implements RouteHandler { #[HttpGet('/oauth2/verify')] public function getVerify(HttpResponseBuilder $response, HttpRequest $request): string { - if(!$this->authInfo->loggedIn) - return Template::renderRaw('oauth2.login', [ - 'login_url' => $this->urls->format('auth-login'), - 'register_url' => $this->urls->format('auth-register'), - ]); - return Template::renderRaw('oauth2.verify'); } @@ -260,14 +248,14 @@ final class OAuth2WebRoutes implements RouteHandler { // TODO: RATE LIMITING - if(!$this->authInfo->loggedIn) - return ['error' => 'auth']; - if(!CSRF::validate($request->getHeaderLine('X-CSRF-token'))) return ['error' => 'csrf']; $response->setHeader('X-CSRF-Token', CSRF::token()); + if(!$this->authInfo->loggedIn) + return ['error' => 'auth']; + $approve = (string)$request->content->getParam('approve'); if(!in_array($approve, ['yes', 'no'])) return ['error' => 'invalid']; @@ -356,14 +344,14 @@ final class OAuth2WebRoutes implements RouteHandler { public function getResolveVerify(HttpResponseBuilder $response, HttpRequest $request) { // TODO: RATE LIMITING - if(!$this->authInfo->loggedIn) - return ['error' => 'auth']; - if(!CSRF::validate($request->getHeaderLine('X-CSRF-token'))) return ['error' => 'csrf']; $response->setHeader('X-CSRF-Token', CSRF::token()); + if(!$this->authInfo->loggedIn) + return ['error' => 'auth']; + try { $deviceInfo = $this->oauth2Ctx->devices->getDeviceInfo(userCode: (string)$request->getParam('code')); } catch(RuntimeException $ex) { diff --git a/templates/auth/login.twig b/templates/auth/login.twig index 17789ea0..b749b4a5 100644 --- a/templates/auth/login.twig +++ b/templates/auth/login.twig @@ -32,6 +32,12 @@

Welcome to Flashii, you may now log in!

+ {% elseif login_oauth2 %} +
+
+

You must be logged in to authorise applications.

+
+
{% endif %}