From 4d69e92a32ddb066af44d0f72f2c4b6cc166bf32 Mon Sep 17 00:00:00 2001 From: Melvin Carvalho Date: Sun, 4 Oct 2026 15:00:50 +0200 Subject: [PATCH] Reuse login redirect_uri in token request (fixes #14) The token request dropped the query string from redirect_uri, so it didn't match the one used for registration and authorization, and the IdP rejected the code exchange with invalid_grant. Store the exact redirect_uri at login and send it back unchanged. --- solid-oidc.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/solid-oidc.js b/solid-oidc.js index be46edb..5c51443 100644 --- a/solid-oidc.js +++ b/solid-oidc.js @@ -493,6 +493,10 @@ export class Session extends EventTarget { const csrfToken = crypto.randomUUID() sessionStorage.setItem('solid_oidc_csrf', csrfToken) + // The token request must repeat the exact redirect_uri used here + // (RFC 6749 ยง4.1.3), query string included + sessionStorage.setItem('solid_oidc_redirect_uri', sanitizedRedirect) + // Build authorization URL const authUrl = new URL(config.authorization_endpoint) authUrl.searchParams.set('response_type', 'code') @@ -542,6 +546,7 @@ export class Session extends EventTarget { const tokenEndpoint = sessionStorage.getItem('solid_oidc_token_endpoint') const jwksUri = sessionStorage.getItem('solid_oidc_jwks_uri') const clientId = this.clientId || sessionStorage.getItem('solid_oidc_client_id') + const redirectUri = sessionStorage.getItem('solid_oidc_redirect_uri') || url.origin + url.pathname + url.search if (!pkceVerifier || !tokenEndpoint || !clientId) { throw new Error('Missing session data') @@ -559,7 +564,7 @@ export class Session extends EventTarget { grant_type: 'authorization_code', code, code_verifier: pkceVerifier, - redirect_uri: url.origin + url.pathname, + redirect_uri: redirectUri, client_id: clientId }, keyPair) @@ -588,6 +593,7 @@ export class Session extends EventTarget { sessionStorage.removeItem('solid_oidc_client_id') sessionStorage.removeItem('solid_oidc_pkce_verifier') sessionStorage.removeItem('solid_oidc_csrf') + sessionStorage.removeItem('solid_oidc_redirect_uri') // Update session state await this._setTokens({ ...tokens, dpop_key_pair: keyPair })