[INJIMOB-3494] add credential-offer and sd-jwt design docs (#2052)

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
This commit is contained in:
abhip2565
2025-08-13 12:56:39 +05:30
committed by GitHub
parent a265a7f5f8
commit 0a7c9e3477
2 changed files with 506 additions and 0 deletions

View File

@@ -0,0 +1,292 @@
## Support of credential offer
This document provides a comprehensive overview of downloading the credential issued from Issuing Authority through credential offer.
### Authorization Support
1. Authorization Code Flow
2. Pre-Authorized Code Flow
### Out of scope
1. Batch credential download
### Actors involved
1. Inji Wallet
2. _inji-vci-client_ (Library for downloading credential)
3. Issuing authority
### Sequence diagram - download credential issued through credential offer for pre-authorized code flow and authorization code flow
```mermaid
sequenceDiagram
participant U as User
participant W as Inji Wallet (Mobile App)
participant VCI as VCI Client Library
participant Certify as Issuing Authority
participant AS as Authorization Server
Note over Certify: Generate QR code to issue credential
W->>Certify: 1. Scan QR code
W->>VCI: 2. Pass scanned credential offer info
Note over VCI: Process credential offer by uri or object
VCI->>Certify: 3. Fetch Issuer metadata<br/>(GET /.well-known/openid-credential-issuer)
Certify-->>VCI: 4. Receive Issuer metadata
Note over VCI: Issuer Metadata is temporarily cached
Note over VCI: Identify the flow type based on the credential offer
Certify->>Certify: 5. Identify the flow type based on the credential offer
alt 5.1 If pre-authorized code flow
VCI->>VCI: 5.1.1 Auth server discovery
alt Requires tx_code
VCI-->>W: 5.1.2 Request for tx_code
U->>W: 5.1.3 User provides tx_code
W->>VCI: 5.1.4 Return tx_code
Note over VCI: Create token request with tx_code
else No tx_code
Note over VCI: Create token request without tx_code
end
else 5.2 If authorization code flow
VCI->>VCI: 5.2.1 Auth server discovery
Note over VCI: create authorization url
VCI-->>W: 5.2.2 Request authorization code
W->>AS: 5.2.3 Redirect to Authorization Server
U->>AS: 5.2.4 User authentication and authorization
AS-->>W: 5.2.5 Redirect back to Wallet with authorization code
W->>VCI: 5.2.5 Return authorization code
Note over VCI: Create token request
end
VCI-->>W: 6. Request for access token<br/>getTokenResponse(tokenRequest)
W->>AS: 7. Request access token
AS-->>W: 8. Return access token with cNonce
W->>VCI: 9. Return access token with cNonce
Note over VCI: Construct the request body for credential request
VCI->>Certify: 10. Credential Request
Certify-->>VCI: 11. Return credential response
VCI-->>W: 12. Return credential response
```
### Steps involved
**Prerequisite -** Generate QR code to issue credential
#### 1. Scan QR code
Wallet scans QR code generated by issuer
````
{
"credential_issuer": "https://example.com/issuer",
"credential_configuration_ids": [
"credential-config-id"
],
"grants": {
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": "412350404962811318869516",
"authorization_server": "https://example.com/authserver"
}
}
}
````
#### 2. Pass scanned credential offer info
After scanning the QR code, pass credential offer info _inji-vci-client_.
````
VCIClient.requestCredentialByCredentialOffer(
credentialOffer,
clientMetadata,
getTxCode,
authorizeUser: () -> authcode,
getTokenResponse: () -> tokenResponse,
getProofJwt: () -> proof,
onCheckIssuerTrust: () -> boolean,
)
Note:
- credentialOffer is credential offer data or uri received from issuer.
- clientMetadata, If it is authorization code flow for client authentication - client-id and redirect-uri
- getTxCode is a callback function to get the tx_code from the user if required.
- authorizeUser is a callback function to authorize the user for the credential request and return authorization code.
- getTokenResponse is a callback function to get the token response from the authorization server.
- getProofJwt is a callback function to create the proof JWT for the credential request.
- onCheckIssuerTrust is a callback function to check if the issuer is trusted or not.
````
#### 3. Fetch Issuer metadata<br/>(GET /.well-known/openid-credential-issuer)
The _inji-vci-client_ fetches the Issuer metadata from the issuing authority to understand the capabilities and requirements for credential issuance.
````
GET credentialIssuer/.well-known/openid-credential-issuer
````
#### 4. Receive Issuer metadata
inji-vci-client receives Issuer's metadata response.
```
{
"credential_issuer": "https://example.com/issuer",
"credential_endpoint": "https://example.com/issuer/credential",
"credential_configurations_supported": {
"credential-config-id": {
"format": "ldp_vc",
"scope": "vc_scope",
"credential_definition": {
"credentialSubject": {
"cliam1": {
"display": [
{
"name": "Claim 1",
"locale": "en"
}
]
},
"claim2": {
"display": [
{
"name": "Claim 1",
"locale": "en"
}
]
}
}
}
}
}
}
```
#### 5. Identify the flow type based on the credential offer
##### 5.1 pre-authorized code flow
If credential offer is created with pre-authorized code
###### 5.1.1 Auth server discovery
The _inji-vci-client_ performs an authorization server discovery to determine the authorization server's endpoint.
```
GET authserver/.well-known/oauth-authorization-server
{
"issuer": "https://example.com/issuer",
"authorization_endpoint": "https://example.com/authserver/authorize",
"token_endpoint": "https://example.com/authserver/token",
"grant_types_supported": [
"authorization_code"
],
"response_types_supported": [
"code"
]
}
```
###### 5.1.2 Request for tx_code if required
_inji-vci-client_ requests a transaction code (tx_code) from the Wallet through getTxCode callback.
###### 5.1.3 User provides tx_code
Wallet prompts screen to accept transaction code. User enters the tx_code received from the issuing authority.
```
{
"tx_code": "412350404962811318869516"
}
```
###### 5.1.4 Return tx_code
Wallet returns the tx_code to the _inji-vci-client_. After receiving tx_code, _inji-vci-client_ creates token request
##### 5.2 authorization code flow
If credential offer is created with authorization code flow
###### 5.2.1 Auth server discovery
The _inji-vci-client_ performs an authorization server discovery to determine the authorization server's endpoint.
```
GET authserver/.well-known/oauth-authorization-server
{
"issuer": "https://example.com/issuer",
"authorization_endpoint": "https://example.com/authserver/authorize",
"token_endpoint": "https://example.com/authserver/token",
"grant_types_supported": [
"authorization_code"
],
"response_types_supported": [
"code"
]
}
```
###### 5.2.2 Request authorization code
The _inji-vci-client_ creates an authorization URL and requests the Wallet to redirect the user to the authorization server.
````
{
"response_type": "code",
"client_id": "your-client-id",
"redirect_uri": "https://your-redirect-uri.com",
"scope": "openid vc_scope",
"state": "random_state_value"
"code_verifier": "random string"
"code-challenge": "random string"
}
````
###### 5.2.3 Redirect to Authorization Server
The Wallet redirects the user to the authorization server with the authorization URL.
###### 5.2.4 User authentication and authorization
The user provide details for authenticates & authorization
###### 5.2.5 Redirect back to Wallet with authorization code
User is redirected back to the Wallet with the authorization code.
```
{
"code": "authorization_code_value"
}
```
#### 6. Request for access token<br/>getTokenResponse(tokenRequest)
The _inji-vci-client_ requests an access token from the authorization server through Wallet by using getTokenResponse callback
#### 7. Request access token
The Wallet sends a request to the authorization server to obtain an access token.
#### 8. Return access token with cNonce
The authorization server returns the access token along with a cNonce (client nonce) to the Wallet.
```
{
"access_token": "access_token_value",
"c_nonce": "c_nonce_value"
}
```
#### 9. Return access token with cNonce
The wallet returns the access token along with a cNonce (client nonce) to the _inji-vci-client_.
#### 10. Credential Request
The _inji-vci-client_ constructs the request body for the credential request using the access token and cNonce.
It then sends the credential request to the issuing authority.
Request is constructed based on credential format - ldp_vc, mso_mdoc.
#### 11. Return credential response
The issuing authority processes the credential request and returns the credential response to the _inji-vci-client_.
Credential response is json if credential format is ldp_vc, and it's base64 url encoded CBOR data if credential format is mso_mdoc.
```
{
"credential": "....."
}
```
#### 12. Return credential response
The _inji-vci-client_ returns the credential response to the Wallet.
```
{
"credential": "<base-64-url-encoded-cbor-data>"
}
```

