diff --git a/vcr/oidc4vci/docs/README.md b/vcr/oidc4vci/docs/README.md deleted file mode 100644 index 84c1b00251..0000000000 --- a/vcr/oidc4vci/docs/README.md +++ /dev/null @@ -1,231 +0,0 @@ -# Prototype for OIDC4VCI - -## Resources: -[Notes on the wiki](https://wiki.nuts.nl/books/credential-issuance-and-presentation/page/notes-on-exploring-credential-issuance) - -## Request examples -Here we describe all the requests and responses for obtaining the NutsAuthorizationCredential. - -In this interaction are 2 roles involved: - -**The issuer**: - -This is the care organisation that wants to offer a NutsAuthorizationCredential to authorize the another care organisation (Holder) to access patient information. -* Hosted at `https://issuer.example` -* Identified by `did:nuts:` - -**Holder**: - -This is the care organisation that will be authorized to access the data of the patient. -* Wallet is hosted at `https://wallet.example` -* Identified by `did:nuts:` - -### Sequence diagram: -![Sequence diagram](./flow.png) - -### 1. Credential Offer - -Step described in [OIDC4VCI 4.1. Credential Offer]( https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-credential-offer ). - -`GET` request from the issuer to the wallet's Offer Endpoint. Specifies `credential_offer` JSON object as url-encoded query parameter: - -```json -{ - "credential_issuer": "https://issuer.example", - "credentials": [ - { - "format": "ldp_vc", - "credential_definition": { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://nuts.nl/credentials/v1" - ], - "type": [ - "VerifiableCredential", - "NutsAuthorizationCredential" - ] - } - } - ], - "grants": { - "urn:ietf:params:oauth:grant-type:pre-authorized_code": { - "pre-authorized_code": "" - } - } -} -``` - -Here we use the `ldp_vc` format, which is defined in [OIDC4VCI E.1.3.3. Credential Offer (JSON-LD)](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-e.1.3.3). It specifies the credential_definition as a JSON-LD object. - -Invokes as: - -```http request -GET https://wallet.example/offer/credential_offer?credential_offer= -``` - -Notes: -- Unclear specification for the credential_offer for JSON-LD: - - _4.1.1. Credential Offer Parameters_ specifies REQUIRED `credentials` parameter to contain the credentials that are offered, - each one containing `format` and format-specific fields. - - _E.1.3.3. Credential Offer (JSON-LD)_ specifies these fields for JSON-LD, which specifies REQUIRED `credential_definition`, - but it is unclear whether this is a top-level field of the credential offer, or a field of the `credentials` entry. - Steven: I don't think it is unclear. The `credentials` field should contain a value of list of objects (or strings). And each object should contain a `format` and fields according to that format. - - It also specifies (again) a `credential_issuer` field. Chosen to put `credential_issuer` again inside the credential spec, - since the intention is (probably) that the issuer from 4.1.1 is the OIDC4VCI issuer, while the issuer from E.1.1.3 is the JSON-LD VC issuer(?). - Steven: I think this is an error in the spec, since nowere this extra field is described. - -### 2. Response - -The wallet response with `202 - Accepted` without a body. - -Notes: -- The response is unspecified by the OIDC4VCI spec. - Chosen to return `202 - Accepted` without a body since the request is accepted, - but the Wallet has to decide whether to do something with it. - -### 3. Get Metadata - -Upon accepting the credential offer, the wallet fetches the Credential Issuer Metadata from the well-known metadata endpoint: - -```http request -GET https://issuer.example/identity//.well-known/openid-credential-issuer -``` - -Notes: - -- A domain serving multiple issuers (a vendor serving multiple client care organizations) should map the issuing care - organization to the issuer URL. E.g., it could use the DID of the care organization as subpath of the issuer URL, - e.g.: `https://issuer.example/`. The resulting well-known metadata URL would be: - `https://issuer.example//.well-known/openid-credential-issuer`. - Perhaps when/if we transition to the `did:web` method, we can use the did as the basis for the well-known URL e.g. `did:web:issuer.example:123` would result in `https://issuer.example/123/.well-known/openid-credential-issuer`. - - -### 4. Response - -The official `openid-credential-issuer` metadata does not contain the open id connect endpoints which should be requested separately with a call to the `openid-configuration` well-known endpoint. But by combining the information of the `openid-credential-issuer` and `openid-configuration` endpoints, the wallet only has to make 1 request to get all the required information. - -The issuer responds with the metadata (`application/json`): - -```json -{ - "credential_issuer": "https://issuer.example", - "issuer": "https://issuer.example", - "token_endpoint": "https://issuer.example/token", - "credential_endpoint": "https://issuer.example/credential", - "credentials_supported": [ - { - "format": "ldp_vc", - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://nuts.nl/credentials/v1" - ], - "type": [ - "VerifiableCredential", - "NutsAuthorizationCredential" - ], - "cryptographic_binding_methods_supported": "did:nuts" - } - ] -} -``` - -Notes: - -- What should the wallet do with the info in `credentials_supported`? - It won't support anything else than Nuts's VCs for now anyway(?). - Proposal: just ignore it. - -### 5. Token Request - -The wallet requests an access token from the issuer using the `urn:ietf:params:oauth:grant-type:pre-authorized_code` grant type. - -```http request -POST https://issuer.example/token -Content-Type: application/x-www-form-urlencoded - -grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code&pre-authorized_code= -``` - -### 6. Access Token Response - -The issuer responds `200 OK` with a `application/json` response, if successful: - -```json -{ - "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ", - "token_type": "bearer", - "expires_in": 300, - "c_nonce": "tZignsnFbp", - "c_nonce_expires_in": 300 -} -``` - -### 7. Request NutsAuthorizationCredential - -The wallet uses the credential endpoint from the issuer metadata and the acquired access token to request the credential: - -```http request -POST https://issuer.example/credential - -{ - "format": "ldp_vc", - "credential_definition": { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://nuts.nl/credentials/v1" - ], - "type": [ - "VerifiableCredential", - "NutsAuthorizationCredential" - ], - }, - "proof": { - "proof_type": "jwt", - "jwt": "eyJraWQiOiJkaWQ6ZXhhbXBsZ...KPxgihac0aW9EkL1nOzM" - } -} -``` - -The `jwt` follows the OIDC4VCI RFC, where the `kid` field contains the DID URL of an `authentication` key from the holders DID document. -This key must be used to sign the JWT. - -Note: -- Only `jwt` proof type specified as of now? -- `authentication` verification relationship looks like the most fitting, but current Nuts DID documents don't have this one. - Specifying `authentication` over a relationship which we already use (e.g. `assertionMethod` or `capabilityInvocation`) would involve migration. - -### 8. Response NutsAuthorizationCredential - -The issuer responds with the issued credential: - -```json -{ - "format": "ldp_vc", - "credential": { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://nuts.nl/credentials/v1" - ], - "id": "did:nuts:#123", - "type": [ - "VerifiableCredential", - "NutsAuthorizationCredential" - ], - "issuer": "did:nuts:", - "issuanceDate": "2010-01-01T00:00:00Z", - "credentialSubject": { - "id": "did:nuts:", - "patient": "bsn:999992", - "purposeOfUse": "careviewer" - }, - "proof": { - "type": "Ed25519Signature2020", - "created": "2022-02-25T14:58:43Z", - "verificationMethod": "did:nuts:#key-1", - "proofPurpose": "assertionMethod", - "proofValue": "zeEdUoM7m9cY8ZyTpey83yBKeBcmcvbyrEQzJ19rD2UXArU2U1jPGoEtrRvGYppdiK37GU4NBeoPakxpWhAvsVSt" - } - }, - "c_nonce": "fGFF7UkhLa" -} -``` diff --git a/vcr/oidc4vci/docs/flow-final.puml b/vcr/oidc4vci/docs/flow-final.puml deleted file mode 100644 index fcdb291db8..0000000000 --- a/vcr/oidc4vci/docs/flow-final.puml +++ /dev/null @@ -1,38 +0,0 @@ -@startuml -'https://plantuml.com/sequence-diagram - -title Credential Offer (pre-authorized_code flow) - -autonumber - -box Issuer - participant Issuer - participant "Token Endpoint" as TokenEP - participant "Credential Endpoint" as CredentialEP -end box - -box Holder - participant "Offer Endpoint" as OfferEP - participant Wallet -end box - -group Credential Offer - Issuer -> OfferEP: CredentialOffer(credentials, (pre-authorized_code)) - OfferEP --> Issuer: Ok - Wallet -> Issuer: Get Issuer Metadata - Issuer --> Wallet: Issuer and openid-configuration Metadata -end - -group Obtain access_token (pre-authorized_code) - Wallet -> TokenEP: Token Request (Pre-Authorized Code) - TokenEP --> Wallet: Token Response (access_token, c_nonce) -end - -group Get Credential - Wallet -> CredentialEP: Credential Request (access_token, proof) - CredentialEP --> Wallet: Credential Response (credential) -end - - - -@enduml diff --git a/vcr/oidc4vci/docs/flow-flow-options.puml b/vcr/oidc4vci/docs/flow-flow-options.puml deleted file mode 100644 index a36a98460c..0000000000 --- a/vcr/oidc4vci/docs/flow-flow-options.puml +++ /dev/null @@ -1,52 +0,0 @@ -@startuml -'https://plantuml.com/sequence-diagram - -title Credential Offer Flow with 2 grant types - -autonumber - -box Issuer - participant Issuer - participant "Authorization Server" as IssuerAS - participant "Token Endpoint" as TokenEP - participant "Credential Endpoint" as CredentialEP -end box - -box Holder - participant Wallet - participant OfferEP -end box - -group Credential Offer - Issuer -> Issuer: Store issuer entry - Issuer -> OfferEP: CredentialOffer(credentials, issuer_state) - OfferEP --> Issuer: Ok - Wallet -> Issuer: Get Metadata - Issuer --> Wallet: Metadata - OfferEP -> Wallet: store offer + metadata -end - -Group Get access_token - Wallet -> Wallet: create request - - alt authorization_code flow - Wallet -> IssuerAS: POST issuer/auth?details&redirect=wallet&issuer_state - IssuerAS -> Wallet: 302 wallet/cb?code - Wallet -> Wallet: Get wallet/cb?code - Wallet -> TokenEP: GET issuer/token?code - TokenEP --> Wallet: access_token - else Pre-authorized-code flow - Wallet -> TokenEP: POST issuer/token?pre-authorized_code - TokenEP --> Wallet: access_token - end -end - -group Get Credential - Wallet -> CredentialEP: GET credential - CredentialEP --> Wallet: credential - Wallet -> Wallet: store credential -end - - - -@enduml diff --git a/vcr/oidc4vci/docs/technical-design-class-diagram.puml b/vcr/oidc4vci/docs/technical-design-class-diagram.puml deleted file mode 100644 index fb727bf277..0000000000 --- a/vcr/oidc4vci/docs/technical-design-class-diagram.puml +++ /dev/null @@ -1,31 +0,0 @@ -@startuml -'https://plantuml.com/object-diagram - -title OIDC4VCI Implementation Relationship Diagram - -package "VCR Issuer" { - object "VCR Issuer" as VCRIssuer - object "OIDC4VCI Issuer" as Publisher - package "OIDC4VCI Issuer" { - object Issuer - object "API" as IssuerAPI - object WalletClient - } -} - -package Holder { - object Wallet - object "API" as HolderAPI - object IssuerClient -} - -VCRIssuer -down-> Publisher : Offer(VC) -Publisher->Issuer : offer\nVC using -Issuer->WalletClient : uses -IssuerAPI->Issuer : invokes -WalletClient -down-> HolderAPI : offer credential - -HolderAPI -left-> Wallet : invokes -Wallet -> IssuerClient : uses -IssuerClient -> IssuerAPI : grant flow\nrequest credential -@enduml \ No newline at end of file diff --git a/vcr/oidc4vci/docs/technical-design-sd.puml b/vcr/oidc4vci/docs/technical-design-sd.puml deleted file mode 100644 index 79261a96f5..0000000000 --- a/vcr/oidc4vci/docs/technical-design-sd.puml +++ /dev/null @@ -1,62 +0,0 @@ -@startuml -'https://plantuml.com/sequence-diagram - -title Credential Offer (pre-authorized_code flow) - -autonumber - -box Credential Issuer - participant Issuer - participant OIDC4VCIIssuer as "OIDC4VCI\nIssuer" - participant HolderClient as "Holder\nClient" - participant IssuerAPI as "OIDC4VCI\nAPI" -end box - -box Holder - participant HolderAPI as "OIDC4VCI\nAPI" - participant Wallet - participant IssuerClient as "Issuer\nClient" -end box - -group Credential Offer - ' Issuer - activate Issuer - Issuer->Issuer : Lookup holder\nmdURL - Issuer->OIDC4VCIIssuer ++ : Offer(credential, mdURL) - OIDC4VCIIssuer->OIDC4VCIIssuer ++ : Create session\n(credential) - OIDC4VCIIssuer-->OIDC4VCIIssuer -- : preAuthCode - OIDC4VCIIssuer->OIDC4VCIIssuer ++ : Create offer\n(credential, preAuthCode) - OIDC4VCIIssuer-->OIDC4VCIIssuer -- : offer - OIDC4VCIIssuer->HolderClient **: Create\n(mdURL) - HolderClient->HolderClient ++ : Load md - HolderClient->HolderAPI ++: HTTP GET mdURL - - ' Holder - HolderAPI->Wallet ++ : Get metadata\n(DID) - Wallet-->HolderAPI -- : clientMD - HolderAPI-->HolderClient --: clientMD - - ' Issuer - HolderClient-->OIDC4VCIIssuer -- - OIDC4VCIIssuer->HolderClient ++ : OfferCredential\n(offer) - HolderClient->HolderAPI ++ : HTTP POST\nto clientMD\nOfferEndpoint\n(offer) - - ' Holder - HolderAPI -> Wallet ++ : AcceptCredentialOffer\n(offer) - Wallet -> IssuerClient ** : Create\n(issuer) - IssuerClient -> IssuerClient ++ : Load md\n(issuer/well-known) - IssuerClient -> IssuerAPI ++ : HTTP GET\nmetadataURL - IssuerAPI --> IssuerClient -- : issuerMD - IssuerClient --> Wallet -- - note left - Access token flow starts here - end note - HolderAPI --> HolderClient -- : 202 Accepted - - ' Issuer - HolderClient-->OIDC4VCIIssuer -- - OIDC4VCIIssuer-->Issuer - deactivate Issuer - deactivate OIDC4VCIIssuer -end -@enduml \ No newline at end of file