OPENID4VP Cross-Device Flow

This document outlines the Cross-Device Flow for digital identity verification, following the OPENID4VP (OpenID for Verifiable Presentations) standard.

1.1 Introduction

The Cross-Device Flow refers to a process where an ANH (Aadhaar Number Holder) initiates a verification or credential presentation on one device—such as a desktop—and completes it on another device—typically a mobile phone. This flow is commonly used in scenarios where verifier services are available from the desktop/laptop or POS devices.

In the OPENID4VP Cross-Device Flow, the ANH presents a Verifiable Presentation (VP) containing Verifiable Credentials (VCs) to a Relying Party (RP).

The flow and specifications outlined in this document conform to the OpenID for Verifiable Presentations - draft 29arrow-up-right

1.2 Abbreviations

Abbreviation
Definition

OPENID4VP

OpenID for Verifiable Presentations

RP

Relying Party (e.g., Verifier requesting credentials)

OP

OpenID Provider (issues or verifies credentials)

VC

Verifiable Credential

VP

Verifiable Presentation

ANH

Aadhaar Number Holder

1.2 Actors

In a cross-device flow, typically, the following actors are engaged for the successful completion of a journey.

  • Aadhaar Number Holder (ANH) or Holder as per the OPENID4VP standards

  • Verifier - an entity that requests, receives, and validates Presentations. The Verifier is a specific case of an OAuth 2.0 Client, just like a Relying Party (RP) in [OpenID.Corearrow-up-right].

  • Aadhaar App - UIDAI app used by the ANH to receive, store, present, and manage Credentials and key material.

1.3 Step-by-Step Explanation of the Flow

1.3.1 Initiate Presentation Request

  • The ANH initiates the process by accessing the Verifier's service (e.g., a login page on a desktop browser or app on the POS device).

  • The Verifier Frontend sends a request to the Verifier Backend to generate a presentation request.

1.3.2 Generate QR Code

  • The Verifier Backend creates a signed JSON Web Token (JWT) with details like redirect_uri, request_uri, state, nonce, scope, response_type and client_id. This JWT encapsulates the Verifiable Presentation (VP) request.

  • The JWT is embedded in a QR code using the Https://maadhaar.com/openid?value=<Base10String> scheme, along with a client_id and the JWT itself.

  • The QR code is returned to the Verifier Frontend and displayed to the ANH.

1.3.2.1 Steps to Create the QR Code

  1. Set Up Claims:

    • Create a JSON object with the following claims:

      • client_id: "https://example.com/"(example)

      • response_type: "vp_token"

      • scope: "openid vp_token"

      • redirect_uri: "https://example.com/getrequest"(example)

      • request_uri: "https://example.com/callback"(example)

      • nonce: A unique UUID (generate a new UUID for each request).

      • state: A unique UUID (generate a new UUID for each request)

Claims Table

Claim Name
Description
Type
Example Value
Purpose

client_id

Identifies the client requesting the token.

String

https://example.gov.in/

Specifies the client in the OpenID Connect flow.

response_type

Indicates the type of response expected (e.g., a verifiable presentation token).

String

vp_token

Defines the response type for the OpenID Connect authorization request.

scope

Specifies the scope of access requested.

String

openid vp_token

Defines the permissions or data access requested (OpenID and vp_token).

redirect_uri

URL to which the response will be sent after processing.

String

https://example.com/openid/getrequest

Redirects the client to this URL after authorization.

request_uri

URL for the callback or request endpoint.

String

https://example.com/openid/callback

Specifies the endpoint for handling the request.

nonce

A unique, random string to prevent replay attacks.

String

123e4567-e89b-12d3-a456-426614174000

Ensures the request is unique and secure.

state

A unique, random string to maintain state between request and response.

String

987fcdeb-1234-5678-90ab-426614174000

Maintains state for correlation between request and callback.

2. Conversion to Base10 String

  • JWT prepared in step 1 is required to be converted to a Base10 value for QR rendering.

  • In the UIDAI sample code, the generateBase10ValueFromJWT method takes the signedToken (the JWT string) and transforms it into a base10 string through the steps listed below.

  1. Convert JWT to Bytes (JWT To ISO 8859-1 encoded Bytes)

  • The JWT string is converted to a byte array using ISO-8859-1 encoding (in go, this is essentially a direct cast of the string to []byte, as strings are UTF-8 by default but treated as raw bytes here).

  • Example: If jwtString is "eyJ...abc", it becomes a byte array []byte("eyJ...abc").

  1. Append Delimiter (Append Delimiter)

  • A delimiter byte (value 255) is appended to the byte array to mark the end of the JWT data.

  • This results in byteArrayWithDelimiter = byteArray + [255].

  1. Compress Data (CompressData)

  • The byte array (with the delimiter) is compressed using gzip compression.

  • A bytesBuffer is used to capture the compressed output, and a gzip. The writer writes the compressed data to it.

  • This produces a smaller compressedData byte array, which is more compact than the original JWT.

  1. Convert to BigInteger (byteArray to BigInt)

  • The compressed byte array is converted to a bigInt (a large integer type from the math/big package) by interpreting the bytes as a big-endian integer.

  • For example, if compressedData is a byte array [0x12, 0x34, 0x56], it becomes a big Int representing the number 0x123456.

  1. Convert to Base10 String (bigIntToBase10String)

  • The bigInt is converted to its decimal (base10) string representation using the String() method.

  • This produces a string of digits (e.g., "123456789") that represents the compressed JWT as a large decimal number

