Endpoints

The holder API is comprised of a set of endpoints that orchestrate the issuance or presentation of verifiable credentials. The holder endpoints assume the sequences implied by the verce-issuer and verce-verifier endpoints.

The primary endpoints for issuance are:

  • Offer - processes an offer of a credential from the issuer and asks the issuer for metadata.
  • Accept - receives acceptance from the holder to accept the offer.
  • PIN - receives a PIN from the holder in cases where the issuer requires one and has sent the PIN via another channel.
  • Get Credential - requests an access token from the issuer and then uses it to request the credential(s) on offer.

The primary endpoints for presentation are:

  • Request - processes a request for presentation from a verifier.
  • Authorize - receives authorization from the holder to make the presentation.
  • Present - presents the requested credentials to the verifier.

Exposing Endpoints

While the OpenID specification assumes HTTP endpoints for the issuer and verifier services, it may not be a practical protocol for a wallet. However, this does not mean it cannot be used. The repository provides a non-HTTP example (using Tauri) but the following is a minimal example web server exposing endpoints required to support a minimal Pre-Authorized flow example. The example uses axum, but any Rust web server should suffice.

#[tokio::main]
async fn main() {
    // http endpoints
    let router = Router::new()
        .route("/offer", post(offer))
        .route("/accept", post(accept))
        .route("/pin", post(pin))
        .route("/credential", post(credential))
        .route("/request", post(request))
        .route("/authorize", post(authorize))
        .route("/present", post(present))
        .with_state(Provider::new());  // <- set up requisite providers in server state

    // run the server
    let listener = TcpListener::bind("0.0.0.0:8080").await.expect("should bind");
    axum::serve(listener, router).await.expect("server should run");
}

Endpoint handlers

In our example above, we have defined handlers for each axum route. Each handler is responsible for converting the HTTP request to a request object that can be passed to the associated endpoint.

The following example shows how the offer handler uses axum to wrap the heavy lifting of converting the HTTP request body to an OfferRequest object ready to forward to the endpoint.

async fn offer(
    State(provider): State<Provider>,                 // <- get providers from state
    Json(mt req): Json<OfferRequest>,                 // <- convert request body
) -> AxResult<Issuance> {
    vercre_holder::offer(provider, &req).await.into() // <- forward to library
}

More On Endpoints

The following sections describe each endpoint in more detail, highlighting the implementer responsibilities and exepected behavior.

Offer

The Offer endpoint receives an offer for a credential from an issuer. This could be implemented, for example, by presenting a QR code to the wallet and passing the retrieved offer to this endpoint. The endpoint will get issuer and credential metadata from the issuer and stash state for subsequent steps in the issuance flow.

The endpoint returns the metadata information so that it can be displayed for consideration of acceptance by the holder.

Accept

The Accept endpoint receives advice from the holder to proceed with issuance.

PIN

The PIN endpoint receives a PIN from the holder in cases where the issuer requires one and has sent the PIN via another channel.

Get Credential

The Get Credential endpoint requests an access token from the issuer and then uses it to request the credential(s) on offer. If required, the PIN will be used in the request. The credentials will be stored in a repository provided by the implementer.

Request

The Request endpoint processes a request for presentation from a verifier. The request can be a fully-formed presentation request or a URI that the wallet can use to retrieve the request from the verifier. In the latter case, using the implementer's provider, the presentation request is retrieved.

The endpoint then looks for the requested credentials in the repository provided by the implementer and returns a rich representation of the presentation request so that it can be considered by the holder for authorization.

Authorize

The Authorize endpoint receives advice from the holder to proceed with presentation.

Present

The Present endpoint presents the requested credentials to the verifier. As required by the OpenID for Verifiable Presentations specification, the credentials are packaged as a Presentation Submission, signed by the implementer's Signer provider.