How it works

The Paspo ID authentication flow, step by step.

Integration requires a single call on the client — authenticate(scope, nonce) — which returns a one-time authorization code. Your app forwards that code to your server, which exchanges it with Paspo ID for the user's data.

All communication between your app and Paspo ID is end-to-end encrypted (ECDH P-256 + AES-256-GCM, with ephemeral keys held only in memory) and handled entirely by the SDK — no cryptographic work is required on your side.

sequenceDiagram
    participant B as Your server
    participant A as Your app (SDK)
    participant P as Paspo ID app
    participant PS as Paspo ID server

    A->>B: request nonce
    B-->>A: nonce
    A->>P: authenticate(scope, nonce)
    Note over A,P: ephemeral ECDH key, end-to-end encrypted
    P->>PS: verify app signature & package
    Note over P: user consent screen
    P-->>A: encrypted response
    Note over A: decrypt -> Success(authCode)
    A->>B: authCode
    B->>PS: exchange authCode (server-to-server)
    PS-->>B: user profile data
  1. Your server generates a nonce and hands it to your app.
  2. Your app calls authenticate(scope, nonce). The SDK generates an ephemeral ECDH key pair and opens the Paspo ID app.
  3. Paspo ID verifies your app's signature and package, then shows the user a consent screen for the requested scope.
  4. On confirmation, Paspo ID returns an encrypted response; the SDK decrypts it and resolves with a one-time authCode.
  5. Your app sends authCode to your server, which exchanges it — server-to-server — with Paspo ID for the user's verified profile data.

Two things stay on your server

These can't be moved to the client — they're what makes the flow secure:

  • Generating the nonce. A fresh, unpredictable nonce per attempt is the protection against replay attacks.
  • Exchanging the authorization code. authCode is single-use and carries no personal data on its own; user data only ever travels over your secure server-to-server channel.

If Paspo ID isn't installed

The SDK detects this, stores the nonce, opens the app/Play Store page for Paspo ID, and returns a NotInstalled result instead of throwing. Once the user installs Paspo ID and retries, the stored nonce is passed along for install attribution. See the Android reference for the exact result type.

What you get back

Your server receives whichever profile fields you requested in scope — phone number, e-mail, national ID, or the user's permanent Paspo ID — never raw biometric data. Face ID and Voice ID matching happens entirely on-device, inside the Paspo ID app.