11import { createSolidTokenVerifier } from '@solid/access-token-verifier' ;
2- import {
3- BadRequestHttpError ,
4- ForbiddenHttpError ,
5- InternalServerError ,
6- joinUrl ,
7- KeyValueStorage
8- } from '@solid/community-server' ;
2+ import { BadRequestHttpError , ForbiddenHttpError , InternalServerError , KeyValueStorage } from '@solid/community-server' ;
93import { getLoggerFor } from 'global-logger-factory' ;
10- import { createRemoteJWKSet , decodeJwt , JWTPayload , jwtVerify } from 'jose' ;
4+ import { decodeJwt , jwtVerify } from 'jose' ;
115import { AccessToken } from '../../tokens/AccessToken' ;
126import { UMA_SCOPES } from '../../ucp/util/Vocabularies' ;
7+ import { getJwks } from '../../util/JwtUtil' ;
138import { reType } from '../../util/ReType' ;
149import { Permission } from '../../views/Permission' ;
1510import { ACCESS , CLIENTID , WEBID } from '../Claims' ;
@@ -21,19 +16,16 @@ import { Verifier } from './Verifier';
2116/**
2217 * A Verifier for OIDC Tokens.
2318 *
24- * The `allowedIssuers` list can be used to only allow tokens from these issuers.
25- * Default is an empty list, which allows all issuers.
19+ * To only allow tokens from certain issuers, set `verifyOptions` to { issuer: [ 'http://example.com/' ] }.
2620 */
2721export class OidcVerifier implements Verifier {
2822 protected readonly logger = getLoggerFor ( this ) ;
2923
3024 private readonly verifyToken = createSolidTokenVerifier ( ) ;
3125
3226 public constructor (
33- protected readonly baseUrl : string ,
3427 protected readonly derivationStore : KeyValueStorage < string , string > ,
35- protected readonly allowedIssuers : string [ ] = [ ] ,
36- protected readonly verifyOptions : Record < string , unknown > = { } ,
28+ protected readonly verifyOptions : Record < string , unknown > = { } , // JWTVerifyOptions
3729 ) { }
3830
3931 /** @inheritdoc */
@@ -46,11 +38,10 @@ export class OidcVerifier implements Verifier {
4638 // We first need to determine if this is a Solid OIDC token or a standard one
4739 const unsafeDecoded = decodeJwt ( credential . token ) ;
4840 const isSolidToken = ( unsafeDecoded . aud === 'solid' ||
49- ( Array . isArray ( unsafeDecoded . aud ) && unsafeDecoded . aud . includes ( 'solid' ) ) )
41+ ( Array . isArray ( unsafeDecoded . aud ) && unsafeDecoded . aud . includes ( 'solid' ) ) )
5042 && typeof unsafeDecoded . webid === 'string' ;
5143
5244 try {
53- this . validateToken ( unsafeDecoded ) ;
5445 if ( isSolidToken ) {
5546 return await this . verifySolidToken ( credential . token ) ;
5647 } else {
@@ -64,18 +55,13 @@ export class OidcVerifier implements Verifier {
6455 }
6556 }
6657
67- protected validateToken ( payload : JWTPayload ) : void {
68- // TODO: disable audience check for now, need to investigate required values further
69- // if (payload.aud !== this.baseUrl && !(Array.isArray(payload.aud) && payload.aud.includes(this.baseUrl))) {
70- // throw new BadRequestHttpError('This server is not valid audience for the token');
71- // }
72- if ( ! payload . iss || this . allowedIssuers . length > 0 && ! this . allowedIssuers . includes ( payload . iss ) ) {
73- throw new BadRequestHttpError ( 'Unsupported issuer' ) ;
74- }
75- }
76-
7758 protected async verifySolidToken ( token : string ) : Promise < { [ WEBID ] : string , [ CLIENTID ] ?: string } > {
7859 const claims = await this . verifyToken ( `Bearer ${ token } ` ) ;
60+ const issuers = this . verifyOptions . issuer ;
61+ const allowedIssuers = issuers !== undefined && ( typeof issuers === 'string' ? [ issuers ] : issuers as string [ ] ) ;
62+ if ( ! claims . iss || ( allowedIssuers && ! allowedIssuers . includes ( claims . iss ) ) ) {
63+ throw new BadRequestHttpError ( 'Unsupported issuer' ) ;
64+ }
7965 // Depends on the spec version which field to use
8066 const clientId = ( claims as { azp ?: string } ) . azp ?? claims . client_id ;
8167
@@ -91,16 +77,7 @@ export class OidcVerifier implements Verifier {
9177
9278 protected async verifyStandardToken ( token : string , format : string , issuer : string ) :
9379 Promise < { [ WEBID ] ?: string , [ CLIENTID ] ?: string , [ ACCESS ] ?: Permission [ ] } > {
94- const configUrl = joinUrl ( issuer , '/.well-known/openid-configuration' ) ;
95- const configResponse = await fetch ( configUrl ) ;
96- if ( configResponse . status !== 200 ) {
97- throw new BadRequestHttpError ( `Unable to access ${ configUrl } ` ) ;
98- }
99- const config = await configResponse . json ( ) as { jwks_uri ?: string } ;
100- if ( ! config . jwks_uri ) {
101- throw new BadRequestHttpError ( `Missing jwks_uri from ${ configUrl } ` ) ;
102- }
103- const jwkSet = createRemoteJWKSet ( new URL ( config . jwks_uri ) ) ;
80+ const jwkSet = await getJwks ( issuer ) ;
10481 const decoded = await jwtVerify ( token , jwkSet , this . verifyOptions ) ;
10582
10683 if ( format === OIDC ) {
0 commit comments