From f31125865a3d63ce7719f790fc5ac74fea7f9ade Mon Sep 17 00:00:00 2001 From: sksadjad Date: Thu, 30 Mar 2023 09:03:36 +0200 Subject: [PATCH] feat: added better support (and distinction) for types v1.0.09 and v1.0.11 --- .../lib/__tests__/OpenID4VCIClient.spec.ts | 4 +- packages/common/lib/types/Generic.types.ts | 259 ++++++++++++++++++ packages/common/lib/types/index.ts | 2 + packages/common/lib/types/v1_0_09.types.ts | 23 ++ packages/common/lib/types/v1_0_11.types.ts | 31 +++ 5 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 packages/common/lib/types/v1_0_09.types.ts create mode 100644 packages/common/lib/types/v1_0_11.types.ts diff --git a/packages/client/lib/__tests__/OpenID4VCIClient.spec.ts b/packages/client/lib/__tests__/OpenID4VCIClient.spec.ts index e92295bc..337439e5 100644 --- a/packages/client/lib/__tests__/OpenID4VCIClient.spec.ts +++ b/packages/client/lib/__tests__/OpenID4VCIClient.spec.ts @@ -131,7 +131,9 @@ describe('OpenID4VCIClient should', () => { }, redirectUri: 'http://localhost:8881/cb', }) - ).toEqual('https://server.example.com/v1/auth/authorize?response_type=code&client_id=test-client&code_challenge_method=S256&code_challenge=mE2kPHmIprOqtkaYmESWj35yz-PB5vzdiSu0tAZ8sqs&authorization_details=%7B%22type%22%3A%22openid_credential%22%2C%22format%22%3A%22ldp_vc%22%2C%22credential_definition%22%3A%7B%22%40context%22%3A%5B%22https%3A%2F%2Fwww%2Ew3%2Eorg%2F2018%2Fcredentials%2Fv1%22%2C%22https%3A%2F%2Fwww%2Ew3%2Eorg%2F2018%2Fcredentials%2Fexamples%2Fv1%22%5D%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22UniversityDegreeCredential%22%5D%7D%2C%22locations%22%3A%22https%3A%2F%2Fserver%2Eexample%2Ecom%22%7D&redirect_uri=http%3A%2F%2Flocalhost%3A8881%2Fcb'); + ).toEqual( + 'https://server.example.com/v1/auth/authorize?response_type=code&client_id=test-client&code_challenge_method=S256&code_challenge=mE2kPHmIprOqtkaYmESWj35yz-PB5vzdiSu0tAZ8sqs&authorization_details=%7B%22type%22%3A%22openid_credential%22%2C%22format%22%3A%22ldp_vc%22%2C%22credential_definition%22%3A%7B%22%40context%22%3A%5B%22https%3A%2F%2Fwww%2Ew3%2Eorg%2F2018%2Fcredentials%2Fv1%22%2C%22https%3A%2F%2Fwww%2Ew3%2Eorg%2F2018%2Fcredentials%2Fexamples%2Fv1%22%5D%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22UniversityDegreeCredential%22%5D%7D%2C%22locations%22%3A%22https%3A%2F%2Fserver%2Eexample%2Ecom%22%7D&redirect_uri=http%3A%2F%2Flocalhost%3A8881%2Fcb' + ); }); it('create an authorization request url with authorization_details and scope', async () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/common/lib/types/Generic.types.ts b/packages/common/lib/types/Generic.types.ts index a34d0ce9..2884d42c 100644 --- a/packages/common/lib/types/Generic.types.ts +++ b/packages/common/lib/types/Generic.types.ts @@ -1,5 +1,190 @@ +import { ICredentialContextType, IVerifiableCredential, W3CVerifiableCredential } from '@sphereon/ssi-types'; + +import { CodeChallengeMethod, ResponseType } from './Authorization.types'; +import { ProofOfPossession } from './CredentialIssuance.types'; import { OpenID4VCIServerMetadata } from './OpenID4VCIServerMetadata'; +/** + * Important Note: please be aware that these Common interfaces are based on versions v1_0.11 and v1_0.09 + */ +export interface CredentialLogo { + url?: string; + alt_text?: string; +} + +export enum CredentialFormatEnum { + jwt_vc_json = 'jwt_vc_json', + jwt_vc_json_ld = 'jwt_vc_json_ld', + ldp_vc = 'ldp_vc', + mso_mdoc = 'mso_mdoc', +} + +export interface NameAndLocale { + name?: string; + locale?: string; +} + +export interface Display extends NameAndLocale { + logo?: CredentialLogo; + background_color?: string; + text_color?: string; +} + +export interface IssuerMetadata { + credential_endpoint: string; + batch_credential_endpoint?: string; + credentials_supported: CredentialIssuerMetadataSupportedCredentials[]; + credential_issuer: Display; +} + +export interface CredentialIssuerMetadataSupportedCredentials { + format: CredentialFormatEnum; + id?: string; + cryptographic_binding_methods_supported?: string[]; + cryptographic_suites_supported?: string[]; +} + +export interface SupportedCredentialIssuerMetadataJwtVcJsonLdAndLdpVc extends CredentialIssuerMetadataSupportedCredentials { + format: CredentialFormatEnum.ldp_vc; + '@context': ICredentialContextType[]; + types: string[]; + credentialSubject?: IssuerCredentialSubject; + display?: Display[]; +} + +export interface SupportedCredentialIssuerMetadataJwtVcJson extends CredentialIssuerMetadataSupportedCredentials { + types: string[]; + credentialSubject?: IssuerCredentialSubject; + display?: Display[]; + order?: string[]; //An array of claims.display.name values that lists them in the order they should be displayed by the Wallet. +} + +export interface MsoClaims { + // key is a certain namespace as defined in [ISO.18013-5] (or any profile of it) examples: "org.iso.18013.5.1", "org.iso.18013.5.1.aamva" + [key: string]: { + [key: string]: { + mandatory?: boolean; + value_type?: string; + display?: Display[]; + }; + }; +} +export interface SupportedCredentialIssuerMetadataMsoMdoc extends CredentialIssuerMetadataSupportedCredentials { + format: CredentialFormatEnum.mso_mdoc; + doctype: string; + claims?: MsoClaims; + order?: string[]; +} + +export interface CredentialOfferCredential { + format: CredentialFormatEnum; +} + +export interface CredentialOfferCredentialJwtVcJson extends CredentialOfferCredential { + format: CredentialFormatEnum.jwt_vc_json; + types: string[]; +} +export interface CredentialOfferCredentialMsoMdoc extends CredentialOfferCredential { + format: CredentialFormatEnum.mso_mdoc; + doctype: string; +} + +export interface IssuerCredentialDefinition { + '@context': ICredentialContextType[]; + types: string[]; + credentialSubject: IssuerCredentialSubject; +} + +//todo: change this back to AuthorizationRequest once merged with latest changes from develop +export interface AbstractAuthorizationRequest { + response_type: ResponseType.AUTH_CODE; + client_id: string; + code_challenge: string; + code_challenge_method: CodeChallengeMethod; + redirect_uri: string; + scope?: string; + authorization_details?: AbstractAuthorizationDetails[]; + wallet_issuer?: string; + user_hint?: string; +} + +export interface AuthorizationRequestJwtVcJson extends AbstractAuthorizationRequest { + authorization_details?: AuthorizationDetailsJwtVcJson[]; +} + +export interface AuthorizationRequestJwtVcJsonLdAndLdpVc extends AbstractAuthorizationRequest { + authorization_details?: AuthorizationDetailsJwtVcJsonLdAndLdpVc[]; +} + +export interface AuthorizationRequestMsoDoc extends AbstractAuthorizationRequest { + authorization_details?: AuthorizationDetailsMsoDoc[]; +} + +export interface AbstractAuthorizationDetails { + type: 'openid_credential'; + format: CredentialFormatEnum; +} + +export interface AuthorizationDetailsJwtVcJson extends AbstractAuthorizationDetails { + format: CredentialFormatEnum.jwt_vc_json; + types: string[]; + credentialSubject?: IssuerCredentialSubject; +} + +export interface AuthorizationDetailsJwtVcJsonLdAndLdpVc extends AbstractAuthorizationDetails { + format: CredentialFormatEnum.ldp_vc | CredentialFormatEnum.jwt_vc_json_ld; + types: string[]; + credential_definition: IssuerCredentialDefinition; +} + +export interface AuthorizationDetailsMsoDoc extends AbstractAuthorizationDetails { + format: CredentialFormatEnum.mso_mdoc; + doctype: string; + claims?: MsoClaims; +} + +export interface CredentialOfferCredentialDefinition { + '@context': ICredentialContextType[]; + types: string[]; + CredentialSubject?: IssuerCredentialSubject; +} + +export enum GrantType { + AUTHORIZATION_CODE = 'authorization_code', + PRE_AUTHORIZED_CODE = 'urn:ietf:params:oauth:grant-type:pre-authorized_code', + PASSWORD = 'password', +} + +//todo: change this back to AccessTokenRequest once merged with latest changes from develop +export interface GenericAccessTokenRequest { + client_id?: string; + code?: string; + code_verifier?: string; + grant_type: GrantType; + 'pre-authorized_code'?: string; + redirect_uri?: string; + scope?: string; + user_pin?: string; +} + +export enum TokenErrorResponse { + invalid_request = 'invalid_request', + invalid_grant = 'invalid_grant', + invalid_client = 'invalid_client', // this code has been added only in v1_0-11, but I've added this to the common interface. @nklomp is this ok? +} + +//todo: change this back to AccessTokenResponse once merged with latest changes from develop +export interface GenericAccessTokenResponse { + access_token: string; + scope?: string; + token_type?: string; + expires_in?: number; // in seconds + c_nonce?: string; + c_nonce_expires_in?: number; // in seconds + authorization_pending?: boolean; + interval?: number; // in seconds +} + export interface ErrorResponse extends Response { error: string; error_description?: string; @@ -7,6 +192,80 @@ export interface ErrorResponse extends Response { state?: string; } +//todo: change this back to CredentialRequest once merged with latest changes from develop +export interface AbstractCredentialRequest { + format: string; + proof?: ProofOfPossession; +} + +export interface CredentialRequestJwtVcJson extends AbstractCredentialRequest { + format: CredentialFormatEnum.jwt_vc_json; + types: string[]; + credentialSubject?: IssuerCredentialSubject; +} + +export interface CredentialRequestJwtVcJsonLdAndLdpVc extends AbstractCredentialRequest { + format: CredentialFormatEnum.jwt_vc_json_ld | CredentialFormatEnum.ldp_vc; + credential_definition: IssuerCredentialDefinition; +} + +//todo: change this back to CredentialResponse once merged with latest changes from develop +export interface AbstractCredentialResponse { + format: string; + credential?: W3CVerifiableCredential; + acceptance_token?: string; + c_nonce?: string; + c_nonce_expires_in?: string; +} + +export interface CredentialResponseJwtVcJsonLdAndLdpVc extends AbstractCredentialResponse { + format: CredentialFormatEnum.jwt_vc_json_ld | CredentialFormatEnum.ldp_vc; + credential: IVerifiableCredential; +} + +export interface IssuerCredentialSubjectDisplay { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + mandatory?: boolean; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + value_type?: string; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + display?: NameAndLocale[]; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + order?: string[]; // An array of claims.display.name values that lists them in the order they should be displayed by the Wallet. + [key: string]: { + mandatory?: boolean; + value_type?: string; + display?: NameAndLocale[]; + order?: string[]; // An array of claims.display.name values that lists them in the order they should be displayed by the Wallet. + }; +} + +export interface IssuerCredentialSubject { + [key: string]: IssuerCredentialSubjectDisplay; +} + +export interface CredentialResponseJwtVcJson { + credential: string; +} + +export interface Grant { + authorization_code?: GrantAuthorizationCode; + 'urn:ietf:params:oauth:grant-type:pre-authorized_code': GrantUrnIetf; +} + +export interface GrantAuthorizationCode { + issuer_state?: string; +} + +export interface GrantUrnIetf { + 'pre-authorized_code': string; + user_pin_required: boolean; +} + export const PRE_AUTH_CODE_LITERAL = 'pre-authorized_code'; export enum WellKnownEndpoints { diff --git a/packages/common/lib/types/index.ts b/packages/common/lib/types/index.ts index 84ce6604..e8eff8c0 100644 --- a/packages/common/lib/types/index.ts +++ b/packages/common/lib/types/index.ts @@ -1,6 +1,8 @@ export * from './Authorization.types'; export * from './CredentialIssuance.types'; export * from './Generic.types'; +export * from './v1_0_09.types'; +export * from './v1_0_11.types'; export * from './OAuth2ASMetadata'; export * from './OpenID4VCIErrors'; export * from './OpenID4VCIServerMetadata'; diff --git a/packages/common/lib/types/v1_0_09.types.ts b/packages/common/lib/types/v1_0_09.types.ts new file mode 100644 index 00000000..b0a908ec --- /dev/null +++ b/packages/common/lib/types/v1_0_09.types.ts @@ -0,0 +1,23 @@ +import { AbstractAuthorizationDetails, AbstractAuthorizationRequest, CredentialOfferCredential, IssuerCredentialSubject } from './Generic.types'; + +// https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-09.html#name-issuance-initiation-request +export interface CredentialOfferV1_0_09 { + issuer: string; + credentials: (CredentialOfferCredential | string)[]; + 'pre-authorized_code'?: string; + user_pin_required?: boolean; + op_state?: string; +} + +export interface AuthorizationRequestV1_0_09 extends AbstractAuthorizationRequest { + op_state?: string; +} + +export interface IssuanceInitiationRequestJwtVcJsonV1_0_09 extends CredentialOfferV1_0_09 { + credentials: CredentialOfferCredential[]; +} + +export interface AuthorizationDetailsJwtVcJsonV1_0_09 extends AbstractAuthorizationDetails { + types: string[]; + CredentialSubject?: IssuerCredentialSubject; +} diff --git a/packages/common/lib/types/v1_0_11.types.ts b/packages/common/lib/types/v1_0_11.types.ts new file mode 100644 index 00000000..1e599cc5 --- /dev/null +++ b/packages/common/lib/types/v1_0_11.types.ts @@ -0,0 +1,31 @@ +import { AbstractAuthorizationRequest, CredentialFormatEnum, CredentialOfferCredential, Grant, IssuerCredentialDefinition } from './Generic.types'; + +export interface CredentialOfferV1_0_11 { + credential_offer?: InnerCredentialOfferV1_0_11; + credential_offer_uri?: string; +} + +export interface InnerCredentialOfferV1_0_11 { + credential_issuer: string; + //fixme: @nklomp, I've made this optional because in the annex E's example, we don't see the credentials property, but we see credential_definition property which I guess does the same thing. I've already asked about this in https://bitbucket.org/openid/connect/issues/1875/differences-between-spec-and-examples-in + credentials?: (CredentialOfferCredential | string)[]; + grants?: Grant; +} + +export interface AuthorizationRequestV1_0_11 extends AbstractAuthorizationRequest { + issuer_state?: string; +} + +export interface CredentialOfferJwtVcJsonLdAndLdpVcV1_0_11 extends InnerCredentialOfferV1_0_11 { + credential_definition: IssuerCredentialDefinition; +} + +export interface CredentialOfferJwtVcJsonV1_0_11 extends InnerCredentialOfferV1_0_11 { + credentials: ( + | { + format: CredentialFormatEnum.jwt_vc_json; + types: string[]; + } + | string + )[]; +}