Your app signs the user in to your identity provider with its own SDK (or AppAuth), then posts the token your provider issued to one Orenda endpoint. Orenda tokens come back. No redirect to an Orenda page, no browser round trip. This is one of two ways to do SSO. The other is hosted sign-in. A program can have either or both. Same Orenda user either way.
Enabled per program by the Orenda team. We need your provider’s issuer URL, its JWKS URI, and the audience we should expect (see below). Contact the team.

Which token to post

Pick one when we set up your program.
  • A token for Orenda (preferred). Register Orenda as an API at your provider under the identifier we give you, and have your app request tokens with that audience. Post the access token. It’s minted for Orenda, so a token your app holds for your own backend is never valid here.
  • Your ID token. Tell us the client id of your native app, one per app, and post the ID token. Its aud is that client id.
Either way the token is a JWT signed with your provider’s keys. Nothing changes on our side between the two except what we expect in aud.

1. Sign in to your provider

Standard authorization code flow with PKCE, in the system browser or the platform’s auth session. Request openid email at least, plus the Orenda audience if you chose that option. We check these claims on the token: Signature is checked against your JWKS. Asymmetric algorithms only.

2. Exchange it

Exchange an ID token is public. The token is the credential.
Exchange straight after sign-in, and exchange each token once. An expired token gets a 401 and you’re back to step 1. So does a token you already exchanged: get a new one from your provider rather than posting the old one again. hasPasskey tells you up front whether the user can pass a passkey step-up. When it’s false and your program enforces passkey step-up, offer enrolment before the user reaches a sensitive operation instead of waiting for SCA_MISSING.

3. Use the tokens

Ordinary Orenda tokens. Authorization: Bearer <accessToken> plus x-program-id on every call.

Refresh and sign out

Orenda issued these tokens, so Orenda refreshes them. Not your provider’s token URL.
  • Refresh: Refresh tokens with the refreshToken from the exchange. The response has no new refresh token; keep the one you have.
  • Sign out: Log out with the accessToken. Then end the session at your provider from your app.
  • Refresh token expired: sign in to your provider again and exchange the new token.
Don’t re-exchange to refresh. The exchange turns a fresh provider sign-in into a session; it doesn’t extend one.

First exchange creates the user

First time we see a sub, we create the Orenda user from the token and link them. After that the same sub is the same user, through this endpoint or hosted sign-in.
  • Verified email required. No email_verified: true on a first exchange means 422 and no account. Later exchanges don’t need the email.
  • We never link by email. If an account with that email exists and isn’t linked to this identity, you get 409. Contact support with the user.
Later tokens don’t update the profile. If the email changes at your provider, we keep the original, and passkey enrolment codes go to the one we hold.

Sensitive operations

This is an SSO session. Passkey step-up applies as written: enrol every user, expect SCA_MISSING on payees, international payments, batches, invites, and secure card details.

Sandbox

Your sandbox program has its own registration (issuer, JWKS, audience, which can point at a test tenant). Exchange against the sandbox program id and send x-sandbox: true on API calls as usual.

Errors

Branch on code, not message.