SpruceKit
SpruceID
  • 🌲SpruceKit Introduction
    • Decentralized Identity Overview
    • Glossary
  • ⚡Quickstart
  • SpruceKit Mobile
    • SpruceKit Showcase App
      • Installation
      • Getting Started
      • Issue a Showcase Credential
      • Present a Showcase Credential
    • SpruceKit Mobile SDK
      • Introduction
      • Core Components
        • StorageManager
        • KeyManager
        • CredentialPack
        • Card
        • IsoMdlPresentation
        • mDocReader/IsomDLReader
        • Document Scanner
      • SpruceKit iOS SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
      • SpruceKit Android SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present an mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
  • Verifiable Digital Credentials
    • ⚙️DIDKit
      • Installation
      • Core Concepts
      • DID Methods
      • Runtime Configuration
      • Specifications and Dependencies
      • Quickstart
      • DIDKit Packages
        • Command Line Interface
        • HTTP Server
        • Rust Crate
        • C Interface
        • Java and Android
        • Python
        • Javascript
      • DIDKit Examples
        • Core Functions (CLI)
        • Core Functions (HTTP)
        • did-web in minutes
        • Batch Generation & Verification
    • 🪪ISO mDL
      • Quickstart
      • Core Concepts
      • User Guide
  • Schema Definition Language
    • 🔗TreeLDR
      • TreeLDR Quickstart
        • First Schema
        • Compilation into JSON Schema
        • Compilation into JSON-LD Context
        • Writing a Layout
        • Simple Rust Integration
      • Types
        • Literal Types
      • Layouts
        • Primitive Layouts
        • Literal Layouts
        • Enumeration
        • Array Layout
        • References
      • Compiling
        • Schema Definition Formats
          • JSON Schema
          • JSON-LD Context
          • Resource Description Framework (RDF)
        • Programming Languages
          • Compiling to Rust
      • RDF Vocabulary
      • 💡TreeLDR Basics
        • Types and Layouts
        • Properties
        • Syntax
  • Witness for Credential Claims
    • 🔭Rebase
      • Core Library
      • Rust Client/Witness SDK
      • WASM Client SDK
      • Simple "Basic Post" Schema
      • DNS Witness Flow Schema
  • References
    • Contributing
    • Code of Conduct
Powered by GitBook
On this page
  • Accept a Credential over OID4VCI
  • Storing Credentials

Was this helpful?

  1. SpruceKit Mobile
  2. SpruceKit Mobile SDK
  3. SpruceKit Android SDK
  4. Build a Wallet

Accept a W3C VC

Accept a W3C VC through the OID4VCI protocol

PreviousBuild a WalletNextPresent a W3C VC

Last updated 2 months ago

Was this helpful?

This guide is for Android applications. Building for iOS? 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 . 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 SpruceKit components
import com.spruceid.mobile.sdk.KeyManager
import com.spruceid.mobile.sdk.rs.AsyncHttpClient
import com.spruceid.mobile.sdk.rs.DidMethod
import com.spruceid.mobile.sdk.rs.HttpRequest
import com.spruceid.mobile.sdk.rs.HttpResponse
import com.spruceid.mobile.sdk.rs.Oid4vci
import com.spruceid.mobile.sdk.rs.Oid4vciExchangeOptions
import com.spruceid.mobile.sdk.rs.generatePopComplete
import com.spruceid.mobile.sdk.rs.generatePopPrepare
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO


val client = HttpClient(CIO)

// Start an OID4VCI session with an async http client 
val oid4vciSession =
    Oid4vci.newWithAsyncClient(
        client =
        object : AsyncHttpClient {
            override suspend fun httpClient(
                request: HttpRequest
            ): HttpResponse {
                val res =
                    client.request(request.url) {
                        method = HttpMethod(request.method)
                        for ((k, v) in request.headers) {
                            headers[k] = v
                        }
                        setBody(request.body)
                    }

                return HttpResponse(
                    statusCode = res.status.value.toUShort(),
                    headers =
                    res.headers.toMap().mapValues {
                        it.value.joinToString()
                    },
                    body = res.readBytes()
                )
            }
        }
    )

    //initate the OID4VCI exchange
try {
    oid4vciSession.initiateWithOffer(
        credentialOffer = url,
        clientId = "skit-demo-wallet",
        redirectUrl = "https://spruceid.com"
    )

    val nonce = oid4vciSession.exchangeToken()

    val metadata = oid4vciSession.getMetadata()

    val keyManager = KeyManager()
    keyManager.generateSigningKey(id = "keyID")
    val jwk = keyManager.getJwk(id = "keyID")

    val signingInput =
        jwk?.let {
            generatePopPrepare(
                audience = metadata.issuer(),
                nonce = nonce,
                didMethod = DidMethod.JWK,
                publicJwk = jwk,
                durationInSecs = null
            )
        }

    // Create a signature over the payload
    val signature =
        signingInput?.let {
            keyManager.signPayload(
                id = "reference-app/default-signing",
                payload = signingInput
            )
        }

    // Finalize the Proof of Possession
    val pop =
        signingInput?.let {
            signature?.let {
                generatePopComplete(
                    signingInput = signingInput,
                    signature =
                    Base64.encodeToString(
                        signature,
                        Base64.URL_SAFE or
                                Base64.NO_PADDING or
                                Base64.NO_WRAP
                    )
                        .toByteArray()
                )
            }
        }
    // If needed, set the context, in the example we use VC Playground Json-LD contexts
    oid4vciSession.setContextMap(getVCPlaygroundOID4VCIContext(ctx = ctx))

    //Acquire the credentials from the OID4VCI exchange
    val credentials =
        pop?.let { oid4vciSession.exchangeCredential(
            proofsOfPossession = listOf(pop),
            options = Oid4vciExchangeOptions(true),
        ) }


    // Save the credentials 
    credentials?.forEach { cred ->
        cred.payload.toString(Charsets.UTF_8).let { credential = it }
    }
}

Storing Credentials

There are multiple ways to store Credentials, but the most straightforward 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 in a CredentialPack

val credentialPack = CredentialPack()
credentialPack.tryAddRawCredential(rawCredential)
try credentialPack.save(storageManager: StorageManager())

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

read the specification
specification