Description
GET/POST /oauth2/logout accepts any server-signed JWT as id_token_hint provided its issuer matches and its audience resolves to a registered client. There is no check that the token is actually an ID token.
An access token issued to an application with no configured default audience carries aud=client_id, since ResolveDefaultAudience falls back to the client id, so it satisfies both conditions. Expiry is intentionally not enforced for id_token_hint per OIDC RP-Initiated Logout, so an expired access token is accepted as well.
The sign-out flow suppresses the End-User confirmation whenever a hint is present, so a party holding any access token for the target client can suppress it. That confirmation is the mitigation for forced logout via cross-site navigation. Not currently exploitable because the default sign-out flow ships with promptOnSignOut: false, but it must be fixed before that mitigation is relied on.
Steps to Reproduce
- Register a confidential client with the
authorization_code grant and no defaultAudience on its access token config.
- Complete an authorization code flow and keep the
access_token.
- Call
GET /oauth2/logout?id_token_hint=<access_token>.
- The request is accepted and the client resolves from the access token's
aud. Setting promptOnSignOut: true on the sign-out flow's SessionSignOutExecutor node shows the confirmation is skipped, where a request with no hint would prompt.
Version
1.0.0
Environment Details (with versions)
No response
Description
GET/POST /oauth2/logoutaccepts any server-signed JWT asid_token_hintprovided its issuer matches and its audience resolves to a registered client. There is no check that the token is actually an ID token.An access token issued to an application with no configured default audience carries
aud=client_id, sinceResolveDefaultAudiencefalls back to the client id, so it satisfies both conditions. Expiry is intentionally not enforced forid_token_hintper OIDC RP-Initiated Logout, so an expired access token is accepted as well.The sign-out flow suppresses the End-User confirmation whenever a hint is present, so a party holding any access token for the target client can suppress it. That confirmation is the mitigation for forced logout via cross-site navigation. Not currently exploitable because the default sign-out flow ships with
promptOnSignOut: false, but it must be fixed before that mitigation is relied on.Steps to Reproduce
authorization_codegrant and nodefaultAudienceon its access token config.access_token.GET /oauth2/logout?id_token_hint=<access_token>.aud. SettingpromptOnSignOut: trueon the sign-out flow'sSessionSignOutExecutornode shows the confirmation is skipped, where a request with no hint would prompt.Version
1.0.0
Environment Details (with versions)
No response