diff --git a/packages/client/lib/__tests__/SdJwt.spec.ts b/packages/client/lib/__tests__/SdJwt.spec.ts index 3d58e94a..1f1b6a38 100644 --- a/packages/client/lib/__tests__/SdJwt.spec.ts +++ b/packages/client/lib/__tests__/SdJwt.spec.ts @@ -10,6 +10,7 @@ import nock from 'nock'; import { OpenID4VCIClientV1_0_13 } from '..'; import { createAccessTokenResponse, IssuerMetadataBuilderV1_13, VcIssuerBuilder } from '../../../issuer'; +import { AuthorizationServerMetadataBuilder } from '../../../issuer/lib/builder/AuthorizationServerMetadataBuilder' export const UNIT_TEST_TIMEOUT = 30000; @@ -27,8 +28,19 @@ const issuerMetadata = new IssuerMetadataBuilderV1_13() } as CredentialConfigurationSupportedV1_0_13) .build(); +const authorizationServerMetadata = new AuthorizationServerMetadataBuilder() + .withIssuer(issuerMetadata.issuer) + .withCredentialEndpoint(issuerMetadata.credential_endpoint) + .withTokenEndpoint(issuerMetadata.token_endpoint) + .withAuthorizationEndpoint('https://token-endpoint.example.com/authorize') + .withTokenEndpointAuthMethodsSupported(['none', 'client_secret_basic', 'client_secret_jwt', 'client_secret_post']) + .withResponseTypesSupported(['code', 'token', 'id_token']) + .withScopesSupported(['openid', 'abcdef']) + .build(); + const vcIssuer = new VcIssuerBuilder() .withIssuerMetadata(issuerMetadata) + .withAuthorizationMetadata(authorizationServerMetadata) .withInMemoryCNonceState() .withInMemoryCredentialOfferState() .withInMemoryCredentialOfferURIState() diff --git a/packages/issuer-rest/lib/OID4VCIServer.ts b/packages/issuer-rest/lib/OID4VCIServer.ts index f40dfeb1..d8d2cd0f 100644 --- a/packages/issuer-rest/lib/OID4VCIServer.ts +++ b/packages/issuer-rest/lib/OID4VCIServer.ts @@ -17,7 +17,7 @@ import { getCredentialEndpoint, getCredentialOfferEndpoint, getIssueStatusEndpoint, - getMetadataEndpoint, + getMetadataEndpoints, pushedAuthorizationEndpoint, } from './oid4vci-api-functions' @@ -116,7 +116,7 @@ export class OID4VCIServer { this._issuer = opts?.issuer ? opts.issuer : buildVCIFromEnvironment() pushedAuthorizationEndpoint(this.router, this.issuer, this.authRequestsData) - getMetadataEndpoint(this.router, this.issuer) + getMetadataEndpoints(this.router, this.issuer) if (opts?.endpointOpts?.createCredentialOfferOpts?.enabled !== false || process.env.CREDENTIAL_OFFER_ENDPOINT_EBALBED === 'true') { createCredentialOfferEndpoint(this.router, this.issuer, opts?.endpointOpts?.createCredentialOfferOpts) } diff --git a/packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts b/packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts index 22756dba..c11bf9f2 100644 --- a/packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts +++ b/packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts @@ -13,10 +13,13 @@ import { JWTPayload, OpenId4VCIVersion, PRE_AUTH_CODE_LITERAL, - PRE_AUTH_GRANT_LITERAL, + PRE_AUTH_GRANT_LITERAL } from '@sphereon/oid4vci-common' import { VcIssuer } from '@sphereon/oid4vci-issuer/dist/VcIssuer' import { CredentialSupportedBuilderV1_13, VcIssuerBuilder } from '@sphereon/oid4vci-issuer/dist/builder' +import { + AuthorizationServerMetadataBuilder +} from '@sphereon/oid4vci-issuer/dist/builder/AuthorizationServerMetadataBuilder' import { MemoryStates } from '@sphereon/oid4vci-issuer/dist/state-manager' import { ExpressBuilder, ExpressSupport } from '@sphereon/ssi-express-support' import { IProofPurpose, IProofType } from '@sphereon/ssi-types' @@ -54,6 +57,16 @@ describe('VcIssuer', () => { // const clientId = 'sphereon:wallet' const preAuthorizedCode = 'test_code' + + const authorizationServerMetadata = new AuthorizationServerMetadataBuilder() + .withIssuer(ISSUER_URL) + .withCredentialEndpoint('http://localhost:3456/test/credential-endpoin') + .withTokenEndpoint('http://localhost:3456/test/token') + .withAuthorizationEndpoint('https://token-endpoint.example.com/authorize') + .withTokenEndpointAuthMethodsSupported(['none', 'client_secret_basic', 'client_secret_jwt', 'client_secret_post']) + .withResponseTypesSupported(['code', 'token', 'id_token']) + .withScopesSupported(['openid', 'abcdef']) + .build(); /*const preAuthorizedCode1 = 'SplxlOBeZQQYbYS6WxSbIA1' const preAuthorizedCode2 = 'SplxlOBeZQQYbYS6WxSbIA2' const preAuthorizedCode3 = 'SplxlOBeZQQYbYS6WxSbIA3' @@ -105,7 +118,7 @@ describe('VcIssuer', () => { } vcIssuer = new VcIssuerBuilder() - // .withAuthorizationServer('https://authorization-server') + .withAuthorizationMetadata(authorizationServerMetadata) .withCredentialEndpoint('http://localhost:3456/test/credential-endpoint') .withDefaultCredentialOfferBaseUri('http://localhost:3456/test') .withCredentialIssuer(ISSUER_URL) @@ -255,9 +268,29 @@ describe('VcIssuer', () => { it('should retrieve server metadata', async () => { await expect(client.retrieveServerMetadata()).resolves.toEqual({ - authorizationServerMetadata: undefined, + authorizationServerMetadata: { + 'authorization_endpoint': 'https://token-endpoint.example.com/authorize', + 'credential_endpoint': 'http://localhost:3456/test/credential-endpoin', + 'issuer': 'http://localhost:3456/test', + 'response_types_supported': [ + 'code', + 'token', + 'id_token' + ], + 'scopes_supported': [ + 'openid', + 'abcdef' + ], + 'token_endpoint': 'http://localhost:3456/test/token', + 'token_endpoint_auth_methods_supported': [ + 'none', + 'client_secret_basic', + 'client_secret_jwt', + 'client_secret_post' + ] + }, authorizationServerType: 'OID4VCI', - authorization_endpoint: undefined, + authorization_endpoint: 'https://token-endpoint.example.com/authorize', deferred_credential_endpoint: undefined, authorization_server: 'http://localhost:3456/test', credentialIssuerMetadata: { diff --git a/packages/issuer-rest/lib/oid4vci-api-functions.ts b/packages/issuer-rest/lib/oid4vci-api-functions.ts index db796f96..0c3f1079 100644 --- a/packages/issuer-rest/lib/oid4vci-api-functions.ts +++ b/packages/issuer-rest/lib/oid4vci-api-functions.ts @@ -21,6 +21,7 @@ import { trimEnd, trimStart, validateJWT, + WellKnownEndpoints } from '@sphereon/oid4vci-common' import { ITokenEndpointOpts, LOG, VcIssuer } from '@sphereon/oid4vci-issuer' import { env, ISingleEndpointOpts, sendErrorResponse } from '@sphereon/ssi-express-support' @@ -32,10 +33,11 @@ import { ICreateCredentialOfferEndpointOpts, ICreateCredentialOfferURIResponse, IGetCredentialOfferEndpointOpts, - IGetIssueStatusEndpointOpts, + IGetIssueStatusEndpointOpts } from './OID4VCIServer' import { validateRequestBody } from './expressUtils' + const expiresIn = process.env.EXPIRES_IN ? parseInt(process.env.EXPIRES_IN) : 90 export function getIssueStatusEndpoint(router: Router, issuer: VcIssuer, opts: IGetIssueStatusEndpointOpts) { @@ -392,11 +394,16 @@ export function pushedAuthorizationEndpoint( }) } -export function getMetadataEndpoint(router: Router, issuer: VcIssuer) { - const path = `/.well-known/openid-credential-issuer` - router.get(path, (request: Request, response: Response) => { +export function getMetadataEndpoints(router: Router, issuer: VcIssuer) { + const credentialIssuerHandler = (request: Request, response: Response) => { return response.send(issuer.issuerMetadata) - }) + } + router.get(WellKnownEndpoints.OPENID4VCI_ISSUER, credentialIssuerHandler) + + const authorizationServerHandler = (request: Request, response: Response) => { + return response.send(issuer.authorizationServerMetadata) + } + router.get(WellKnownEndpoints.OAUTH_AS, authorizationServerHandler) } export function determinePath( diff --git a/packages/issuer/lib/VcIssuer.ts b/packages/issuer/lib/VcIssuer.ts index e9d6eb5b..592804c7 100644 --- a/packages/issuer/lib/VcIssuer.ts +++ b/packages/issuer/lib/VcIssuer.ts @@ -1,7 +1,7 @@ import { uuidv4 } from '@sphereon/oid4vc-common' import { ALG_ERROR, - AUD_ERROR, + AUD_ERROR, AuthorizationServerMetadata, CNonceState, CreateCredentialOfferURIResult, CREDENTIAL_MISSING_ERROR, @@ -36,7 +36,7 @@ import { toUniformCredentialOfferRequest, TxCode, TYP_ERROR, - URIState, + URIState } from '@sphereon/oid4vci-common' import { CredentialEventNames, CredentialOfferEventNames, EVENTS } from '@sphereon/oid4vci-common' import { CredentialIssuerMetadataOptsV1_0_13 } from '@sphereon/oid4vci-common' @@ -48,6 +48,7 @@ import { CredentialDataSupplier, CredentialDataSupplierArgs, CredentialIssuanceI export class VcIssuer { private readonly _issuerMetadata: CredentialIssuerMetadataOptsV1_0_13 + private readonly _authorizationServerMetadata: AuthorizationServerMetadata private readonly _defaultCredentialOfferBaseUri?: string private readonly _credentialSignerCallback?: CredentialSignerCallback private readonly _jwtVerifyCallback?: JWTVerifyCallback @@ -59,6 +60,7 @@ export class VcIssuer { constructor( issuerMetadata: CredentialIssuerMetadataOptsV1_0_13, + authorizationServerMetadata: AuthorizationServerMetadata, args: { txCode?: TxCode baseUri?: string @@ -74,6 +76,7 @@ export class VcIssuer { ) { this.setDefaultTokenEndpoint(issuerMetadata) this._issuerMetadata = issuerMetadata + this._authorizationServerMetadata = authorizationServerMetadata this._defaultCredentialOfferBaseUri = args.defaultCredentialOfferBaseUri this._credentialOfferSessions = args.credentialOfferSessions this._cNonces = args.cNonces @@ -680,4 +683,10 @@ export class VcIssuer { public get issuerMetadata() { return this._issuerMetadata } + + public get authorizationServerMetadata() { + return this._authorizationServerMetadata + } + + } diff --git a/packages/issuer/lib/builder/AuthorizationServerMetadataBuilder.ts b/packages/issuer/lib/builder/AuthorizationServerMetadataBuilder.ts new file mode 100644 index 00000000..ada04213 --- /dev/null +++ b/packages/issuer/lib/builder/AuthorizationServerMetadataBuilder.ts @@ -0,0 +1,226 @@ +import { SigningAlgo } from '@sphereon/oid4vc-common' +import { + AuthorizationServerMetadata, + OAuthGrantType, OAuthResponseMode, + OAuthResponseType, + OAuthScope, + PKCECodeChallengeMethod, + RevocationEndpointAuthMethod, + RevocationEndpointAuthSigningAlg, + TokenEndpointAuthMethod, + TokenEndpointAuthSigningAlg +} from '@sphereon/oid4vci-common' + + +export class AuthorizationServerMetadataBuilder { + private metadata: Partial = {} + + public withIssuer(issuer: string): AuthorizationServerMetadataBuilder { + this.metadata.issuer = issuer + return this + } + + public withAuthorizationEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.authorization_endpoint = endpoint + return this + } + + public withTokenEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.token_endpoint = endpoint + return this + } + + public withTokenEndpointAuthMethodsSupported(methods:Array): AuthorizationServerMetadataBuilder { + this.metadata.token_endpoint_auth_methods_supported = methods + return this + } + + public withTokenEndpointAuthSigningAlgValuesSupported(algs: Array): AuthorizationServerMetadataBuilder { + this.metadata.token_endpoint_auth_signing_alg_values_supported = algs + return this + } + + public withRegistrationEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.registration_endpoint = endpoint + return this + } + + public withScopesSupported(scopes: Array): AuthorizationServerMetadataBuilder { + this.metadata.scopes_supported = scopes + return this + } + + public withResponseTypesSupported(types: Array): AuthorizationServerMetadataBuilder { + this.metadata.response_types_supported = types + return this + } + + public withResponseModesSupported(modes: Array): AuthorizationServerMetadataBuilder { + this.metadata.response_modes_supported = modes + return this + } + + public withGrantTypesSupported(types: Array): AuthorizationServerMetadataBuilder { + this.metadata.grant_types_supported = types + return this + } + + public withServiceDocumentation(url: string): AuthorizationServerMetadataBuilder { + this.metadata.service_documentation = url + return this + } + + public withUILocalesSupported(locales: string[]): AuthorizationServerMetadataBuilder { + this.metadata.ui_locales_supported = locales + return this + } + + public withOpPolicyUri(uri: string): AuthorizationServerMetadataBuilder { + this.metadata.op_policy_uri = uri + return this + } + + public withOpTosUri(uri: string): AuthorizationServerMetadataBuilder { + this.metadata.op_tos_uri = uri + return this + } + + public withRevocationEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.revocation_endpoint = endpoint + return this + } + + public withRevocationEndpointAuthMethodsSupported(methods: Array): AuthorizationServerMetadataBuilder { + this.metadata.revocation_endpoint_auth_methods_supported = methods + return this + } + + public withRevocationEndpointAuthSigningAlgValuesSupported(algs: Array): AuthorizationServerMetadataBuilder { + this.metadata.revocation_endpoint_auth_signing_alg_values_supported = algs + return this + } + + public withIntrospectionEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.introspection_endpoint = endpoint + return this + } + + public withCodeChallengeMethodsSupported(methods: Array): AuthorizationServerMetadataBuilder { + this.metadata.code_challenge_methods_supported = methods + return this + } + + public withPushedAuthorizationRequestEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.pushed_authorization_request_endpoint = endpoint + return this + } + + public withRequirePushedAuthorizationRequests(required: boolean): AuthorizationServerMetadataBuilder { + this.metadata.require_pushed_authorization_requests = required + return this + } + + public withPreAuthorizedGrantAnonymousAccessSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata['pre-authorized_grant_anonymous_access_supported'] = supported + return this + } + + public withDPoPSigningAlgValuesSupported(algs: (string | SigningAlgo)[]): AuthorizationServerMetadataBuilder { + this.metadata.dpop_signing_alg_values_supported = algs + return this + } + + // OIDC specific methods + public withFrontchannelLogoutSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata.frontchannel_logout_supported = supported + return this + } + + public withFrontchannelLogoutSessionSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata.frontchannel_logout_session_supported = supported + return this + } + + public withBackchannelLogoutSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata.backchannel_logout_supported = supported + return this + } + + public withBackchannelLogoutSessionSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata.backchannel_logout_session_supported = supported + return this + } + + public withUserinfoEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.userinfo_endpoint = endpoint + return this + } + + public withCheckSessionIframe(url: string): AuthorizationServerMetadataBuilder { + this.metadata.check_session_iframe = url + return this + } + + public withEndSessionEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.end_session_endpoint = endpoint + return this + } + + public withAcrValuesSupported(values: string[]): AuthorizationServerMetadataBuilder { + this.metadata.acr_values_supported = values + return this + } + + public withSubjectTypesSupported(types: string[]): AuthorizationServerMetadataBuilder { + this.metadata.subject_types_supported = types + return this + } + + public withRequestObjectSigningAlgValuesSupported(algs: string[]): AuthorizationServerMetadataBuilder { + this.metadata.request_object_signing_alg_values_supported = algs + return this + } + + public withDisplayValuesSupported(values: string[]): AuthorizationServerMetadataBuilder { + this.metadata.display_values_supported = values + return this + } + + public withClaimTypesSupported(types: string[]): AuthorizationServerMetadataBuilder { + this.metadata.claim_types_supported = types + return this + } + + public withClaimsSupported(claims: string[]): AuthorizationServerMetadataBuilder { + this.metadata.claims_supported = claims + return this + } + + public withClaimsParameterSupported(supported: boolean): AuthorizationServerMetadataBuilder { + this.metadata.claims_parameter_supported = supported + return this + } + + // VCI specific methods + public withCredentialEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.credential_endpoint = endpoint + return this + } + + public withDeferredCredentialEndpoint(endpoint: string): AuthorizationServerMetadataBuilder { + this.metadata.deferred_credential_endpoint = endpoint + return this + } + + public build(): AuthorizationServerMetadata { + if (!this.metadata.issuer) { + throw new Error('Issuer is required') + } + + if (!this.metadata.response_types_supported) { + throw new Error('Response types supported is required') + } + + return this.metadata as AuthorizationServerMetadata + } +} diff --git a/packages/issuer/lib/builder/VcIssuerBuilder.ts b/packages/issuer/lib/builder/VcIssuerBuilder.ts index 5094197c..207b8b6b 100644 --- a/packages/issuer/lib/builder/VcIssuerBuilder.ts +++ b/packages/issuer/lib/builder/VcIssuerBuilder.ts @@ -1,4 +1,5 @@ import { + AuthorizationServerMetadata, CNonceState, CredentialConfigurationSupportedV1_0_13, CredentialOfferSession, @@ -9,7 +10,7 @@ import { MetadataDisplay, TokenErrorResponse, TxCode, - URIState, + URIState } from '@sphereon/oid4vci-common' import { CredentialIssuerMetadataOptsV1_0_13 } from '@sphereon/oid4vci-common' @@ -22,6 +23,7 @@ import { IssuerMetadataBuilderV1_13 } from './IssuerMetadataBuilderV1_13' export class VcIssuerBuilder { issuerMetadataBuilder?: IssuerMetadataBuilderV1_13 issuerMetadata: Partial = {} + authorizationServerMetadata: Partial = {} txCode?: TxCode defaultCredentialOfferBaseUri?: string userPinRequired?: boolean @@ -41,6 +43,11 @@ export class VcIssuerBuilder { return this } + public withAuthorizationMetadata(authorizationServerMetadata: AuthorizationServerMetadata) { + this.authorizationServerMetadata = authorizationServerMetadata + return this + } + public withIssuerMetadataBuilder(builder: IssuerMetadataBuilderV1_13) { this.issuerMetadataBuilder = builder return this @@ -162,6 +169,12 @@ export class VcIssuerBuilder { if (!this.cNonceStateManager) { throw new Error(TokenErrorResponse.invalid_request) } + if(Object.keys(this.issuerMetadata).length === 0) { + throw new Error('issuerMetadata not set') + } + if(Object.keys(this.authorizationServerMetadata).length === 0) { + throw new Error('authorizationServerMetadata not set') + } const builder = this.issuerMetadataBuilder?.build() const metadata: Partial = { ...this.issuerMetadata, ...builder } @@ -171,7 +184,7 @@ export class VcIssuerBuilder { if (!metadata.credential_endpoint || !metadata.credential_issuer || !this.issuerMetadata.credential_configurations_supported) { throw new Error(TokenErrorResponse.invalid_request) } - return new VcIssuer(metadata as IssuerMetadataV1_0_13, { + return new VcIssuer(metadata as IssuerMetadataV1_0_13, this.authorizationServerMetadata as AuthorizationServerMetadata, { //TODO: discuss this with Niels. I did not find this in the spec. but I think we should somehow communicate this ...(this.txCode && { txCode: this.txCode }), defaultCredentialOfferBaseUri: this.defaultCredentialOfferBaseUri, diff --git a/packages/oid4vci-common/lib/types/ServerMetadata.ts b/packages/oid4vci-common/lib/types/ServerMetadata.ts index 246bdd03..b8f6208c 100644 --- a/packages/oid4vci-common/lib/types/ServerMetadata.ts +++ b/packages/oid4vci-common/lib/types/ServerMetadata.ts @@ -1,29 +1,110 @@ -import { DynamicRegistrationClientMetadata, SigningAlgo } from '@sphereon/oid4vc-common'; +import { DynamicRegistrationClientMetadata, SigningAlgo } from '@sphereon/oid4vc-common' + +export type OAuthResponseType = + | 'code' + | 'token' + | 'id_token' + | 'code token' + | 'code id_token' + | 'token id_token' + | 'code token id_token'; + + +export type TokenEndpointAuthMethod = + | 'client_secret_basic' + | 'client_secret_post' + | 'client_secret_jwt' + | 'private_key_jwt' + | 'none'; + +export type TokenEndpointAuthSigningAlg = + | 'RS256' + | 'RS384' + | 'RS512' + | 'ES256' + | 'ES384' + | 'ES512' + | 'PS256' + | 'PS384' + | 'PS512' + | 'HS256' + | 'HS384' + | 'HS512'; + +export type OAuthScope = + | 'openid' + | 'profile' + | 'email' + | 'address' + | 'phone' + | 'offline_access' + + +export type OAuthResponseMode = + | 'query' + | 'fragment' + | 'form_post'; + +export type OAuthGrantType = + | 'authorization_code' + | 'implicit' + | 'password' + | 'client_credentials' + | 'refresh_token' + | 'urn:ietf:params:oauth:grant-type:device_code' + | 'urn:ietf:params:oauth:grant-type:saml2-bearer' + | 'urn:ietf:params:oauth:grant-type:jwt-bearer' + +export type RevocationEndpointAuthMethod = + | 'client_secret_basic' + | 'client_secret_post' + | 'client_secret_jwt' + | 'private_key_jwt' + | 'none' + +export type RevocationEndpointAuthSigningAlg = + | 'RS256' + | 'RS384' + | 'RS512' + | 'ES256' + | 'ES384' + | 'ES512' + | 'PS256' + | 'PS384' + | 'PS512' + | 'HS256' + | 'HS384' + | 'HS512' + +export type PKCECodeChallengeMethod = + | 'plain' + | 'S256'; export interface AuthorizationServerMetadata extends DynamicRegistrationClientMetadata { issuer: string; authorization_endpoint?: string; token_endpoint?: string; - token_endpoint_auth_methods_supported?: string[]; - token_endpoint_auth_signing_alg_values_supported?: string[]; + token_endpoint_auth_methods_supported?: Array; + token_endpoint_auth_signing_alg_values_supported?: Array; registration_endpoint?: string; - scopes_supported?: string[]; - response_types_supported: string[]; - response_modes_supported?: string[]; - grant_types_supported?: string[]; + scopes_supported?: Array; + response_types_supported: Array + response_modes_supported?: Array; + grant_types_supported?: Array; service_documentation?: string; ui_locales_supported?: string[]; op_policy_uri?: string; op_tos_uri?: string; revocation_endpoint?: string; - revocation_endpoint_auth_methods_supported?: string[]; - revocation_endpoint_auth_signing_alg_values_supported?: string[]; + revocation_endpoint_auth_methods_supported?: Array; + revocation_endpoint_auth_signing_alg_values_supported?: Array; introspection_endpoint?: string; - code_challenge_methods_supported?: string[]; + code_challenge_methods_supported?: Array; + // TODO below fields are not in the rfc8414 spec, do we need them? pushed_authorization_request_endpoint?: string; // The URL of the pushed authorization request endpoint at which a client can post an authorization request to exchange for a request_uri value usable at the authorization server // Note that the presence of pushed_authorization_request_endpoint is sufficient for a client to determine that it may use the PAR flow. A request_uri value obtained from the PAR endpoint is usable at the authorization endpoint regardless of other authorization server metadata such as request_uri_parameter_supported or require_request_uri_registration require_pushed_authorization_requests?: boolean; // Boolean parameter indicating whether Indicates whether the client is required to use PAR to initiate authorization. If omitted, the default value is false. @@ -54,6 +135,33 @@ export interface AuthorizationServerMetadata extends DynamicRegistrationClientMe [x: string]: any; //We use any, so you can access properties if you know the structure } +// These can be used be a reducer +export const authorizationServerMetadataFieldNames: Array = [ + 'issuer', + 'authorization_endpoint', + 'token_endpoint', + 'jwks_uri', + 'registration_endpoint', + 'scopes_supported', + 'response_types_supported', + 'response_modes_supported', + 'grant_types_supported', + 'token_endpoint_auth_methods_supported', + 'token_endpoint_auth_signing_alg_values_supported', + 'service_documentation', + 'ui_locales_supported', + 'op_policy_uri', + 'op_tos_uri', + 'revocation_endpoint', + 'revocation_endpoint_auth_methods_supported', + 'revocation_endpoint_auth_signing_alg_values_supported', + 'introspection_endpoint', + 'introspection_endpoint_auth_methods_supported', + 'introspection_endpoint_auth_signing_alg_values_supported', + 'code_challenge_methods_supported', + 'signed_metadata' +] as const + export enum WellKnownEndpoints { OPENID_CONFIGURATION = '/.well-known/openid-configuration', OAUTH_AS = '/.well-known/oauth-authorization-server', diff --git a/packages/oid4vci-common/lib/types/v1_0_13.types.ts b/packages/oid4vci-common/lib/types/v1_0_13.types.ts index 93933882..fecab1c4 100644 --- a/packages/oid4vci-common/lib/types/v1_0_13.types.ts +++ b/packages/oid4vci-common/lib/types/v1_0_13.types.ts @@ -209,6 +209,29 @@ export interface CredentialIssuerMetadataOptsV1_0_13 { credential_supplier_config?: CredentialSupplierConfig; } +// These can be used be a reducer +export const credentialIssuerMetadataFieldNames: Array = [ + // Required fields + 'credential_issuer', + 'credential_configurations_supported', + 'credential_endpoint', + + // Optional fields from CredentialIssuerMetadataOpts + 'batch_credential_endpoint', + 'deferred_credential_endpoint', + 'notification_endpoint', + 'credential_response_encryption', + 'authorization_servers', + 'token_endpoint', + 'display', + 'credential_supplier_config', + + // Optional fields from v1.0.13 + 'credential_identifiers_supported', + 'signed_metadata' +] as const + + export interface EndpointMetadataResultV1_0_13 extends EndpointMetadata { // The EndpointMetadata are snake-case so they can easily be used in payloads/JSON. // The values below should not end up in requests/responses directly, so they are using our normal CamelCase convention