Skip to content

Commit

Permalink
When authn error occurs, send 'invalid-request'
Browse files Browse the repository at this point in the history
This error status was previously not supported. It is now. The uncaught
errors are caught, and the invalid-request is sent back to the JS app.

That in turn displays the user facing error page.
  • Loading branch information
MKodde committed Sep 2, 2024
1 parent 8022610 commit 136a243
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 25 deletions.
3 changes: 3 additions & 0 deletions assets/typescript/AuthenticationPageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ export class AuthenticationPageService {
case 'challenge-expired':
this.switchToChallengeHasExpired();
break;
case 'invalid-request':
this.switchToNotificationFailed();
break;
case 'needs-refresh':
this.reloadPage();
break;
Expand Down
8 changes: 8 additions & 0 deletions assets/typescript/__test__/AuthenticationPageService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ describe('AuthenticationPageService', () => {
successCallback('challenge-expired');
expect(spy).toBeCalled();
});
it('Should handle authn error (invalid request)', () => {
if (!successCallback || !errorCallback) {
throw new Error('Should have started status request');
}
const spy = jest.spyOn(context.authenticationPageService, 'switchToNotificationFailed');
successCallback('invalid-request');
expect(spy).toBeCalled();
});

it('Should handle challenge expired', () => {
if (!successCallback || !errorCallback) {
Expand Down
62 changes: 37 additions & 25 deletions src/Controller/AuthenticationStatusController.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,41 +46,53 @@ public function __construct(
#[Route(path: '/authentication/status', name: 'app_identity_authentication_status', methods: ['GET'])]
public function __invoke(): JsonResponse
{
$nameId = $this->authenticationService->getNameId();
$sari = $this->stateHandler->getRequestId();
$logger = WithContextLogger::from($this->logger, ['nameId' => $nameId, 'sari' => $sari]);
$logger->info('Request for authentication status');

if (!$this->authenticationService->authenticationRequired()) {
$logger->error('There is no pending authentication request from SP');
return $this->refreshAuthenticationPage();
}

$isAuthenticated = $this->tiqrService->isAuthenticated();

if ($isAuthenticated) {
$logger->info('Send json response is authenticated');

return $this->refreshAuthenticationPage();
}

if ($this->authenticationChallengeIsExpired()) {
return $this->timeoutNeedsManualRetry();
try {
$nameId = $this->authenticationService->getNameId();
$sari = $this->stateHandler->getRequestId();
$logger = WithContextLogger::from($this->logger, ['nameId' => $nameId, 'sari' => $sari]);
$logger->info('Request for authentication status');

if (!$this->authenticationService->authenticationRequired()) {
$logger->error('There is no pending authentication request from SP');
return $this->refreshAuthenticationPage();
}

$isAuthenticated = $this->tiqrService->isAuthenticated();

if ($isAuthenticated) {
$logger->info('Send json response is authenticated');

return $this->refreshAuthenticationPage();
}

if ($this->authenticationChallengeIsExpired()) {
return $this->timeoutNeedsManualRetry();
}

$logger->info('Send json response is not authenticated');

return $this->scheduleNextPollOnAuthenticationPage();
} catch (Exception $e) {
$this->logger->error(
sprintf(
'An unexpected authentication error occurred. Responding with "invalid-request", '.
'original exception message: "%s"',
$e->getMessage()
)
);
return $this->generateAuthenticationStatusResponse('invalid-request');
}

$logger->info('Send json response is not authenticated');

return $this->scheduleNextPollOnAuthenticationPage();
}

/**
* Generate a status response for authentication.html.
*
* The javascript in the authentication page expects one of three statuses:
* The javascript in the authentication page expects one of four statuses:
*
* - pending: waiting for user action, schedule next poll
* - needs-refresh: refresh the page (the /authentication page will handle the success or error)
* - challenge-expired: Message user challenge is expired, let the user give the option to retry.
* - invalid-request: There was a state issue, or another reason why authentication failed
*
* @return JsonResponse
*/
Expand Down

0 comments on commit 136a243

Please sign in to comment.