1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-12-04 05:22:38 +03:00
Files
bookstack/app/Access/Controllers/OidcController.php
Dan Brown adfac3e30e OIDC: Updated state handling to prevent loss from other requests
Which was occuring in chrome, where background requests to the PWA
manifest, or opensearch, endpoint caused OIDC to fail due to lost state
since it was only flashed to the session.
This persists it with a manual TTL.

Added tests to cover.
Manually tested against Azure.
For #5929
2025-12-03 13:34:00 +00:00

76 lines
2.1 KiB
PHP

<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\Oidc\OidcException;
use BookStack\Access\Oidc\OidcService;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class OidcController extends Controller
{
public function __construct(
protected OidcService $oidcService
) {
$this->middleware('guard:oidc');
}
/**
* Start the authorization login flow via OIDC.
*/
public function login()
{
try {
$loginDetails = $this->oidcService->login();
} catch (OidcException $exception) {
$this->showErrorNotification($exception->getMessage());
return redirect('/login');
}
session()->put('oidc_state', time() . ':' . $loginDetails['state']);
return redirect($loginDetails['url']);
}
/**
* Authorization flow redirect callback.
* Processes authorization response from the OIDC Authorization Server.
*/
public function callback(Request $request)
{
$responseState = $request->query('state');
$splitState = explode(':', session()->pull('oidc_state', ':'), 2);
if (count($splitState) !== 2) {
$splitState = [null, null];
}
[$storedStateTime, $storedState] = $splitState;
$threeMinutesAgo = time() - 3 * 60;
if (!$storedState || $storedState !== $responseState || intval($storedStateTime) < $threeMinutesAgo) {
$this->showErrorNotification(trans('errors.oidc_fail_authed', ['system' => config('oidc.name')]));
return redirect('/login');
}
try {
$this->oidcService->processAuthorizeResponse($request->query('code'));
} catch (OidcException $oidcException) {
$this->showErrorNotification($oidcException->getMessage());
return redirect('/login');
}
return redirect()->intended();
}
/**
* Log the user out, then start the OIDC RP-initiated logout process.
*/
public function logout()
{
return redirect($this->oidcService->logout());
}
}