1.3.3 QR Scan

  • The ANH uses the Aadhaar App on their mobile device to scan the QR code displayed on the Verifier's device.

  • The app parses the QR code, validates the JWT signature using JSON Web Key Sets (JWKS), and extracts the presentation request details (e.g., request_id, request_uri).

  • Retrieve presentation _definition: The Aadhaar App sends a GET request to the request_uri (provided in the JWT) to fetch the presentation_definition, which specifies the required credentials (e.g., Aadhaar details like name, email, etc).

1.3.4 Implementation to generate OPENID4VP Request Object (also referred to as presentation_definition)

  • Verifier backend service validates an incoming request from the aadhaar using the JWT (shared through the QR code) from the Authorisation header, extracts nonce and state claims. Post validation of the incoming request, a new JWT and Request Object is prepared, specifying required credential fields (Name, Email, Dob, Address, Mobile).

  • The verifier backend must conform to the following specifications to accept calls from the aadhaar app.

    • HTTP Method: GET

    • Authentication: Requires a valid JWT in the Authorisation header with the Bearer scheme.

    • Response: Returns a JSON object containing a signed JWT or an error message.

1.3.4.1 Request Format

  • HTTP Method: GET

  • Headers:

    • Authorisation: Required. Bearer token (e.g., Bearer <JWT>).

      • JWT must be signed with RS256 and verifiable with the public key from rsa pub cert.pem.

      • JWT payload must include:

  • The <signed_jwt> is signed with RS256 using the private key from rsa privkey.pem and contains:

Claim Name
Type
Description
Example Value

iss

String

Issuer of the JWT.

https://uidai.gov.in/

aud

String

Audience of the JWT.

https://example.gov.in/

client_id

String

Client identifier.

https://example.gov.in/

ac

String

Application-specific code.

000

sc

String

Scope code.

212121

response_type

String

Expected response type.

vp_token

scope

String

Scope of access requested.

openid vp_token

call_back

String

Callback URL for the response.

https://example.com/openid/callback

nonce

String

Unique string from incoming JWT.

123e4567-e89b-12d3-a456-426614174000

txn

String

Transaction ID (maps to state from incoming JWT).

987fcdeb-1234-5678-90ab-426614174000

exp

Integer

Expiration time (Unix timestamp, 1 hour from creation).

1740934440

presentation_definition

Object

Defines required credential fields.

See below

Structure of presentation_definition:

Note: Security considerations

  • The jwt issued in the QR code will be sent in the header for this call for Authentication of the end point.

1.3.5 Aadhaar App Steps

On receipt of the presentation_definition, the aadhaar app performs the following steps for cross-device credential exchange.

  • Intent Signature Verification:

    • The Aadhaar App sends the intent (the request to present credentials) to the UIDAI Backend (CIDR) for signature verification.

    • The UIDAI Backend (CIDR) verifies the intent and returns the result (verified).

  • Face Authentication:

    • The Aadhaar App prompts the ANH to perform FaceAuth (face authentication) for proof of presence verification.

  • Match Aadhaar Credentials:

    • The Aadhaar App retrieves the Aadhaar credentials (e.g., residentName, email, etc.) from the stored Verifiable Credential (VC).

  • Create Verifiable Presentation (VP):

    • The app creates a Verifiable Presentation (VP) containing the requested Aadhaar credentials.

    • The VP is encapsulated in a JWT (SD-JWT) and signed with the Holder's private key to ensure authenticity.

  • Submit VP to Verifier:

    • The New Aadhaar App sends a POST request to the Verifier's callback endpoint (e.g., callback_uri), including the VP, a token, and state.

1.3.6 Call-Back Implementation:

Call-Back UIRL would be hosted by the Verifier backend to receive the credential from aadhaar app. aadhaar app will invoke the callback URL to share the credential in a secured manner.

Endpoint Overview

  • Purpose:

    • Validates an incoming JWT (Refer step 1.3.5) from the Authorization header,

    • Accepts an SD-JWT credential provided in the request body, extracts ANH information Example : (Name, Email, Dob, Address, PhoneNumber)

    • Returns a success or error response with a transaction ID.

      • HTTP Method: POST

      • Authentication: Requires a valid JWT in the Authorization header with the Bearer scheme.

      • Response: Returns a JSON object with a transaction ID, response code, and message indicating success or failure.

The Call-back request from the aadhaaqr app will follow the foloowing standards.

1.3.6.1 Request Format

  • HTTP Method: POST

  • Headers:

    • Authorization: Required. Bearer token (e.g., Authorization: Bearer <JWT>).

Body: JSON object with the following fields:

  • txn: Required. String matching the txn claim in the JWT (e.g., 987fcdeb-1234-5678-90ab-426614174000).

  • token: Required. SD-JWT credential containing ANH information (Name, EmailID, Dob, Address, PhoneNumber).

Example:

1.3.7 Response Format

To get a successful upload by the aadhaar app, the Callback URL is expected to provide a response.

Content-Type: application/json

  • The Verifier Backend validates the VP by verifying the signatures, checking the nonce and state to prevent replay attacks, and ensuring the credentials meet the presentation definition.

  • The Verifier Backend returns a response to the Verifier Frontend with a transaction ID (txnId), responseCode: 200, and responseMsg: "Success". This is a non-normative flow.

  • The Verifier Frontend notifies the ANH of successful verification, granting access to the requested service. This is a non-normative flow.

Last updated