Data Wallet (OpenID4VC) SDKs
The following steps outline how developers can integrate EUDI Wallet OpenID4VC SDKs for Android and iOS into their existing Android or iOS applications.
Step 01: Installation
Use the following code to add depedency:
- Android
- iOS
repositories {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.decentralised-dataexchange:eudi-wallet-oidc-android:2024.5.1'
}
Additional dependencies:
dependencies {
implementation("com.nimbusds:nimbus-jose-jwt:9.21")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
}
Follow the instructions below to add the SDK to your iOS project:
- File > Swift Packages > Add Package Dependency
- Enter the URL of the package: https://github.com/decentralised-dataexchange/eudi-wallet-oidc-ios and click Next.
- Choose the version or branch you want and click Next.
- Select the target to which you want to add the package and click Finish.
Verifiable Credential Issuance Functions
Initialise
The following function allows you to initialise the issuance service class with the required parameters.
- Android
- iOS
val issueService = IssueService()
Import the EUDI wallet SDK as follows:
import eudiWalletOidcIos
To create instance of an issuance service, use the following function:
let keyHandler = CryptoKitHandler()
let issueService = eudiWalletOidcIos.IssueService(keyHandler: keyHandler)
NOTE: The classes in which the functions are implemented should conform to NSObject.
Resolve Credential offer
This function allows resolving the credential offer received from the issuer. A credential offer may have a grant specified. It can be either:
- Pre-Authorized code flow
- Authorization code flow
- Android
- iOS
val credentialOffer = issueService.resolveCredentialOffer(data)
let credentialOffer = try await issueService?.resolveCredentialOffer(credentialOffer:data)
Issuer Metadata
This function allows to perform discovery and fetch issuer metadata.
- Android
- iOS
val discoveryService = DiscoveryService()
val issuerMetadata= discoveryService.getIssuerConfig("${credentialOffer?.credentialIssuer}/.well-known/openid-credential-issuer")
let issuerMetadata = try await eudiWalletOidcIos.DiscoveryService.shared.getIssuerConfig(credentialIssuerWellKnownURI: credentialOffer.credentialIssuer)
Authorisation Server Metadata
This function allows to perform discovery and fetch authorisation server metadata.
- Android
- iOS
val authorisationServerMetadata = DiscoveryService().getAuthConfig("${issuerMetadata?.issuerConfig?.authorizationServer}/.well-known/openid-configuration"
)
let authorisationServerMetadata = try? await eudiWalletOidcIos.DiscoveryService.shared.getAuthConfig(authorisationServerWellKnownURI: issuerMetadata.authorizationServer)
Authorisation Request
This section outlines the steps to perform the authorization request for credential issuance.
Step 1: Identify the Code Flow
Determine whether the issuance is an Authorized code flow or Pre-authorized code flow using the following code:
- Android
- iOS
val isPreAuthFlow = credentialOffer.grants?.preAuthorizationCode != null
let isPreAuthFlow = credentialOffer.grants?.urnIETFParamsOauthGrantTypePreAuthorizedCode
Step 2: Create DID and Public/Private Key Pair
Create Public/Private Key Pair
The following function allows to create a random public/private key pair and Json Web Key (JWK) for the same:
- Android
- iOS
val jwk = DIDService().createJWK(cryptographicAlgorithm = CryptographicAlgorithms.ES256)
let jwk = await eudiWalletOidcIos.DidService.shared.createJWK(keyHandler: keyHandler)
Create DID
The following function allows to create a did:key
identifier from a JSON Web Key (JWK).
- Android
- iOS
val did = DIDService().createDID(jwk, cryptographicAlgorithm = CryptographicAlgorithms.ES256)
let did = await didKeyHandler.shared.createDID(jwk: jwk.0)
Step 3: Generate Code Verifier for Proof Key for Code Exchange (PKCE)
The following function allows to create a code verifier for Proof Key for Code Exchange (PKCE):
- Android
- iOS
val codeVerifier = CodeVerifierService().generateCodeVerifier()
let codeVerifier = codeVerifierHandler.shared.generateCodeVerifier()
Step 4: Send Authorisation Request
The following function allows to send authorisation request to issuer's authorisation server endpoint and obtain the authorisation response.
- Android
- iOS
val authorisationResponse = issueService.processAuthorisationRequest(
did,
jwk,
credentialOffer,
codeVerifier,
authorisationServerMetadata?.authConfig?.authorizationEndpoint
)
val authorisationCode = Uri.parse(authorisationResponse).getQueryParameter("code")
let authorisationCode = await issueService?.processAuthorisationRequest(did: did, secureKey: jwk.1, credentialOffer: credentialOffer, codeVerifier: codeVerifier, authServer: authorisationServerMetadata)
Token Request
The following function allows to sent token request to the issuer's token endpoint and obtain the access token/refresh token pair.
- Android
- iOS
val tokenResponse= issueService.processTokenRequest(
did = did,
tokenEndPoint = authorisationServerMetadata?.authConfig?.tokenEndpoint,
code = authorisationCode,
codeVerifier = codeVerifier,
isPreAuthorisedCodeFlow = isPreAuthFlow ,
userPin = null
)
let tokenResponse = await issueService?.processTokenRequest(did: did, tokenEndPoint: authorisationServerMetadata.tokenEndpoint, code: code , codeVerifier: codeVerifier, isPreAuthorisedCodeFlow: false, userPin: nil)
Credential Request
Credentials can be issued in two ways: InTime and Deferred.
- InTime issuance: The credential is provided immediately as a response.
- Deferred issuance: The credential is issued after a processing period, which can take minutes to hours.
The following function allows to sent credential request to credential endpoint using the access token and nonce obtained from the previous step:
- Android
- iOS
val credentialResponse = issueService.processCredentialRequest(did, jwk, nonce, credentialOffer, issuerMetadata?.issuerConfig, accessToken, format)
Format can be obtained from the issuerMetadata, Use
issuerService.getFormatFromIssuerConfig(issuerMetadata?.issuerConfig, <Credential type>)
let credentialResponse = await issueService?.processCredentialRequest(did: did, secureKey: jwk.1, nonce: tokenResponse.cNonce, credentialOffer: credentialOffer, issuerConfig: issuerMetadata, accessToken: tokenResponse.accessToken, format: "")
In the response, you will receive the credential. Sometimes, instead of credentials, you will only receive an acceptance token. If the response contains an acceptance token, you need to follow the deferred credential flow.
Deferred Credential Request
The following function allows to sent deferred credential request to deferred credential endpoint using the acceptance token obtained from the previous step:
- Android
- iOS
val credentialResponse = issueService.processDeferredCredentialRequest(acceptanceToken, issuerMetadata.issuerConfig?.deferredCredentialEndpoint)
let credentialResponse = await issueService?.processDeferredCredentialRequest(acceptanceToken: acceptanceToken, deferredCredentialEndPoint: issuerConfig.deferredCredentialEndpoint)
Verifiable Presentation Functions
Authorisation Request
This function allows to resolve the authorisation request from the verifier containing the presentation definition:
- Android
- iOS
val authorisationRequest = VerificationService().processAuthorisationRequest(data)
let authorisationRequest = await verificationHandler.processAuthorisationRequest(data: data)
Authorisation Response
This function allows to send the authorisation response with VP token and presentation submission to the verifier.
Step 1: Filter the Matching Credentials against Presentation Definition
- Android
- iOS
val filteredCredentials = VerificationService().filterCredentials(<All credentials in the storage>, authorisationRequest)
let filteredCredentials = verificationHandler.filterCredentials(credentialList:<All stored credentials>, presentationDefinition: presentationDefinitionModel)
Step 2: Send Authorisation Response
- Android
- iOS
val authorisationCode = VerificationService().sendVPToken(did, jwk, authorisationRequest, filteredCredentials)
let authorisationCode = await verificationHandler.sendVPToken(did: did, secureKey: jwk.1, authorisationRequest: presentationRequest, credentialsList: [filteredCredentials])