Skip to content

Commit

Permalink
OpenID V12 spec
Browse files Browse the repository at this point in the history
  • Loading branch information
sanderPostma committed Jan 9, 2024
1 parent 1595df2 commit 566f8a9
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 44 deletions.
2 changes: 1 addition & 1 deletion packages/client/lib/CredentialOfferClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
CredentialOfferPayload,
CredentialOfferPayloadV1_0_09,
CredentialOfferRequestWithBaseUrl,
CredentialOfferV1_0_11,
CredentialOfferV1_0_12,
determineSpecVersionFromURI,
OpenId4VCIVersion,
toUniformCredentialOfferRequest,
Expand Down
4 changes: 2 additions & 2 deletions packages/client/lib/MetadataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export class MetadataClient {
if (credentialIssuerMetadata.token_endpoint) {
token_endpoint = credentialIssuerMetadata.token_endpoint;
}
if (credentialIssuerMetadata.authorization_server) {
authorization_server = credentialIssuerMetadata.authorization_server;
if (credentialIssuerMetadata.authorization_servers) {
authorization_server = credentialIssuerMetadata.authorization_servers;
}
if (credentialIssuerMetadata.authorization_endpoint) {
authorization_endpoint = credentialIssuerMetadata.authorization_endpoint;
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/OpenID4VCIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export class OpenID4VCIClient {
private handleLocations(authorizationDetails: AuthDetails) {
if (
authorizationDetails &&
(this.endpointMetadata.credentialIssuerMetadata?.authorization_server || this.endpointMetadata.authorization_endpoint)
(this.endpointMetadata.credentialIssuerMetadata?.authorization_servers || this.endpointMetadata.authorization_endpoint)
) {
if (authorizationDetails.locations) {
if (Array.isArray(authorizationDetails.locations)) {
Expand Down
2 changes: 2 additions & 0 deletions packages/common/lib/types/Authorization.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ export interface AuthorizationDetailsJwtVcJson extends CommonAuthorizationDetail
*/
credentialSubject?: IssuerCredentialSubject;

issuer_state?: string;

types: string[]; // This claim contains the type values the Wallet requests authorization for at the issuer.
}

Expand Down
10 changes: 4 additions & 6 deletions packages/common/lib/types/CredentialIssuance.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import { W3CVerifiableCredential } from '@sphereon/ssi-types';
import { AuthzFlowType } from './Authorization.types';
import { OID4VCICredentialFormat } from './Generic.types';
import { OpenId4VCIVersion } from './OpenID4VCIVersions.types';
import { CredentialOfferPayloadV1_0_08 } from './v1_0_08.types';
import { CredentialOfferPayloadV1_0_09, CredentialOfferV1_0_09 } from './v1_0_09.types';
import { CredentialOfferPayloadV1_0_11, CredentialOfferV1_0_11 } from './v1_0_11.types';
import { CredentialOfferPayloadV1_0_12, CredentialOfferV1_0_12 } from './v1_0_12.types';

export interface CredentialResponse {
credential?: W3CVerifiableCredential; // OPTIONAL. Contains issued Credential. MUST be present when acceptance_token is not returned. MAY be a JSON string or a JSON object, depending on the Credential format. See Appendix E for the Credential format specific encoding requirements
Expand All @@ -23,9 +21,9 @@ export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOffe
preAuthorizedCode?: string;
}

export type CredentialOffer = CredentialOfferV1_0_09 | CredentialOfferV1_0_11;
export type CredentialOffer = CredentialOfferV1_0_12;

export type CredentialOfferPayload = CredentialOfferPayloadV1_0_08 | CredentialOfferPayloadV1_0_09 | CredentialOfferPayloadV1_0_11;
export type CredentialOfferPayload = CredentialOfferPayloadV1_0_12;

export interface AssertedUniformCredentialOffer extends UniformCredentialOffer {
credential_offer: UniformCredentialOfferPayload;
Expand All @@ -42,7 +40,7 @@ export interface UniformCredentialOfferRequest extends AssertedUniformCredential
supportedFlows: AuthzFlowType[];
}

export type UniformCredentialOfferPayload = CredentialOfferPayloadV1_0_11;
export type UniformCredentialOfferPayload = CredentialOfferPayloadV1_0_12;

export interface ProofOfPossession {
proof_type: 'jwt';
Expand Down
76 changes: 57 additions & 19 deletions packages/common/lib/types/Generic.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ICredentialContextType, IVerifiableCredential, W3CVerifiableCredential
import { ProofOfPossession } from './CredentialIssuance.types';
import { AuthorizationServerMetadata } from './ServerMetadata';
import { CredentialOfferSession } from './StateManager.types';
import { CredentialRequestV1_0_11 } from './v1_0_11.types';
import { CredentialRequestV1_0_12 } from './v1_0_12.types';

/**
* Important Note: please be aware that these Common interfaces are based on versions v1_0.11 and v1_0.09
Expand All @@ -17,6 +17,23 @@ export interface ImageInfo {

export type OID4VCICredentialFormat = 'jwt_vc_json' | 'jwt_vc_json-ld' | 'ldp_vc' | 'vc+sd-jwt' /*| 'mso_mdoc'*/; // we do not support mdocs at this point

export type KeyProofType = 'jwt' | 'cwt'

export type JWAlgorithm =
'HS256' | // HMAC using SHA-256
'HS384' | // HMAC using SHA-384
'HS512' | // HMAC using SHA-512
'RS256' | // RSASSA-PKCS1-v1_5 using SHA-256
'RS384' | // RSASSA-PKCS1-v1_5 using SHA-384
'RS512' | // RSASSA-PKCS1-v1_5 using SHA-512
'ES256' | // ECDSA using P-256 and SHA-256
'ES384' | // ECDSA using P-384 and SHA-384
'ES512' | // ECDSA using P-521 and SHA-512
'PS256' | // RSASSA-PSS using SHA-256 and MGF1 with SHA-256
'PS384' | // RSASSA-PSS using SHA-384 and MGF1 with SHA-384
'PS512' | // RSASSA-PSS using SHA-512 and MGF1 with SHA-512
'none' // No digital signature or MAC performed

export interface NameAndLocale {
name?: string; // REQUIRED. String value of a display name for the Credential.
locale?: string; // OPTIONAL. String value that identifies the language of this object represented as a language tag taken from values defined in BCP47 [RFC5646]. Multiple display objects MAY be included for separate languages. There MUST be only one object with the same language identifier.
Expand All @@ -30,10 +47,12 @@ export interface LogoAndColor {
text_color?: string; // OPTIONAL. String value of a text color of the Credential represented as numerical color values defined in CSS Color Module Level 37 [CSS-Color].
}


export type CredentialsSupportedDisplay = NameAndLocale &
LogoAndColor & {
name: string; // REQUIRED. String value of a display name for the Credential.
background_image?: ImageInfo; //OPTIONAL, NON-SPEC compliant!. URL of a background image useful for card views of credentials. Expected to an image that fills the full card-view of a wallet
name: string // REQUIRED. String value of a display name for the Credential.
locale?: string // OPTIONAL. String value that identifies the language of this object represented as a language tag taken from values defined in BCP47
description?: string // OPTIONAL. String value of a description of the Credential.
};

export type MetadataDisplay = NameAndLocale &
Expand All @@ -46,14 +65,19 @@ export interface CredentialSupplierConfig {
}

export interface CredentialIssuerMetadataOpts {
credential_issuer: string; // REQUIRED. The Credential Issuer's identifier.
authorization_servers?: string[]; // OPTIONAL. Identifier of the OAuth 2.0 Authorization Server (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
credential_endpoint?: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components.
batch_credential_endpoint?: string; // OPTIONAL. URL of the Credential Issuer's Batch Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. If omitted, the Credential Issuer does not support the Batch Credential Endpoint.
credentials_supported: CredentialSupported[]; // REQUIRED. A JSON array containing a list of JSON objects, each of them representing metadata about a separate credential type that the Credential Issuer can issue. The JSON objects in the array MUST conform to the structure of the Section 10.2.3.1.
credential_issuer: string; // REQUIRED. The Credential Issuer's identifier.
authorization_server?: string; // OPTIONAL. Identifier of the OAuth 2.0 Authorization Server (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
token_endpoint?: string;
deferred_credential_endpoint?: string; // OPTIONAL. URL of the Credential Issuer's Deferred Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path, and query parameter components. If omitted, the Credential Issuer does not support the Deferred Credential Endpoint.
credential_response_encryption_alg_values_supported?: JWAlgorithm[] // OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (alg values)
credential_response_encryption_enc_values_supported?: JWAlgorithm[] // OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (enc values)
require_credential_response_encryption?: boolean // OPTIONAL. Boolean value specifying whether the Credential Issuer requires additional encryption on top of TLS for the Credential Response and expects encryption parameters to be present in the Credential Request and/or Batch Credential Request, with true indicating support. When the value is true, credential_response_encryption_alg_values_supported parameter MUST also be provided. If omitted, the default value is false
credential_identifiers_supported?: boolean // OPTIONAL. Boolean value specifying whether the Credential Issuer supports returning credential_identifiers parameter in the authorization_details Token Response parameter, with true indicating support. If omitted, the default value is false.
display?: MetadataDisplay[]; // An array of objects, where each object contains display properties of a Credential Issuer for a certain language. Below is a non-exhaustive list of valid parameters that MAY be included:
credential_supplier_config?: CredentialSupplierConfig;
credentials_supported: CredentialSupported[]; // REQUIRED. A JSON array containing a list of JSON objects, each of them representing metadata about a separate credential type that the Credential Issuer can issue. The JSON objects in the array MUST conform to the structure of the Section 10.2.3.1.
token_endpoint?: string; // CUSTOM out of spec
credential_supplier_config?: CredentialSupplierConfig; // CUSTOM out of spec
}

// For now we extend the opts above. Only difference is that the credential endpoint is optional in the Opts, as it can come from other sources. The value is however required in the eventual Issuer Metadata
Expand All @@ -67,12 +91,12 @@ export interface CredentialSupportedBrief {
}

export type CommonCredentialSupported = CredentialSupportedBrief & {
format: OID4VCICredentialFormat | string; //REQUIRED. A JSON string identifying the format of this credential, e.g. jwt_vc_json or ldp_vc.
id?: string; // OPTIONAL. A JSON string identifying the respective object. The value MUST be unique across all credentials_supported entries in the Credential Issuer Metadata
display?: CredentialsSupportedDisplay[]; // OPTIONAL. An array of objects, where each object contains the display properties of the supported credential for a certain language
/**
* following properties are non-mso_mdoc specific and we might wanna rethink them when we're going to support mso_mdoc
*/
format: OID4VCICredentialFormat | string; // REQUIRED. A JSON string identifying the format of this credential, i.e., jwt_vc_json or ldp_vc. Depending on the format value, the object contains further elements defining the type and (optionally) particular claims the credential MAY contain and information about how to display the credential.
// id is @Deprecated V12, but still in use I see
id?: string; // OPTIONAL. A JSON string identifying the respective object. The value MUST be unique across all credentials_supported entries in the Credential Issuer Metadata
scope?: string; // OPTIONAL. A JSON string identifying the scope value that this Credential Issuer supports for this particular credential. The value can be the same across multiple credentials_supported objects. Scope values in this Credential Issuer metadata MAY duplicate those in the scopes_supported parameter of the Authorization Server.
proof_types_supported?: KeyProofType[];
display?: CredentialsSupportedDisplay[];
};

export interface CredentialSupportedJwtVcJsonLdAndLdpVc extends CommonCredentialSupported {
Expand All @@ -83,9 +107,13 @@ export interface CredentialSupportedJwtVcJsonLdAndLdpVc extends CommonCredential
format: 'ldp_vc' | 'jwt_vc_json-ld';
}

export interface CredentialSupportedJwtVcJson extends CommonCredentialSupported {
types: string[]; // REQUIRED. JSON array designating the types a certain credential type supports
export interface JwtVcCredentialDefinition {
type: string[]; // REQUIRED. JSON array designating the types a certain credential type supports
credentialSubject?: IssuerCredentialSubject; // OPTIONAL. A JSON object containing a list of key value pairs, where the key identifies the claim offered in the Credential. The value MAY be a dictionary, which allows to represent the full (potentially deeply nested) structure of the verifiable credential to be issued.
}

export interface CredentialSupportedJwtVcJson extends CommonCredentialSupported {
credential_definition: JwtVcCredentialDefinition; // REQUIRED. JSON object containing the detailed description of the credential type
order?: string[]; //An array of claims.display.name values that lists them in the order they should be displayed by the Wallet.
format: 'jwt_vc_json';
}
Expand Down Expand Up @@ -156,7 +184,7 @@ export interface ErrorResponse extends Response {
state?: string;
}

export type UniformCredentialRequest = CredentialRequestV1_0_11;
export type UniformCredentialRequest = CredentialRequestV1_0_12;

export interface CommonCredentialRequest {
format: OID4VCICredentialFormat /* | OID4VCICredentialFormat[];*/; // for now it seems only one is supported in the spec
Expand Down Expand Up @@ -233,12 +261,22 @@ export interface GrantUrnIetf {
/**
* REQUIRED. The code representing the Credential Issuer's authorization for the Wallet to obtain Credentials of a certain type.
*/
'pre-authorized_code': string;
'pre-authorized_code': string
/**
* OPTIONAL. Boolean value specifying whether the Credential Issuer expects presentation of a user PIN along with the Token Request
* in a Pre-Authorized Code Flow. Default is false.
*/
user_pin_required: boolean;
user_pin_required?: boolean

/**
* OPTIONAL. The minimum amount of time in seconds that the Wallet SHOULD wait between polling requests to the token endpoint (in case the Authorization Server responds with error code authorization_pending - see Section 6.3). If no value is provided, Wallets MUST use 5 as the default.
*/
interval?: number

/**
* OPTIONAL string that the Wallet can use to identify the Authorization Server to use with this grant type when authorization_servers parameter in the Credential Issuer metadata has multiple entries. MUST NOT be used otherwise. The value of this parameter MUST match with one of the values in the authorization_servers array obtained from the Credential Issuer metadata.
*/
authorization_server?: string
}

export const PRE_AUTH_CODE_LITERAL = 'pre-authorized_code';
2 changes: 1 addition & 1 deletion packages/common/lib/types/v1_0_08.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface IssuerMetadataV1_0_08 {
// OPTIONAL. A JSON object containing display properties for the Credential issuer.
display: NameAndLocale | NameAndLocale[]; // OPTIONAL. An array of objects, where each object contains display properties of a Credential issuer for a certain language. Below is a non-exhaustive list of valid parameters that MAY be included:
};
authorization_server?: string;
authorization_servers?: string;
token_endpoint?: string;
display?: MetadataDisplay[];
[x: string]: unknown;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import {
} from './Generic.types';
import { QRCodeOpts } from './QRCode.types';

export interface CredentialOfferV1_0_11 {
credential_offer?: CredentialOfferPayloadV1_0_11;
export interface CredentialOfferV1_0_12 {
credential_offer?: CredentialOfferPayloadV1_0_12;
credential_offer_uri?: string;
}

export interface CredentialOfferRESTRequest extends CredentialOfferV1_0_11 {
export interface CredentialOfferRESTRequest extends CredentialOfferV1_0_12 {
baseUri?: string;
scheme?: string;
pinLength?: number;
qrCodeOpts?: QRCodeOpts;
credentialDataSupplierInput?: CredentialDataSupplierInput;
}

export interface CredentialOfferPayloadV1_0_11 {
export interface CredentialOfferPayloadV1_0_12 {
/**
* REQUIRED. The URL of the Credential Issuer, the Wallet is requested to obtain one or more Credentials from.
*/
Expand All @@ -50,14 +50,14 @@ export interface CredentialOfferPayloadV1_0_11 {
grants?: Grant;
}

export type CredentialRequestV1_0_11 = CommonCredentialRequest &
export type CredentialRequestV1_0_12 = CommonCredentialRequest &
(CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVc | CredentialRequestSdJwtVc);

export interface AuthorizationRequestV1_0_11 extends AuthorizationDetailsJwtVcJson, AuthorizationDetailsJwtVcJson {
issuer_state?: string;

export interface AuthorizationRequestV1_0_12 extends AuthorizationDetailsJwtVcJson, AuthorizationDetailsJwtVcJson {
}

// todo https://sphereon.atlassian.net/browse/VDX-185
export function isAuthorizationRequestV1_0_11(request: CommonAuthorizationRequest): boolean {
export function isAuthorizationRequestV1_0_12(request: CommonAuthorizationRequest): boolean {
return request && 'issuer_state' in request;
}
2 changes: 1 addition & 1 deletion packages/issuer-rest/lib/OID4VCIServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class OID4VCIServer<DIDDoc extends object> {
}

private assertAccessTokenHandling(tokenEndpointOpts?: ITokenEndpointOpts) {
const authServer = this.issuer.issuerMetadata.authorization_server
const authServer = this.issuer.issuerMetadata.authorization_servers
if (this.isTokenEndpointDisabled(tokenEndpointOpts)) {
if (!authServer) {
throw Error(
Expand Down
2 changes: 1 addition & 1 deletion packages/issuer-rest/lib/oid4vci-api-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function accessTokenEndpoint<DIDDoc extends object>(
opts: ITokenEndpointOpts & ISingleEndpointOpts & { baseUrl: string | URL },
) {
const tokenEndpoint = issuer.issuerMetadata.token_endpoint
const externalAS = issuer.issuerMetadata.authorization_server
const externalAS = issuer.issuerMetadata.authorization_servers
if (externalAS) {
console.log(`[OID4VCI] External Authorization Server ${tokenEndpoint} is being used. Not enabling issuer token endpoint`)
return
Expand Down
2 changes: 1 addition & 1 deletion packages/issuer/lib/VcIssuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
CredentialOfferFormat,
CredentialOfferPayloadV1_0_11,
CredentialOfferSession,
CredentialOfferV1_0_11,
CredentialOfferV1_0_12,
CredentialRequestV1_0_11,
CredentialResponse,
DID_NO_DIDDOC_ERROR,
Expand Down
2 changes: 1 addition & 1 deletion packages/issuer/lib/__tests__/VcIssuerBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('VcIssuer builder should', () => {
.withCredentialsSupported(credentialsSupported)
.build()

expect(vcIssuer.issuerMetadata.authorization_server).toEqual('https://authorization-server')
expect(vcIssuer.issuerMetadata.authorization_servers).toEqual('https://authorization-server')
expect(vcIssuer.issuerMetadata.display).toBeDefined()
expect(vcIssuer.issuerMetadata.credentials_supported[0].id).toEqual('UniversityDegree_JWT')
})
Expand Down
2 changes: 1 addition & 1 deletion packages/issuer/lib/builder/VcIssuerBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class VcIssuerBuilder<DIDDoc extends object> {
}

public withAuthorizationServer(authorizationServer: string): this {
this.issuerMetadata.authorization_server = authorizationServer
this.issuerMetadata.authorization_servers = authorizationServer
return this
}

Expand Down
2 changes: 1 addition & 1 deletion packages/issuer/lib/functions/CredentialOfferUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
CredentialIssuerMetadataOpts,
CredentialOfferPayloadV1_0_11,
CredentialOfferSession,
CredentialOfferV1_0_11,
CredentialOfferV1_0_12,
Grant,
PIN_VALIDATION_ERROR,
UniformCredentialOffer,
Expand Down

0 comments on commit 566f8a9

Please sign in to comment.