AnybanQID

Build with AnybanQID

AnybanQID is a private digital identity service operated by Clobe (Pvt) Ltd. Your users prove who they are once, then approve logins, transactions and document signatures in the AnybanQID app โ€” biometric-gated, device-bound. Two integrations work today: CIBA and App approval.

Use cases

๐Ÿ“ฒ Decoupled auth (CIBA)

  • Call centre, POS, kiosk, web โ€” no browser redirect on the user's side.
  • Initiate with login_hint=nic:<nic>, poll the token endpoint (poll mode).
  • The user approves the request in the AnybanQID app.

๐Ÿ’ธ App approval & transactions

  • Confirm logins and payments with signed display data (amount, merchant).
  • Create an order server-side; show it as a QR code or a same-device app link; poll its status.
  • What the user sees is what gets signed.

โœ๏ธ e-Signatures

  • Sign documents with the citizen's device key (PAdES).
  • Signed under a per-citizen certificate issued at their first signature.
  • Multi-signer ordering, hash-reviewed on the phone.

๐Ÿ” Login with AnybanQID โ€” coming soon

  • Web & mobile sign-in by browser redirect โ€” coming soon.
  • Standard OIDC Authorization Code + PKCE. No authorization code is issued yet โ€” use CIBA or App approval today.
  • Assurance levels loa1โ€“loa3 via acr_values.

How a request reaches the citizen

AnybanQID does not send push notifications. A request reaches the AnybanQID app in one of three ways: the citizen scans a QR code you display; they tap an app link on the same phone (https://id.anybanq.lk/app/order/<id> or anybanqid://order/<id>, with an optional ?return=https://โ€ฆ to come back to your site); or it appears when they open the app. Tell the citizen to open AnybanQID when you start a CIBA request.

How a browser login will flow โ€” coming soon

Authorization Code + PKCE โ€” coming soon. No authorization code is issued yet; use CIBA or App approval today.
Your app AnybanQID User's phone GET /oauth2/authorize (code_challenge) request in the app (QR / app link) approve โ€” biometric + device signature 302 ?code=โ€ฆ POST /oauth2/token (code_verifier) access + id + refresh tokens

Signing certificates

Document signatures are made under an X.509 certificate issued to the citizen personally, not a service-held key. That certificate is issued the first time the citizen signs a document (or when they join a company that requires it): the app builds a PKCS#10 CSR from the device's secure-element key, so the private key never leaves the phone. As a relying party you normally never touch these endpoints — the app enrols the certificate when it is first needed — but the states are visible on the signing request, and it is worth knowing the failure modes.

Issuance against the live CA is two-phase. The first call is accepted but does not return a certificate: the CA emails the citizen a PIN, which the second call redeems.

# Phase 1 โ€” submit the CSR. Returns {id, status: "PENDING_PIN"}.
POST /certificate/certificates/requests
{ "type": "SIGNING", "csrPem": "-----BEGIN CERTIFICATE REQUEST-----..." }

# Phase 2 โ€” redeem the emailed PIN. Returns the issued certificate.
POST /certificate/certificates/requests/:id/verify-pin
{ "pin": "..." }

Certificates expire. AnybanQID reminds the citizen ahead of time and marks lapsed certificates EXPIRED, so a signing request can fail for a citizen who signed successfully last year. Handle FAILED as a retryable, explainable state rather than a dead end.

# Renewal โ€” single-phase, no PIN. The replaced certificate becomes SUPERSEDED.
POST /certificate/certificates/:serial/renew
{ "csrPem": "-----BEGIN CERTIFICATE REQUEST-----..." }

A renewed certificate gets a new serial, so anything you have stored against the old one keeps referring to the certificate that actually made those signatures. A revoked certificate cannot be renewed — revocation is a trust decision, not an expiry.

Set up in four steps

Get sandbox credentials

The developer portal is not self-serve yet. Email hello@anybanq.lk for sandbox credentials โ€” you'll get a client id/secret with the CIBA grant enabled if you need decoupled auth.

Discover the endpoints

curl https://id.anybanq.lk/oidc/.well-known/openid-configuration

Start a request โ€” CIBA or App approval

# CIBA (poll mode) โ€” issuer https://id.anybanq.lk/oidc
curl -X POST https://id.anybanq.lk/oidc/oauth2/bc-authorize \
  -u "$ANYBANQID_CLIENT_ID:$ANYBANQID_CLIENT_SECRET" \
  -d 'login_hint=nic:<12-digit NIC>' \
  -d 'scope=openid profile'
# โ†’ { "auth_req_id": "...", "expires_in": 300, "interval": 5 }

curl -X POST https://id.anybanq.lk/oidc/oauth2/token \
  -u "$ANYBANQID_CLIENT_ID:$ANYBANQID_CLIENT_SECRET" \
  -d 'grant_type=urn:openid:params:grant-type:ciba' \
  -d "auth_req_id=$AUTH_REQ_ID"
# pending โ†’ { "error": "authorization_pending" }; approved โ†’ tokens

# App approval โ€” create an order, show it as a QR code or app link, poll its status
curl -X POST https://id.anybanq.lk/api/v1/auth/auth/orders \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  -d '{ "type": "TRANSACTION", "userRef": { "nic": "<12-digit NIC>" },
        "displayData": { "title": "Confirm payment", "amount": 24500, "currency": "LKR" } }'
# โ†’ { "orderId": "...", "expiresAt": "..." }
# QR / link: https://id.anybanq.lk/app/order/<orderId>?return=https://app.example.lk/done

curl https://id.anybanq.lk/api/v1/auth/auth/orders/$ORDER_ID/status \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Handle tokens & refresh

Tokens are ES256-signed; refresh tokens rotate on every use with reuse detection โ€” always store the newest one. Full flow diagrams (app-approval orders, CIBA, error codes) live in the documentation.

Read the full documentation โ†’