View File

@@ -0,0 +1,214 @@
## Support of credential format vc+sd-jwt/dc+sd-jwt in Inji Wallet
This document provides a comprehensive overview of the process for downloading and rendering an IETF SD-JWT VC, adhering to the OpenID4VCI specification.
### Scope
- SD-JWT VC download, verification, and rendering in Inji Wallet.
- vc+sd-jwt/dc+sd-jwt credential format for SD-JWT. All non-normative examples are referred for `vc+sd-jwt` format.
- Cryptographic Key Binding - JWK is being used for cryptographic key binding in SD-JWT VC.
### Actors involved
1. Inji Wallet
2. Issuing authority
3. _inji-vci-client_ (Library for downloading credential)
4. _vc-verifier_ (library for verification of downloaded VC)
### Sequence diagram - download & view vc+sd-jwt credential format VC for Wallet Initiated Flow
```mermaid
sequenceDiagram
participant W as Inji Wallet (Mobile App)
participant VCI_Lib as Inji VCI Client (Library)
participant Issuer as Issuing Authority
participant VCVerifier as VC Verifier (Library)
W ->> VCI_Lib: 1. Get Issuer Metadata for given credential issuer
VCI_Lib ->> Issuer: 2. Fetch Issuer Metadata (GET /.well-known/openid-credential-issuer)
Issuer -->> VCI_Lib: 3. Return Issuer well-known metadata
Note over VCI_Lib: Issuer Metadata is temporarily cached
VCI_Lib -->> W: 4. Return Issuer well-known metadata
Note over W: Cache the Issuer Metadata for future use
Note over W: User selects one of the supported credentials
W ->> VCI_Lib: 5. Request Credential from Issuer
VCI_Lib -->> W: 6. Authorize user for credential request and get authorization code and access token
W ->> VCI_Lib: 7. Provide authorization code and access token
Note over VCI_Lib: Construct the request body for credential request
VCI_Lib ->> Issuer: 8. Credential Request
Issuer -->> VCI_Lib: 9. Return vc+sd-jwt format specific Credential response
VCI_Lib -->> W: 10. Return vc+sd-jwt Credential
W ->> VCVerifier: 11. Verify sd-jwt Credential
VCVerifier -->> W: 12. Return Verification Result
Note over W: If verification is successful, proceed to save the credential
Note over W: Use cached Issuer Metadata for rendering
```
#### Steps involved
##### 1. Get Issuer Metadata
Establish communication with the _inji-vci-client_
Fetch Issuer Metadata
````
VCIClient.getIssuerMetadata(credentialIssuer)
Note: credentialIssuer is Credential Issuer Uri received from trusted issuers list.
````
##### 2. Fetch Issuer Metadata
The _inji-vci-client_ fetch issuer's metadata from issuing authority.
````
GET credentialIssuer/.well-known/openid-credential-issuer
````
##### 3. Receive Issuer Metadata Response
_inji-vci-client_ receives Issuer's metadata response.
````
{
"credential_issuer": "https://example.com/issuer",
"credential_endpoint": "https://example.com/issuer/credential",
"credential_configurations_supported":
{
"SD_JWT_VC_example_in_OpenID4VCI": {
"format": "vc+sd-jwt",
"scope": "vc_scope",
"claims": {
"cliam1": {
"display": [
{
"name": "Claim 1",
"locale": "en"
}
]
},
"claim2": {
"display": [
{
"name": "Claim 1",
"locale": "en"
}
]
}
},
"vct": "SD_JWT_VC_example_in_OpenID4VCI",
}
}
}
````
##### 4. Return Issuer Metadata Response
Once the response is received in _inji-vci-client_, it is returned to the Wallet.
##### 5. Request Credential from Issuer
````
VCIClient.requestCredentialFromTrustedIssuer(
credentialIssuer,
credentialConfigurationId,
clientMetadata,
authorizeUser: () -> authcode,
getTokenResponse: () -> tokenResponse,
getProofJwt: () -> proof
)
Note:
- credentialIssuer is Credential Issuer Uri received from trusted issuers list.
- credentialConfigurationId is one of the supported credential configuration id user has selected.
- clientMetadata for client authentication - client-id and redirect-uri
- authorizeUser is a callback function to authorize the user for the credential request and return authorization code.
- getTokenResponse is a callback function to get the token response from the authorization server.
- getProofJwt is a callback function to create the proof JWT for the credential request.
````
##### 6. Authorize user for credential request and get authorization code and access token
_inji-vci-client_ uses `authorizeUser` callback function to authorize the user for the credential request.
This typically involves redirecting the user to an authorization server where they can log in and grant permission
for the credential request.
Once authorization code is received, _inji-vci-client_ uses `getTokenResponse` callback function to exchange the
authorization code for an access token.
For more details check [VCI Client Library](https://github.com/mosip/inji-vci-client/blob/master/kotlin/README.md)
##### 7. Provide authorization code and access token
When the user has successfully authorized the request, the _inji-vci-client_ will receive an authorization code and access token.
##### 8. Create Credential Request and send to Issuing Authority
_inji-vci-client_ will use `CredentialRequestFactory` and create `SdJwtCredentialRequest` request with following body:
````
{
"format": "vc+sd-jwt",
"vct": "SD_JWT_VC_example_in_OpenID4VCI"
"proof": {
"proof_type": "jwt",
"jwt": "eyJraWQiOiJkaWQ6ZXhhbXBsZ...KPxgihac0aW9EkL1nOzM"
}
}
````
and send it to the issuing authority.
##### 9. Receive the Credential Response
The _inji-vci-client_ receives the credential response as jwt string
```
"eyJraWQiOiJkaWQ6ZXhhbXBsZ.eyJpc3N1YW5jZURhdGUiOiIyM.KPxgihac0aW9EkL1nOzM~disclousure1~disclousure1~"
```
##### 10. Return the Credential Response
Once the response is received in _inji-vci-client_, it is returned to the Wallet.
````
{
"credential": "eyJraWQiOiJkaWQ6ZXhhbXBsZ.eyJpc3N1YW5jZURhdGUiOiIyM.KPxgihac0aW9EkL1nOzM~disclousure1~disclousure1~",
"credentialIssuer": "https://example.com/issuer",
"credentialConfigurationId": "SD_JWT_VC_example_in_OpenID4VCI"
}
````
##### 11. Perform vc verification
After obtaining the credential from the issuing authority through the _inji-vci-client_ library, a verification process ensures that the issued Verifiable Credential (VC) remains unaltered through _vc-verifier_ library.
_vc-verifier_ will use `CredentialVerifierFactory` and create `SdJwtVerifiableCredential` to perform validation and verification of the credential.
1. [x] Confirm the credential is not tampered. (Cryptographic Signature Verification)
2. [x] Disclosure Verification to confirm sd claims are not tampered. (Cryptographic Hash Verification)
````
VCVerifier.verify(
credential: "eyJraWQiOiJkaWQ6ZXhhbXBsZ.eyJpc3N1YW5jZURhdGUiOiIyM.KPxgihac0aW9EkL1nOzM~disclousure1~disclousure1~",
credentialFormat: "vc+sd-jwt"
)
````
##### 12. Return VC verification Result
After verifying the VC, return verification result
````
{
"verificationStatus": true,
"verificationMessage": "",
"verificationErrorCode": null
}
````
- ##### VC Rendering:
- Field Labels:
The labels displayed for each field are derived from the Credential Issuer's metadata claims under the display attribute.
Reference: OpenID4VCI Spec - Credential Issuer Metadata.
- Field Ordering:
- As per OpenID4VCI Draft 13, the order property in the issuers well-known configuration defines the order of fields to be displayed.
This structured approach ensures that the credential is rendered accurately and efficiently while maintaining a lightweight storage and transmission footprint.
### Out of scope
- Revocation - Inji Wallet doesn't support revocation for any credential format. So this document does not cover revocation of IETF SD-JWT VC.
- SVG Rendering - Inji Wallet does not support SVG rendering for any credential format. So this document does not cover SVG rendering of IETF SD-JWT VC.