From 39eaea609ee2ddef3d9d18e8b991e45e449cb064 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Wed, 29 Jan 2025 13:36:49 +0100 Subject: [PATCH 1/4] chore: openapi.yml file for VCI REST API --- .../oid4vci-openapi.yml | 499 ++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml diff --git a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml new file mode 100644 index 00000000..84886b44 --- /dev/null +++ b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml @@ -0,0 +1,499 @@ +openapi: 3.0.0 +info: + title: Sphereon OID4VCI API + version: 1.0.0 + description: Sphereon OpenID for Verifiable Credential Issuance API + +servers: + - url: / + description: Base API path + +components: + schemas: + Error: + type: object + properties: + error: + type: string + error_description: + type: string + + IssueStatusResponse: + type: object + required: + - createdAt + - lastUpdatedAt + - status + properties: + createdAt: + type: number + lastUpdatedAt: + type: number + status: + type: string + enum: + - OFFER_CREATED + - OFFER_URI_RETRIEVED + - ACCESS_TOKEN_REQUESTED + - ACCESS_TOKEN_CREATED + - CREDENTIAL_REQUEST_RECEIVED + - CREDENTIAL_ISSUED + - NOTIFICATION_CREDENTIAL_ACCEPTED + - NOTIFICATION_CREDENTIAL_DELETED + - NOTIFICATION_CREDENTIAL_FAILURE + - ERROR + error: + type: string + clientId: + type: string + + AuthorizationChallengeRequest: + type: object + properties: + client_id: + type: string + issuer_state: + type: string + auth_session: + type: string + scope: + type: string + code_challenge: + type: string + code_challenge_method: + type: string + enum: [ plain, S256 ] + presentation_during_issuance_session: + type: string + + AuthorizationChallengeResponse: + type: object + required: + - authorization_code + properties: + authorization_code: + type: string + + AccessTokenRequest: + type: object + required: + - grant_type + properties: + client_id: + type: string + code: + type: string + code_verifier: + type: string + grant_type: + type: string + enum: + - authorization_code + - urn:ietf:params:oauth:grant-type:pre-authorized_code + - password + pre-authorized_code: + type: string + redirect_uri: + type: string + scope: + type: string + user_pin: + type: string + tx_code: + type: string + + AccessTokenResponse: + type: object + required: + - access_token + properties: + access_token: + type: string + scope: + type: string + token_type: + type: string + expires_in: + type: number + c_nonce: + type: string + c_nonce_expires_in: + type: number + authorization_pending: + type: boolean + interval: + type: number + + NotificationRequest: + type: object + required: + - event + properties: + event: + type: string + event_description: + type: string + notification_id: + type: string + + CredentialResponse: + type: object + properties: + credential: + oneOf: + - type: string + - type: object + format: + type: string + enum: + - jwt_vc_json + - jwt_vc + - ldp_vc + - jwt_vc_json-ld + - vc+sd-jwt + - mso_mdoc + transaction_id: + type: string + acceptance_token: + type: string + c_nonce: + type: string + c_nonce_expires_in: + type: number + notification_id: + type: string + + CredentialRequestV1_0_13: + type: object + required: + - format + properties: + format: + type: string + enum: + - jwt_vc_json + - jwt_vc + - ldp_vc + - jwt_vc_json-ld + - vc+sd-jwt + - mso_mdoc + credential_identifier: + type: string + proof: + $ref: '#/components/schemas/ProofOfPossession' + credential_response_encryption: + type: object + properties: + jwk: + type: object + alg: + type: string + enc: + type: string + + ProofOfPossession: + type: object + required: + - proof_type + - jwt + properties: + proof_type: + type: string + enum: [ jwt ] + jwt: + type: string + + CredentialOfferPayload: + type: object + required: + - credential_issuer + - credential_configuration_ids + properties: + credential_issuer: + type: string + credential_configuration_ids: + type: array + items: + type: string + grants: + type: object + client_id: + type: string + + CredentialOfferRequest: + type: object + properties: + credential_offer: + $ref: '#/components/schemas/CredentialOfferPayload' + credential_offer_uri: + type: string + baseUri: + type: string + scheme: + type: string + pinLength: + type: number + qrCodeOpts: + type: object + credentialDataSupplierInput: + type: object + + IssuerMetadata: + type: object + required: + - credential_configurations_supported + - credential_issuer + - credential_endpoint + properties: + credential_configurations_supported: + type: object + additionalProperties: + $ref: '#/components/schemas/CredentialConfigurationSupported' + credential_issuer: + type: string + credential_endpoint: + type: string + authorization_servers: + type: array + items: + type: string + deferred_credential_endpoint: + type: string + notification_endpoint: + type: string + token_endpoint: + type: string + display: + type: array + items: + $ref: '#/components/schemas/MetadataDisplay' + authorization_challenge_endpoint: + type: string + + CredentialConfigurationSupported: + type: object + required: + - format + properties: + format: + type: string + scope: + type: string + cryptographic_binding_methods_supported: + type: array + items: + type: string + credential_signing_alg_values_supported: + type: array + items: + type: string + proof_types_supported: + type: object + display: + type: array + items: + $ref: '#/components/schemas/CredentialDisplay' + + MetadataDisplay: + type: object + properties: + name: + type: string + locale: + type: string + logo: + type: object + properties: + url: + type: string + alt_text: + type: string + background_color: + type: string + text_color: + type: string + + CredentialDisplay: + type: object + properties: + name: + type: string + locale: + type: string + logo: + type: object + properties: + url: + type: string + alt_text: + type: string + background_color: + type: string + text_color: + type: string + +paths: + /.well-known/openid-credential-issuer: + get: + summary: Get credential issuer metadata + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/IssuerMetadata' + + /.well-known/oauth-authorization-server: + get: + summary: Get authorization server metadata + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + + /webapp/credential-offer-status: + post: + summary: Get credential issuance status + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/IssueStatusResponse' + '404': + description: Credential offer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /authorization-challenge: + post: + summary: Authorization challenge endpoint + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationChallengeRequest' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationChallengeResponse' + + /token: + post: + summary: Access token endpoint + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AccessTokenRequest' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/AccessTokenResponse' + + /credentials: + post: + summary: Get credential endpoint + security: + - bearerAuth: [ ] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialRequestV1_0_13' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialResponse' + + /notification: + post: + summary: Notification endpoint + security: + - bearerAuth: [ ] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotificationRequest' + responses: + '204': + description: Notification processed successfully + '400': + description: Invalid notification request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /webapp/credential-offers/{id}: + get: + summary: Get credential offer + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialOfferPayload' + + /webapp/credential-offers: + post: + summary: Create credential offer + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialOfferRequest' + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + uri: + type: string + userPin: + type: string + txCode: + type: object From 2e00fe0e7475c0818d0727a9e27a44e97c728168 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Wed, 29 Jan 2025 14:21:06 +0100 Subject: [PATCH 2/4] chore: examples & descriptions --- .../oid4vci-openapi.yml | 109 ++++++++++++------ 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml index 84886b44..e4f4859e 100644 --- a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml +++ b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml @@ -2,24 +2,58 @@ openapi: 3.0.0 info: title: Sphereon OID4VCI API version: 1.0.0 - description: Sphereon OpenID for Verifiable Credential Issuance API - -servers: - - url: / - description: Base API path + description: | + Sphereon OpenID for Verifiable Credential Issuance API + This API allows issuers to provide verifiable credentials to wallets following the OID4VCI specification. components: schemas: Error: + description: Standard error response format type: object properties: error: type: string + description: Error code + example: invalid_request error_description: type: string + description: Human readable error description + example: The credential offer xyz was not found + + CredentialResponse: + description: Response containing the issued credential + type: object + properties: + credential: + oneOf: + - type: string + - type: object + description: The issued credential, either as a JWT string or JSON object + example: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..." + format: + type: string + enum: + - jwt_vc_json + - jwt_vc + - ldp_vc + - jwt_vc_json-ld + - vc+sd-jwt + - mso_mdoc + description: Format of the issued credential + example: jwt_vc_json + c_nonce: + type: string + description: Nonce for subsequent credential requests + example: "b326c4ab-16f1-4304-83e1-4637f8fe4207" + c_nonce_expires_in: + type: number + description: Expiration time of the c_nonce in seconds + example: 300 IssueStatusResponse: type: object + description: Status of a credential issuance request required: - createdAt - lastUpdatedAt @@ -27,10 +61,15 @@ components: properties: createdAt: type: number + description: Unix timestamp of when the request was created + example: 1706533345000 lastUpdatedAt: type: number + description: Unix timestamp of the last status update + example: 1706533346000 status: type: string + description: Current status of the issuance process enum: - OFFER_CREATED - OFFER_URI_RETRIEVED @@ -42,6 +81,7 @@ components: - NOTIFICATION_CREDENTIAL_DELETED - NOTIFICATION_CREDENTIAL_FAILURE - ERROR + example: CREDENTIAL_ISSUED error: type: string clientId: @@ -49,13 +89,20 @@ components: AuthorizationChallengeRequest: type: object + description: Request to initiate authorization challenge properties: client_id: type: string + description: Client identifier + example: "https://wallet.example.com" issuer_state: type: string + description: Opaque state from issuer + example: "a81bc81b-dead-4563-8692-3bc3c7f12897" auth_session: type: string + description: Session identifier for associating subsequent requests + example: "d270fee1-9185-4e60-9901-d291e1338d7a" scope: type: string code_challenge: @@ -136,33 +183,6 @@ components: notification_id: type: string - CredentialResponse: - type: object - properties: - credential: - oneOf: - - type: string - - type: object - format: - type: string - enum: - - jwt_vc_json - - jwt_vc - - ldp_vc - - jwt_vc_json-ld - - vc+sd-jwt - - mso_mdoc - transaction_id: - type: string - acceptance_token: - type: string - c_nonce: - type: string - c_nonce_expires_in: - type: number - notification_id: - type: string - CredentialRequestV1_0_13: type: object required: @@ -205,18 +225,27 @@ components: CredentialOfferPayload: type: object + description: Core credential offer data required: - credential_issuer - credential_configuration_ids properties: credential_issuer: type: string + description: URL of the credential issuer + example: "https://issuer.example.com" credential_configuration_ids: type: array + description: Identifiers for the offered credential configurations items: type: string + example: [ "university_degree_1", "verified_email_2" ] grants: type: object + description: Supported authorization grant types + example: + "urn:ietf:params:oauth:grant-type:pre-authorized_code": + "pre-authorized_code": "d270fee1-9185-4e60-9901-d291e1338d7a" client_id: type: string @@ -239,6 +268,7 @@ components: type: object IssuerMetadata: + description: Credential issuer metadata as defined in the OID4VCI specification type: object required: - credential_configurations_supported @@ -247,12 +277,17 @@ components: properties: credential_configurations_supported: type: object + description: Map of supported credential configurations additionalProperties: $ref: '#/components/schemas/CredentialConfigurationSupported' credential_issuer: type: string + description: URL identifying the credential issuer + example: "https://issuer.example.com" credential_endpoint: type: string + description: URL of the credential endpoint + example: "https://issuer.example.com/credentials" authorization_servers: type: array items: @@ -336,6 +371,7 @@ paths: /.well-known/openid-credential-issuer: get: summary: Get credential issuer metadata + description: Returns the metadata about the credential issuer's capabilities responses: '200': description: Successful response @@ -358,6 +394,7 @@ paths: /webapp/credential-offer-status: post: summary: Get credential issuance status + description: Check the current status of a credential issuance request requestBody: required: true content: @@ -369,6 +406,8 @@ paths: properties: id: type: string + description: Identifier of the credential offer + example: "b326c4ab-16f1-4304-83e1-4637f8fe4207" responses: '200': description: Successful response @@ -420,6 +459,7 @@ paths: /credentials: post: summary: Get credential endpoint + description: Request issuance of a credential security: - bearerAuth: [ ] requestBody: @@ -430,7 +470,7 @@ paths: $ref: '#/components/schemas/CredentialRequestV1_0_13' responses: '200': - description: Successful response + description: Successful response with issued credential content: application/json: schema: @@ -460,12 +500,15 @@ paths: /webapp/credential-offers/{id}: get: summary: Get credential offer + description: Retrieve a specific credential offer by ID parameters: - name: id in: path required: true + description: Unique identifier of the credential offer schema: type: string + example: "b326c4ab-16f1-4304-83e1-4637f8fe4207" responses: '200': description: Successful response From aaef2236e31c651b095185d7fc59c78b9417a4c3 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Wed, 29 Jan 2025 15:15:37 +0100 Subject: [PATCH 3/4] chore: examples & descriptions --- .../oid4vci-openapi.yml | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml index e4f4859e..d02eddee 100644 --- a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml +++ b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml @@ -3,7 +3,7 @@ info: title: Sphereon OID4VCI API version: 1.0.0 description: | - Sphereon OpenID for Verifiable Credential Issuance API + API for OpenID for Verifiable Credential Issuance This API allows issuers to provide verifiable credentials to wallets following the OID4VCI specification. components: @@ -123,31 +123,50 @@ components: AccessTokenRequest: type: object + description: Request for obtaining an access token required: - grant_type properties: client_id: type: string + description: Unique identifier for the client making the request + example: "client-12345" code: type: string + description: Authorization code received from the authorization server + example: "abc123xyz" code_verifier: type: string + description: Code verifier used in the PKCE flow + example: "s256-code-verifier" grant_type: type: string + description: OAuth 2.0 grant type enum: - authorization_code - urn:ietf:params:oauth:grant-type:pre-authorized_code - password + example: "authorization_code" pre-authorized_code: type: string + description: Pre-authorized code used for credential issuance + example: "pre-auth-code-xyz" redirect_uri: type: string + description: The redirect URI where the response should be sent + example: "https://wallet.example.com/callback" scope: type: string + description: The scope of access requested by the client + example: "openid credential" user_pin: type: string + description: PIN required for pre-authorized flows (if applicable) + example: "1234" tx_code: type: string + description: Transaction code for authorization (if applicable) + example: "tx-56789" AccessTokenResponse: type: object @@ -185,11 +204,13 @@ components: CredentialRequestV1_0_13: type: object + description: Request to issue a credential according to OID4VCI v1.0.13 specification required: - format properties: format: type: string + description: Format of the requested credential enum: - jwt_vc_json - jwt_vc @@ -197,19 +218,34 @@ components: - jwt_vc_json-ld - vc+sd-jwt - mso_mdoc + example: "jwt_vc_json" credential_identifier: type: string + description: Identifier of the credential configuration to be issued + example: "UniversityDegree_JWT" proof: $ref: '#/components/schemas/ProofOfPossession' credential_response_encryption: type: object + description: Parameters for response encryption properties: jwk: type: object + description: JWK for encryption + example: { + "kty": "EC", + "crv": "P-256", + "x": "...", + "y": "..." + } alg: type: string + description: Algorithm for encryption + example: "ES256" enc: type: string + description: Content encryption algorithm + example: "A256GCM" ProofOfPossession: type: object @@ -307,65 +343,89 @@ components: CredentialConfigurationSupported: type: object + description: Defines the supported configurations for issuing credentials required: - format properties: format: type: string + description: Format of the credential being issued + example: "jwt_vc_json" scope: type: string + description: Scope of the credential request, if applicable + example: "openid credential" cryptographic_binding_methods_supported: type: array items: type: string + description: Supported cryptographic binding methods credential_signing_alg_values_supported: type: array items: type: string + description: Supported credential signing algorithms proof_types_supported: type: object + description: Types of proof supported for credential issuance display: type: array items: - $ref: '#/components/schemas/CredentialDisplay' + $ref: '#/components/schemas/CredentialsSupportedDisplay' MetadataDisplay: type: object + description: Display metadata for a credential or issuer properties: name: type: string + description: Display name for the credential or issuer + example: "University Degree" locale: type: string + description: Language locale for the display information + example: "en-US" logo: type: object properties: url: type: string + description: URL to the logo image alt_text: type: string + description: Alternative text for the logo background_color: type: string + description: Background color for display components text_color: type: string + description: Text color for display components - CredentialDisplay: + CredentialsSupportedDisplay: type: object + description: Display information for a credential type properties: name: type: string + description: Name of the credential for display purposes locale: type: string + description: Language locale for the credential display logo: type: object properties: url: type: string + description: URL to the credential logo alt_text: type: string + description: Alternative text for the logo background_color: type: string + description: Background color for the credential display text_color: type: string + description: Text color for the credential display paths: /.well-known/openid-credential-issuer: @@ -442,6 +502,7 @@ paths: /token: post: summary: Access token endpoint + description: Issues an access token based on an authorization request requestBody: required: true content: From 1882aac3fa50846abd4bd5703a9e5a77f6d86f14 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Wed, 29 Jan 2025 15:51:14 +0100 Subject: [PATCH 4/4] chore: examples & descriptions --- .../oid4vci-openapi.yml | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml index d02eddee..cddf6df1 100644 --- a/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml +++ b/packages/oid4vci-issuer-rest-api/oid4vci-openapi.yml @@ -202,7 +202,7 @@ components: notification_id: type: string - CredentialRequestV1_0_13: + CredentialRequest: type: object description: Request to issue a credential according to OID4VCI v1.0.13 specification required: @@ -286,22 +286,34 @@ components: type: string CredentialOfferRequest: + description: Request to create a credential offer type: object properties: credential_offer: $ref: '#/components/schemas/CredentialOfferPayload' credential_offer_uri: type: string + description: URI pointing to the credential offer + example: "https://issuer.example.com/credential-offer/123" baseUri: type: string + description: Base URI for constructing offer-related links + example: "https://issuer.example.com" scheme: type: string + description: URI scheme for offer delivery + example: "openid-credential-offer" pinLength: type: number + description: Length of the user PIN if required for authentication + example: 4 qrCodeOpts: type: object + description: Options for generating a QR code representation of the offer credentialDataSupplierInput: type: object + description: Additional input for the credential data supplier, if needed + IssuerMetadata: description: Credential issuer metadata as defined in the OID4VCI specification @@ -528,7 +540,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CredentialRequestV1_0_13' + $ref: '#/components/schemas/CredentialRequest' responses: '200': description: Successful response with issued credential @@ -581,6 +593,7 @@ paths: /webapp/credential-offers: post: summary: Create credential offer + description: Generate and return a new credential offer requestBody: required: true content: @@ -597,7 +610,12 @@ paths: properties: uri: type: string + description: Credential offer URI + example: "https://issuer.example.com/credential-offer/123" userPin: type: string + description: User PIN for access if required + example: "1234" txCode: type: object + description: Transaction code details for tracking