Accept a W3C VC

Accept a W3C VC through the OID4VCI protocol

This guide is for iOS applications. Building for Android? Look here: Accept a W3C VC

Accept a Credential over OID4VCI

This page will not go over how OpenID for Verifiable Credential issuance works, but we do encourage you to read the specification. The example code below shows a particular profile of OID4VCI, which you are not necessarily required to implement, but does illustrate that you can i.e. generate a Proof of Possession with the SpruceKit Core Rust functionality.

// Import the SpruceID Mobile SDK
import SpruceIDMobileSdk
import SpruceIDMobileSdkRs
import SwiftUI

// The value for credentialOffer should be a compliant OID4VCI CredentialOffer
func getCredential(credentialOffer: String) {
    // Instantiate an OID4VCI client
    let client = Oid4vciAsyncHttpClient()
    
    // Start a new OID4VCI session
    let oid4vciSession = Oid4vci.newWithAsyncClient(client: client)
    Task {
        do {
            try await oid4vciSession.initiateWithOffer(
                credentialOffer: credentialOffer,
                // Replace the clientId with your own
                clientId: "skit-demo-wallet",
                // Replace the redirectUrl with your own
                redirectUrl: "https://spruceid.com"
            )

            let nonce = try await oid4vciSession.exchangeToken()

            let metadata = try oid4vciSession.getMetadata()

            // Create key material for the Proof of Possession (PoP)
            _ = KeyManager.generateSigningKey(
                id: "ExampleKeyID")
            let jwk = KeyManager.getJwk(id: "ExampleKeyID")
            
            //Prepare the Proof of Possession
            let signingInput =
                try await SpruceIDMobileSdkRs.generatePopPrepare(
                    audience: metadata.issuer(),
                    nonce: nonce,
                    didMethod: .jwk,
                    publicJwk: jwk!,
                    durationInSecs: nil
                )

            // Create a signature
            let signature = KeyManager.signPayload(
                id: "ExampleKeyID",
                payload: [UInt8](signingInput))

            // Finalize the PoP
            let pop = try SpruceIDMobileSdkRs.generatePopComplete(
                signingInput: signingInput,
                signature: Data(Data(signature!).base64EncodedUrlSafe.utf8)
            )

            // Set your Json-LD context maps.
            // This example uses a function that loads in VC Playground contexts.
            try oid4vciSession.setContextMap(
                values: getVCPlaygroundOID4VCIContext())

            self.credentialPack = CredentialPack()
            
            // Acquire Credentials
            let credentials = try await oid4vciSession.exchangeCredential(
                proofsOfPossession: [pop],
                options: Oid4vciExchangeOptions(verifyAfterExchange: true)
            )
            
            // Add your credential to a CredentialPack
            try credentials.forEach {
                let cred = String(decoding: Data($0.payload), as: UTF8.self)
                _ = try self.credentialPack?.addJsonVc(
                    jsonVc: JsonVc.newFromJson(utf8JsonString: cred))
                self.credential = cred
            }

        } catch {
            err = error.localizedDescription
            print(error)
        }
    }
}

There is a lot of optionality in the OID4VCI protocol, and this code example only reflects one profile. Be sure to use the OID4VCI protocol in the way you want by studying the specification

Storing Credentials

There are multiple ways to store Credentials, but the most straight forward way is to use a CredentialPack. Even if you intend to store only a single credential in a CredentialPack, the component offers the most convenient API for interactions with other SpruceKit components.

// Store a Credential by adding your credential to a CredentialPack

let credentialPack = CredentialPack()
// Use the tryAddRawCredential API to store any supported credential format
_ = try credentialPack.tryAddRawCredential(rawCredential: rawCredential)
try credentialPack.save(storageManager: StorageManager())

Last updated

Was this helpful?