fix: Support WWW-Authenticate scope param for SEP-835 (#983)

Co-authored-by: OtotheA <oscar@otothea.com>
This commit is contained in:
Chip 2025-11-03 09:24:42 -06:00 • committed by GitHub
commit ee9fed28cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 118 additions and 74 deletions

View file

@ -218,38 +218,6 @@ describe('Authorization Handler', () => {
});
});
describe('Scope validation', () => {
it('validates requested scopes against client registered scopes', async () => {
const response = await supertest(app).get('/authorize').query({
client_id: 'valid-client',
redirect_uri: 'https://example.com/callback',
response_type: 'code',
code_challenge: 'challenge123',
code_challenge_method: 'S256',
scope: 'profile email admin' // 'admin' not in client scopes
});
expect(response.status).toBe(302);
const location = new URL(response.header.location);
expect(location.searchParams.get('error')).toBe('invalid_scope');
});
it('accepts valid scopes subset', async () => {
const response = await supertest(app).get('/authorize').query({
client_id: 'valid-client',
redirect_uri: 'https://example.com/callback',
response_type: 'code',
code_challenge: 'challenge123',
code_challenge_method: 'S256',
scope: 'profile' // subset of client scopes
});
expect(response.status).toBe(302);
const location = new URL(response.header.location);
expect(location.searchParams.has('code')).toBe(true);
});
});
describe('Resource parameter validation', () => {
it('propagates resource parameter', async () => {
const mockProviderWithResource = jest.spyOn(mockProvider, 'authorize');

View file

@ -4,7 +4,7 @@ import express from 'express';
import { OAuthServerProvider } from '../provider.js';
import { rateLimit, Options as RateLimitOptions } from 'express-rate-limit';
import { allowedMethods } from '../middleware/allowedMethods.js';
import { InvalidRequestError, InvalidClientError, InvalidScopeError, ServerError, TooManyRequestsError, OAuthError } from '../errors.js';
import { InvalidRequestError, InvalidClientError, ServerError, TooManyRequestsError, OAuthError } from '../errors.js';
export type AuthorizationHandlerOptions = {
provider: OAuthServerProvider;
@ -120,14 +120,6 @@ export function authorizationHandler({ provider, rateLimit: rateLimitConfig }: A
let requestedScopes: string[] = [];
if (scope !== undefined) {
requestedScopes = scope.split(' ');
const allowedScopes = new Set(client.scope?.split(' '));
// Check each requested scope against allowed scopes
for (const scope of requestedScopes) {
if (!allowedScopes.has(scope)) {
throw new InvalidScopeError(`Client was not registered with scope ${scope}`);
}
}
}
// All validation passed, proceed with authorization