The Inji VCI Client is a Kotlin-based library built to simplify credential issuance via OpenID for Verifiable Credential Issuance (OID4VCI) protocol. It supports Issuer Initiated (Credential Offer) and Wallet Initiated (Trusted Issuer) flows, with secure proof handling, PKCE support, and custom error handling.
Add the following dependency to your build.gradle to include the library from Maven Central:
implementation "io.inji:inji-vci-client:0.7.0"- The
VCIClientis constructed with atraceabilityIdwhich is used to track the session and traceability of the credential request.
val traceabilityId = "sample-trace-id"
val vciClient = VCIClient(traceabilityId)| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| traceabilityId | String | Yes | N/A | Unique identifier for the session |
Retrieve the issuer metadata from the credential issuer's well-known endpoint.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialIssuer | String | Yes | N/A | URI of the Credential Issuer |
IssuerMetadata object containing details like credential_endpoint, credential_issuer, and other IssuerMetadata information from the well-known endpoint of Credential Issuer, which can be used by the consumer to display Issuer information, etc.
Note: This method does not parse the metadata, it simply returns the raw Network response of well-known endpoint as a
Map<String, Any>.
val issuerMetadata : Map<String, Any> = VCIClient(traceabilityId).getIssuerMetadata(
credentialIssuer = "https://example.com/issuer"
)
//The response looks similar to this
mapOf(
"credential_issuer" to "https://example.com/issuer",
"credential_endpoint" to "https://example.com/issuer/credential",
)Retrieve credential configurations supported for given issuer from its well-known endpoint.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialIssuer | String | Yes | N/A | URI of the Credential Issuer |
Map of credential_configurations_supported objects containing details like format, scope and other configuration
information from the well-known endpoint of Credential Issuer, which can be used by the consumer to display supported
credential types, etc.
Note: This method does not parse the metadata, it simply returns the raw Network response of well-known endpoint as a
Map<String, Any>.
val credentialConfigurationsSupported : Map<String, Any> = VCIClient(traceabilityId).getCredentialConfigurationsSupported(
credentialIssuer = "https://example.com/issuer"
)
//The response looks similar to this
mapOf(
"credentialConfigId-1" to mapOf(
"format" to "ldp_vc",
"credential_definition" to mapOf(
"type" to listOf("VerifiableCredential", "ExampleCredential")
)
),
"credentialConfigId-2" to mapOf(
"format" to "mso_mdoc",
"doctype" to "org.iso.18013.5.1.mDL"
)
)- Method:
fetchCredentialUsingCredentialOffer - This method allows you to fetch a credential using a credential offer, which can be either an embedded JSON or a URI pointing to the credential offer.
- It supports both Pre-Authorization and Authorization flows.
- The library handles the PKCE flow internally.
- User-trust based credential download supported through onCheckIssuerTrust callback.
- This method is the recommended way to request credential using credential offer.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialOffer | String | Yes | N/A | Credential offer as embedded JSON or credential_offer_uri |
| clientMetadata | ClientMetadata | Yes | N/A | Contains client ID and redirect URI |
| getTxCode | TxCodeCallback | No | N/A | Optional callback function for TX Code (for Pre-Auth flows) |
| authorizations | List | Yes | N/A | Callback functions list to handle authorization and return the resultant authorization response (for Authorization flows) see authorization details |
| getTokenResponse | TokenResponseCallback | Yes | N/A | Callback function to exchange Authorization Grant with Access Token response |
| getProofJwt | ProofJwtCallback | Yes | N/A | Callback function to prepare proof-jwt for Credential Request |
| onCheckIssuerTrust | CheckIssuerTrustCallback | No | null | Callback function to get user trust with the Credential Issuer |
| downloadTimeoutInMillis | Long | No | 10000 | Download timeout set for Credential Request call with Credential Issuer (defaults to 10000 ms) |
An instance of CredentialResponse containing:
| Name | Type | Description |
|---|---|---|
| credential | JsonElement | The credential downloaded from the Issuer |
| credentialConfigurationId | String | The identifier of the respective supported credential from well-known response |
| credentialIssuer | String | URI of the Credential Issuer |
val credentialResponse: CredentialResponse = vciClient.fetchCredentialUsingCredentialOffer(
credentialOffer = "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fsample-issuer.com%2Fcredential-offer",
clientMetadata = ClientMetadata(clientId = "sample-client-id", redirectUri = "https://sample-wallet.com/callback"),
getTxCode = object : TxCodeCallback {
override suspend fun invoke(p1: String?, p2: String?, p3: Int?): String {
// Handle the transaction code retrieval logic here
val txCode = "sampleTxCode"
return txCode
}
},
authorizations = listOf(
// Presentation During Issuance flow for authorization
AuthorizationMethod.PresentationDuringIssuance(
selectCredentialsForPresentation = selectCredentialsForPresentationCallback(),
signVerifiablePresentation = signVerifiablePresentationCallback(),
ldpVpSignatureSuite = "Ed25519Signature2020"
),
// Redirect to Web flow for Web view authorization
AuthorizationMethod.RedirectToWeb(openWebPage = openWebPageCallback())
),
getTokenResponse = object : TokenResponseCallback {
override suspend fun invoke(tokenRequest: TokenRequest): TokenResponse {
// Handle the token response retrieval logic here
//Exchange authorization code for access token
return TokenResponse(
accessToken = "sampleAccessToken",
cNonce = "sampleNonce",
tokenType = "Bearer",
expiresIn = 3600,
cNonceExpiresIn = 3600,
)
}
},
getProofJwt = object : ProofJwtCallback {
override suspend fun invoke(
credentialIssuer: String,
cNonce: String?,
proofSigningAlgorithmsSupported: List<String>
): String {
// Prepare payload for JWT
//Sign the JWT with the private key as per the proofSigningAlgorithmsSupported
val jwt = "sampleProofJwt"
return jwt
}
},
onCheckIssuerTrust = object : CheckIssuerTrustCallback {
override suspend fun invoke(
credentialIssuer: String,
issuerDisplay: List<Map<String, Any>>
): Boolean {
// Handle the issuer trust check logic here
return true // Assume the issuer is trusted for this example
}
},
downloadTimeoutInMillis = 10000
)
//Consider the credential is a Driver's license credential (credential format `mso_mdoc`)
val credentialResponse = vciClient.fetchCredentialUsingCredentialOffer(credentialOffer, clientMetadata, getTxCode, authorizations, getTokenResponse, getProofJwt, onCheckIssuerTrust, downloadTimeoutInMillis)
credentialResponse.credential // This will be a JsonElement containing the credential data. eg - JsonPrimitive("omdk...t")
credentialResponse.credentialConfigurationId // eg - "DriversLicense"
credentialResponse.credentialIssuer // eg - "https://sample-issuer.com"- Method:
requestCredentialByCredentialOffer - This method allows you to request a credential using a credential offer, which can be either an embedded JSON or a URI pointing to the credential offer.
- It supports both Pre-Authorization and Authorization flows.
- The library handles the PKCE flow internally.
- User-trust based credential download supported through onCheckIssuerTrust callback.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialOffer | String | Yes | N/A | Credential offer as embedded JSON or credential_offer_uri |
| clientMetadata | ClientMetadata | Yes | N/A | Contains client ID and redirect URI |
| getTxCode | TxCodeCallback | No | N/A | Optional callback function for TX Code (for Pre-Auth flows) |
| authorizeUser | AuthorizeUserCallback | Yes | N/A | Handles authorization and returns the code (for Authorization flows) |
| getTokenResponse | TokenResponseCallback | Yes | N/A | Callback function to exchange Authorization Grant with Access Token response |
| getProofJwt | ProofJwtCallback | Yes | N/A | Callback function to prepare proof-jwt for Credential Request |
| onCheckIssuerTrust | CheckIssuerTrustCallback | No | null | Callback function to get user trust with the Credential Issuer |
| downloadTimeoutInMillis | Long | No | 10000 | Download timeout set for Credential Request call with Credential Issuer (defaults to 10000 ms) |
An instance of CredentialResponse containing:
| Name | Type | Description |
|---|---|---|
| credential | JsonElement | The credential downloaded from the Issuer |
| credentialConfigurationId | String | The identifier of the respective supported credential from well-known response |
| credentialIssuer | String | URI of the Credential Issuer |
val credentialResponse: CredentialResponse = vciClient.requestCredentialByCredentialOffer(
credentialOffer = "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fsample-issuer.com%2Fcredential-offer",
clientMetadata = ClientMetadata(clientId = "sample-client-id", redirectUri = "https://sample-wallet.com/callback"),
getTxCode = object : TxCodeCallback {
override suspend fun invoke(p1: String?, p2: String?, p3: Int?): String {
// Handle the transaction code retrieval logic here
val txCode = "sampleTxCode"
return txCode
}
},
authorizeUser = object : AuthorizeUserCallback {
override suspend fun invoke(authEndpoint: String): String {
// Handle the user authorization logic here
val authCode = "sampleAuthCode"
return authCode
}
},
getTokenResponse = object : TokenResponseCallback {
override suspend fun invoke(tokenRequest: TokenRequest): TokenResponse {
// Handle the token response retrieval logic here
//Exchange authorization code for access token
return TokenResponse(
accessToken = "sampleAccessToken",
cNonce = "sampleNonce",
tokenType = "Bearer",
expiresIn = 3600,
cNonceExpiresIn = 3600,
)
}
},
getProofJwt = object : ProofJwtCallback {
override suspend fun invoke(
credentialIssuer: String,
cNonce: String?,
proofSigningAlgorithmsSupported: List<String>
): String {
// Prepare payload for JWT
//Sign the JWT with the private key as per the proofSigningAlgorithmsSupported
val jwt = "sampleProofJwt"
return jwt
}
},
onCheckIssuerTrust = object : CheckIssuerTrustCallback {
override suspend fun invoke(
credentialIssuer: String,
issuerDisplay: List<Map<String, Any>>
): Boolean {
// Handle the issuer trust check logic here
return true // Assume the issuer is trusted for this example
}
},
downloadTimeoutInMillis = 10000
)
//Consider the credential is a Driver's license credential (credential format `mso_mdoc`)
val mdocCredentialResponse = vciClient.requestCredentialByCredentialOffer(credentialOffer, clientMetadata, getTxCode, authorizeUser, getTokenResponse, getProofJwt, onCheckIssuerTrust, downloadTimeoutInMillis)
credentialResponse.credential // This will be a JsonElement containing the credential data. eg - JsonPrimitive("omdk...t")
credentialResponse.credentialConfigurationId // eg - "DriversLicense"
credentialResponse.credentialIssuer // eg - "https://sample-issuer.com"- Method:
fetchCredentialFromTrustedIssuer - It supports Authorization flow.
- The library handles the PKCE flow internally.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialIssuer | String | Yes | N/A | URI of the Credential Issuer |
| credentialConfigurationId | String | Yes | N/A | Identifier of the respective supported credential from well-known response |
| clientMetadata | ClientMetadata | Yes | N/A | Contains client ID and redirect URI |
| authorizations | List | Yes | N/A | Callback functions list to handle authorization and return the resultant authorization response (for Authorization flows) see authorization details |
| getTokenResponse | TokenResponseCallback | Yes | N/A | Callback function to exchange Authorization Grant with Access Token response |
| getProofJwt | ProofJwtCallback | Yes | N/A | Callback function to prepare proof-jwt for Credential Request |
| downloadTimeoutInMillis | Long | No | 10000 | Download timeout set for Credential Request call with Credential Issuer (defaults to 10000 ms) |
An instance of CredentialResponse containing:
| Name | Type | Description |
|---|---|---|
| credential | JsonElement | The credential downloaded from the Issuer |
| credentialConfigurationId | String | The identifier of the respective supported credential from well-known response |
| credentialIssuer | String | URI of the Credential Issuer |
val credentialResponse: CredentialResponse = vciClient.fetchCredentialFromTrustedIssuer(
credentialIssuer = "https://sample-issuer.com",
credentialConfigurationId = "DriversLicense",
clientMetadata = ClientMetadata(
clientId = "sample-client-id",
redirectUri = "https://sample-wallet.com/callback"
),
authorizations = listOf(
// Presentation During Issuance flow for authorization
AuthorizationMethod.PresentationDuringIssuance(
selectCredentialsForPresentation = selectCredentialsForPresentationCallback(),
signVerifiablePresentation = signVerifiablePresentationCallback(),
ldpVpSignatureSuite = "Ed25519Signature2020"
),
// Redirect to Web flow for Web view authorization
AuthorizationMethod.RedirectToWeb(openWebPage = openWebPageCallback())
),
getTokenResponse = object : TokenResponseCallback {
override suspend fun invoke(tokenRequest: TokenRequest): TokenResponse {
// Handle the token response retrieval logic here
//Exchange authorization code for access token
return TokenResponse(
accessToken = "sampleAccessToken",
cNonce = "sampleNonce",
tokenType = "Bearer",
expiresIn = 3600,
cNonceExpiresIn = 3600,
)
}
},
getProofJwt = object : ProofJwtCallback {
override suspend fun invoke(
credentialIssuer: String,
cNonce: String?,
proofSigningAlgorithmsSupported: List<String>
): String {
// Prepare payload for JWT
//Sign the JWT with the private key as per the proofSigningAlgorithmsSupported
val jwt = "sampleProofJwt"
return jwt
}
},
downloadTimeoutInMillis = 10000
)
//Consider the credential is a Driver's license credential (credential format `mso_mdoc`)
val mdocCredentialResponse = vciClient.fetchCredentialFromTrustedIssuer(credentialIssuer, credentialConfigurationId, clientMetadata, authorizations, getTokenResponse, getProofJwt, downloadTimeoutInMillis)
credentialResponse.credential // This will be a JsonElement containing the credential data. eg - JsonPrimitive("omdk...t")
credentialResponse.credentialConfigurationId // eg - "DriversLicense"
credentialResponse.credentialIssuer // eg - "https://sample-issuer.com"- Method:
requestCredentialFromTrustedIssuer - This method allows you to request a credential from a trusted issuer of Wallet.
- It supports Authorization flow.
- The library handles the PKCE flow internally.
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| credentialIssuer | String | Yes | N/A | URI of the Credential Issuer |
| credentialConfigurationId | String | Yes | N/A | Identifier of the respective supported credential from well-known response |
| clientMetadata | ClientMetadata | Yes | N/A | Contains client ID and redirect URI |
| authorizeUser | AuthorizeUserCallback | Yes | N/A | Handles authorization and returns the code (for Authorization flows) |
| getTokenResponse | TokenResponseCallback | Yes | N/A | Callback function to exchange Authorization Grant with Access Token response |
| getProofJwt | ProofJwtCallback | Yes | N/A | Callback function to prepare proof-jwt for Credential Request |
| downloadTimeoutInMillis | Long | No | 10000 | Download timeout set for Credential Request call with Credential Issuer (defaults to 10000 ms) |
An instance of CredentialResponse containing:
| Name | Type | Description |
|---|---|---|
| credential | JsonElement | The credential downloaded from the Issuer |
| credentialConfigurationId | String | The identifier of the respective supported credential from well-known response |
| credentialIssuer | String | URI of the Credential Issuer |
val credentialResponse: CredentialResponse = vciClient.requestCredentialFromTrustedIssuer(
credentialIssuer = "https://sample-issuer.com",
credentialConfigurationId = "DriversLicense",
clientMetadata = ClientMetadata(
clientId = "sample-client-id",
redirectUri = "https://sample-wallet.com/callback"
),
authorizeUser = object : AuthorizeUserCallback {
override suspend fun invoke(authEndpoint: String): String {
// Handle the user authorization logic here
val authCode = "sampleAuthCode"
return authCode
}
},
getTokenResponse = object : TokenResponseCallback {
override suspend fun invoke(tokenRequest: TokenRequest): TokenResponse {
// Handle the token response retrieval logic here
//Exchange authorization code for access token
return TokenResponse(
accessToken = "sampleAccessToken",
cNonce = "sampleNonce",
tokenType = "Bearer",
expiresIn = 3600,
cNonceExpiresIn = 3600,
)
}
},
getProofJwt = object : ProofJwtCallback {
override suspend fun invoke(
credentialIssuer: String,
cNonce: String?,
proofSigningAlgorithmsSupported: List<String>
): String {
// Prepare payload for JWT
//Sign the JWT with the private key as per the proofSigningAlgorithmsSupported
val jwt = "sampleProofJwt"
return jwt
}
},
downloadTimeoutInMillis = 10000
)
//Consider the credential is a Driver's license credential (credential format `mso_mdoc`)
val mdocCredentialResponse = vciClient.requestCredentialFromTrustedIssuer(credentialIssuer, credentialConfigurationId, clientMetadata, authorizeUser, getTokenResponse, getProofJwt, downloadTimeoutInMillis)
credentialResponse.credential // This will be a JsonElement containing the credential data. eg - JsonPrimitive("omdk...t")
credentialResponse.credentialConfigurationId // eg - "DriversLicense"
credentialResponse.credentialIssuer // eg - "https://sample-issuer.com"The authorizations parameter is a list of Authorization objects indicating the supported authorizations of the Wallet for the download flow. Currently, library supports two authorization flows - Redirect To Web and Presentation During Issuance. Library exposes the supported authorization flows via class - AuthorizationMethod
- Redirect To Web (for Authorization flow)
Redirect the user to the authorization endpoint (authorization server) in a web view or browser, and get the authorization response parameters back after successful authorization.
Parameters :
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| openWebPage | OpenWebPageCallback | Yes | N/A | Callback function to open the authorization endpoint in a web view or browser, and return the authorization response parameters (e.g., code, state) after successful authorization. |
Example usage
AuthorizationMethod.RedirectToWeb(
openWebPage = object : OpenWebPageCallback {
override suspend fun invoke(authorizationEndpoint: String): Map<String, String> {
// Handle the user authorization logic here
// Open a web view or browser with the authorizationEndpoint
// Return the authorization response parameters (e.g., code, state)
val result: Map<String, String> = openWebViewAndGetResult(authorizationEndpoint)
return result
}
}
)Note: The Redirect to Web flow for an interactive authorization flow is exposed as an experimental API, and is expected to be improved in future releases.
- Presentation During Issuance
Presentation During Issuance flow allows the Wallet to present a verifiable presentation to the Credential Issuer during the credential download process, which can be used by the issuer to verify certain claims about the user before issuing the credential. The authorization for the download here is presentation of another credential (or a verifiable presentation) instead of user interaction-based authorization as in Redirect To Web flow.
This implementation follows - OpenID4VCI v1.1 Specification Commit
Note:
- While this library primarily implements OpenID4VCI draft 13 and 11, the Presentation During Issuance feature follows the v1.1 specification as mentioned above.
- For Presentation During Issuance flow, this VCI client library internally uses inji-openid4vp library to construct the VP and handle the presentation exchange with the issuer.
Parameters :
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| selectCredentialsForPresentation | SelectCredentialsForPresentationCallback | Yes | N/A | Callback function to select credentials from the wallet to be presented to the issuer during issuance as per the Issuer's request. The callback will be invoked with a VP request, this VP request will be used by the Wallet to ask the user for selecting the credentials and then the selected credentials are returned back |
| signVerifiablePresentation | SignVerifiablePresentationCallback | Yes | N/A | Callback function to sign the data which will be used for Verifiable Presentation construction. The callback will be invoked with the data to be signed, and the wallet needs to sign this data with the appropriate key and return the signature back to the library. |
| ldpVpSignatureSuite | String | No | null | The signature suite to be used for signing the VP in case of LDP VCs. It is mandatory to provide this parameter if the credential being requested is of format ldp_vc. The library will use this information to prepare the proof for the Verifiable Presentation accordingly. Supported values are - Ed25519Signature2020, Ed25519Signature2018, JsonWebSignature2020 and RSASignature2018. |
Example usage
AuthorizationMethod.PresentationDuringIssuance(
selectCredentialsForPresentation = object : SelectCredentialsForPresentationCallback {
override suspend fun invoke(
presentationRequest: AuthorizationRequest
): Map<String, Map<FormatType, List<Any>>> {
// Handle the logic to select credentials from the wallet as per the presentation request
// Handle the logic for obtaining consent from the user for presenting the credentials to the issuer
val selectedCredentials: Map<String, Map<FormatType, List<Any>>> = selectCredentials(presentationRequest)
return selectedCredentials
}
},
signVerifiablePresentation = object : SignVerifiablePresentationCallback {
override suspend fun invoke(
payload: List<UnsignedVPTokenV2>
): List<VPTokenSigningResultV2> {
// Handle the logic to sign the data with the appropriate key as per the credential descriptor and signature suite
// From UnsignedVPTokenV2 use the data like format, holderKeyReference and signatureAlgorithm to identify the key to be used for signing and the algorithm to be used for signing the dataToSign, and then return the signature result to the library
val signedData : List<VPTokenSigningResultV2> = signDataForVP(payload)
// since the payload is a list of data to be signed for each credential, the result is also a list containing the signature result for each credential, and the library will take care of constructing the VP with the respective proof for each credential accordingly
// To avoid any confusion, the library will expect the implementation of this callback to return a list of signature results corresponding to each credential in the same order as the payload, and the library will match the signature result with the respective credential based on the order of the payload list.
return signedData
}
},
ldpVpSignatureSuite = "Ed25519Signature2020"
)For more details on the Presentation During Issuance flow and the expected implementation of the callbacks, please refer to the inji-wallet Presentation During Issuance documentation
- Method:
requestCredential - Request for credential from the providers (credential issuer), and receive the credential back.
Note: This method is deprecated and will be removed in future releases. Please migrate to
requestCredentialByCredentialOffer()orrequestCredentialFromTrustedIssuer().
| Name | Type | Required | Default Value | Description |
|---|---|---|---|---|
| issuerMetadata | IssuerMetaData | Yes | N/A | Data object of the issuer details |
| proofJwt | Proof | Yes | N/A | The proof used for making credential request. Supported proof types : JWT. |
| accessToken | String | Yes | N/A | token issued by providers based on auth code |
- Format:
ldp_vc
val issuerMetadata = IssuerMetaData(
CREDENTIAL_AUDIENCE,
CREDENTIAL_ENDPOINT,
DOWNLOAD_TIMEOUT,
CREDENTIAL_TYPE,
CredentialFormat.LDP_VC )
- Format:
mso_mdoc
val issuerMetadata = IssuerMetaData(
CREDENTIAL_AUDIENCE,
CREDENTIAL_ENDPOINT,
DOWNLOAD_TIMEOUT,
DOC_TYPE,
CLAIMS,
CredentialFormat.MSO_MDOC )
- Format:
vc+sd-jwt
val issuerMetadata = IssuerMetaData(
CREDENTIAL_AUDIENCE,
CREDENTIAL_ENDPOINT,
DOWNLOAD_TIMEOUT,
VCT,
CredentialFormat.VC_SD_JWT )
- Format:
dc+sd-jwt
val issuerMetadata = IssuerMetaData(
CREDENTIAL_AUDIENCE,
CREDENTIAL_ENDPOINT,
DOWNLOAD_TIMEOUT,
VCT,
CredentialFormat.DC_SD_JWT )
An instance of CredentialResponse containing:
| Name | Type | Description |
|---|---|---|
| credential | JsonElement | The credential downloaded from the Issuer |
| credentialConfigurationId | Null | N/A |
| credentialIssuer | Null | N/A |
val credentialResponse = vciClient.requestCredential(
issuerMetaData = IssuerMetaData(
CREDENTIAL_AUDIENCE,
CREDENTIAL_ENDPOINT,
DOWNLOAD_TIMEOUT,
DOC_TYPE,
CLAIMS,
CredentialFormat.MSO_MDOC ),
proofJwt = JWTProof(jwtValue = "sampleProofJwt"),
accessToken = "sampleAccessToken"
)
credentialResponse.credential // This will be a JsonElement containing the credential data. eg - JsonPrimitive("omdk...t")
credentialResponse.credentialConfigurationId // This will be null
credentialResponse.credentialIssuer // This will be nullThe following methods are deprecated and will be removed in future releases. Please migrate to the suggested alternatives.
| Method Name | Description | Deprecated Since | Suggested Alternative |
|---|---|---|---|
| requestCredentialFromTrustedIssuer | Request for the download of Verifiable Credential through trusted flow has been improvised to accept different authorizations (web / presentation during issuance) | 0.7.0 | fetchCredentialFromTrustedIssuer |
| requestCredentialByCredentialOffer | Request for download of Verifiable Credential through Credential Offer flow has been improvised to accept different authorizations (web / presentation during issuance). | 0.7.0 | fetchCredentialUsingCredentialOffer |
| requestCredential | Request for credential from the providers (credential issuer), and receive the credential back. | 0.4.0 | fetchCredentialUsingCredentialOffer() or fetchCredentialFromTrustedIssuer() |
- PKCE (Proof Key for Code Exchange) handled internally (RFC 7636)
- Supports
S256code challenge method - Secure
c_noncebinding via proof JWTs
All exceptions thrown by the library are subclasses of VCIClientException.
They carry structured error codes like VCI-001, VCI-002 etc., to help consumers identify and recover from failures.
| Code | Exception Type | Description |
|---|---|---|
| VCI-001 | AuthorizationServerDiscoveryException |
Failed to discover authorization server |
| VCI-002 | DownloadFailedException |
Failed to download Credential issuer |
| VCI-003 | InvalidAccessTokenException |
Access token is invalid |
| VCI-004 | InvalidDataProvidedException |
Required details not provided |
| VCI-005 | InvalidPublicKeyException |
Invalid public key passed metadata |
| VCI-006 | NetworkRequestFailedException |
Network request failed |
| VCI-007 | NetworkRequestTimeoutException |
Network request timed-out |
| VCI-008 | OfferFetchFailedException |
Failed to fetch credentialOffer |
| VCI-009 | IssuerMetadataFetchException |
Failed to fetch issuerMetadata |
| VCI-011 | InteractiveAuthorizationException |
Failed to perform Interactive authorization (Presentation During Issuance / Redirect to Web interaction) |
Mock-based tests are available covering:
- Credential download flow (offer + trusted issuer)
- Proof JWT signing callbacks
- Token exchange logic
See
VCIClientTestfor full coverage
- Kotlin: 1.9+
- JVM: Java 17
- Android: minSdk 23, compileSdk 34
- Gradle: 8.0+
- AGP (Android Gradle Plugin): 8.0+
Architecture decisions are noted as ADRs here.