Go to developer

Authentication Challenges

After enrollment, each login or step-up creates a short-lived challenge the user must approve.

On this page
YOUR LOGIN UI       YOUR BACKEND          KEYRA              USER DEVICE
     │                    │                  │                     │
     │ Credentials        │                  │                     │
     ├───────────────────►│                  │                     │
     │                    │ get2FAStatus     │                     │
     │                    ├─────────────────►│                     │
     │                    │ enrolled: true   │                     │
     │                    │◄─────────────────┤                     │
     │                    │ startAuthentication                    │
     │                    ├─────────────────►│                     │
     │                    │ challengeUrl     │                     │
     │                    │◄─────────────────┤                     │
     │ Show QR            │                  │                     │
     │◄───────────────────┤                  │                     │
     │                    │                  │◄──── open/scan ─────┤
     │                    │                  │──── user verifies ──►│
     │                    │ waitForChallengeApproval               │
     │                    ├─────────────────►│                     │
     │                    │ approved + token │                     │
     │                    │◄─────────────────┤                     │
     │                    │ consumeChallenge │                     │
     │                    ├─────────────────►│                     │
     │                    │ consumed: true   │                     │
     │                    │◄─────────────────┤                     │
     │                    │ Create YOUR app session                │
     │ Authenticated      │                  │                     │
     │◄───────────────────┤                  │                     │
Challenge path

Prerequisites

  • Identity enrolled (get2FAStatusenrolled: true / status active).
  • Secret Partner credentials on your backend.

If not enrolled: HTTP 404 not_enrolled — run enrollment first.

Start a challenge

SERVERTypeScript
const challenge = await keyra.startAuthentication(externalUserId, {
  nonce: optionalOpaqueString, // max 256 chars
  returnUrl: optionalHttpsUrl, // must satisfy project callback rules
});
responseResponse
JSON
{
  "challengeId": "…",
  "status": "pending",
  "expiresIn": 120,
  "challengeUrl": "https://get-started.keyra.ie/challenge/…",
  "pollAfterMs": 1500
}

Challenge lifetime at creation: 120 seconds. SDK adds qrCode as an alias of challengeUrl.

Display the challenge

SERVER → browserTypeScript
import QRCode from "qrcode";
const qrDataUrl = await QRCode.toDataURL(challenge.qrCode);
// Browser: <img src={qrDataUrl} alt="KEYRA verification QR" />
// Keep challenge.challengeId on the server/session for wait + consume.

What happens here? Your backend creates the challenge; KEYRA hosts the user verification UI at challengeUrl; your UI only presents that URL as QR or link.

Wait for approval

SERVERTypeScript
// Recommended helper (timeout 120s, interval 1.5s; honors pollAfterMs)
const approved = await keyra.waitForChallengeApproval(challenge.challengeId);

// Manual polling
const snap = await keyra.pollChallenge(challenge.challengeId);
// When status === "approved", read verificationToken ONCE, then consume.

Defaults: timeout 120s, interval 1500ms.

Terminal states

StatusMeaningSDK behavior
approvedUser verified; token may be presentwaitForChallengeApproval resolves
deniedUser deniedthrows KeyraChallengeDeniedError
expiredTimer elapsed while pending/scanned/otp_sentthrows KeyraChallengeExpiredError
consumedAlready consumedDo not consume again

Intermediate: pending, scanned, otp_sent.

Next step

Approval alone is not application login. Continue to consume / verification.

Try challenges in Playground →