fix(auth): callback iss must equal metadata issuer (honor metadataIssuer override) (#361)
#359 made the metadata `issuer` honor the metadataIssuer override so the 2025-03-26 backcompat scenario is RFC 8414 §3.3-compliant. The authorize callback's `iss` parameter was still derived as `getAuthBaseUrl()+routePrefix`, so when a scenario sets metadataIssuer (bare origin) but keeps a routePrefix, the callback `iss` mismatches the metadata `issuer` and an RFC 9207-conforming client correctly rejects it. Extract `resolveIssuer()` and use it for both the metadata `issuer` and the `'correct'`/`'normalized'` callback `iss` so they always match.
This commit is contained in:
parent
1ff5d88370
commit
5d1b3cea3b
1 changed files with 15 additions and 7 deletions
|
|
@ -127,6 +127,14 @@ export function createAuthServer(
|
|||
registration_endpoint: `${routePrefix}/register`
|
||||
};
|
||||
|
||||
// The issuer identifier this AS publishes — used for both the metadata
|
||||
// `issuer` field and the RFC 9207 callback `iss` parameter, which per
|
||||
// RFC 9207 §2.4 must be identical under simple string comparison.
|
||||
const resolveIssuer = () =>
|
||||
typeof metadataIssuer === 'function'
|
||||
? metadataIssuer()
|
||||
: (metadataIssuer ?? `${getAuthBaseUrl()}${routePrefix}`);
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
|
@ -158,10 +166,7 @@ export function createAuthServer(
|
|||
});
|
||||
|
||||
const metadata: any = {
|
||||
issuer:
|
||||
typeof metadataIssuer === 'function'
|
||||
? metadataIssuer()
|
||||
: (metadataIssuer ?? `${getAuthBaseUrl()}${routePrefix}`),
|
||||
issuer: resolveIssuer(),
|
||||
authorization_endpoint: `${getAuthBaseUrl()}${authRoutes.authorization_endpoint}`,
|
||||
token_endpoint: `${getAuthBaseUrl()}${authRoutes.token_endpoint}`,
|
||||
...(!disableDynamicRegistration && {
|
||||
|
|
@ -274,16 +279,19 @@ export function createAuthServer(
|
|||
redirectUrl.searchParams.set('state', state);
|
||||
}
|
||||
|
||||
// ISS: Include iss parameter in redirect if configured
|
||||
// ISS: Include iss parameter in redirect if configured. The 'correct'
|
||||
// value must equal the metadata `issuer` exactly (RFC 9207 §2.4 simple
|
||||
// string comparison), so honor the same metadataIssuer override the
|
||||
// metadata document does.
|
||||
if (issInRedirect === 'correct') {
|
||||
redirectUrl.searchParams.set('iss', `${getAuthBaseUrl()}${routePrefix}`);
|
||||
redirectUrl.searchParams.set('iss', resolveIssuer());
|
||||
} else if (issInRedirect === 'wrong') {
|
||||
redirectUrl.searchParams.set('iss', 'https://evil.example.com');
|
||||
} else if (issInRedirect === 'normalized') {
|
||||
// Normalization-equivalent variant of the correct issuer: identical
|
||||
// after RFC 3986 scheme-based normalization (trailing slash on an
|
||||
// empty path) but different under simple string comparison.
|
||||
redirectUrl.searchParams.set('iss', `${getAuthBaseUrl()}${routePrefix}/`);
|
||||
redirectUrl.searchParams.set('iss', `${resolveIssuer()}/`);
|
||||
}
|
||||
|
||||
res.redirect(redirectUrl.toString());
|
||||
|
|
|
|||
Loading…
Reference in a new issue