fix(auth): block OIDC token exchange without PKCE verifier

Throw a session-expired error when the PKCE verifier is missing and keep
the settings component mount redirect-compatible.
This commit is contained in:
Andras Bacsai 2026-06-15 17:05:52 +02:00
parent c656892738
commit a1dbde3412
3 changed files with 11 additions and 10 deletions

View file

@ -209,9 +209,11 @@ public function getAccessTokenResponse($code)
$fields = $this->getTokenFields($code);
if ($this->getConfig()->usePkce) {
$verifier = $this->pullOidcFlowValue($this->verifierSessionKey((string) $this->request->input('state')));
if ($verifier !== null) {
$fields['code_verifier'] = $verifier;
if ($verifier === null) {
throw new OidcException('OIDC login session expired. Please try again.');
}
$fields['code_verifier'] = $verifier;
}
$response = $this->getHttpClient()->post($this->getTokenUrl(), [

View file

@ -5,6 +5,7 @@
use App\Models\InstanceSettings;
use App\Models\OauthSetting;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\RedirectResponse;
use Illuminate\Validation\ValidationException;
use Livewire\Component;
@ -55,7 +56,7 @@ private function validationRules(?string $provider = null): array
return $rules;
}
public function mount(?string $provider = null)
public function mount(?string $provider = null): ?RedirectResponse
{
if (! isInstanceAdmin()) {
return redirect()->route('home');
@ -73,6 +74,8 @@ public function mount(?string $provider = null)
if ($this->selectedProvider !== null && ! array_key_exists($this->selectedProvider, $this->oauth_settings_map)) {
abort(404);
}
return null;
}
private function updateOauthSettings(?string $provider = null): void

View file

@ -1,5 +1,6 @@
<?php
use App\Auth\Oidc\Exceptions\OidcException;
use App\Auth\Oidc\OidcConfig;
use App\Auth\Oidc\OidcDiscoveryDocument;
use App\Auth\Oidc\OidcDiscoveryService;
@ -128,7 +129,7 @@ function oidc_provider(Request $request): TestOidcProviderWithExposedAuthUrl
->and($session->has('oidc.code_verifier.state-value'))->toBeFalse();
});
it('does not send an expired oidc pkce verifier during token exchange', function () {
it('throws a session expired error for an expired oidc pkce verifier during token exchange', function () {
$session = oidc_provider_session();
$session->put('oidc.code_verifier.state-value', [
'value' => 'expired-verifier',
@ -144,9 +145,4 @@ function oidc_provider(Request $request): TestOidcProviderWithExposedAuthUrl
$provider->setHttpClient(new Client(['handler' => $handler]));
$provider->getAccessTokenResponse('authorization-code');
parse_str((string) $history[0]['request']->getBody(), $tokenRequestFields);
expect($tokenRequestFields)->not->toHaveKey('code_verifier')
->and($session->has('oidc.code_verifier.state-value'))->toBeFalse();
});
})->throws(OidcException::class, 'OIDC login session expired. Please try again.');