Migrating from Okta
UniAuth is a standards-compliant OIDC provider. If your app uses Okta's discovery URL and any certified OIDC library, migration is mostly swapping the issuer. This page covers the edge cases.
Endpoint Mapping
| Okta | UniAuth |
|---|---|
| /.well-known/openid-configuration | /.well-known/openid-configuration |
| /oauth2/default/.well-known/openid-configuration | /.well-known/openid-configuration |
| /oauth2/v1/keys | /.well-known/jwks.json |
| /oauth2/v1/authorize | /api/oauth/authorize |
| /oauth2/v1/token | /api/oauth/token |
| /oauth2/v1/userinfo | /api/oauth/userinfo |
| /oauth2/v1/logout | /api/oauth/end-session |
| /oauth2/v1/revoke | /api/oauth/revoke |
| /oauth2/v1/introspect | /api/oauth/introspect |
| /oauth2/v1/device/authorize | /api/oauth/device |
| /oauth2/v1/clients | /api/oauth/register |
Authorization Servers: Okta has multiple (Org AS + Custom AS at/oauth2/{asId}). UniAuth has one, rooted at https://uniauth.id. Point your library at that issuer; discovery does the rest.
Claim Mapping
| Okta claim | UniAuth claim | Notes |
|---|---|---|
| sub | sub | Okta ties sub to user ID; UniAuth uses pairwise HMAC (different per app) |
| Standard | ||
| email_verified | email_verified | Standard |
| name | name | Standard |
| given_name | given_name | Standard |
| family_name | family_name | Standard |
| preferred_username | preferred_username | Standard |
| locale | locale | Standard |
| zoneinfo | zoneinfo | Standard |
| groups | groups | Requires 'groups' scope on both sides |
| cid / uid / scp | — | Okta-specific; UniAuth uses standard aud + scope |
| idp / idp_type | — | Okta federation metadata; use groups claim instead |
| auth_time | auth_time | Standard |
| amr | amr | Both emit pwd, mfa, otp, hwk, face, fpt |
| acr | acr | UniAuth: urn:uniauth:acr:pwd / :mfa / :passkey |
Key Behavioral Differences
1. Pairwise subject identifiers
Okta's sub is the internal user ID, identical across apps. UniAuth computes a per-client pairwisesub so two apps see different values for the same user. If you correlate users across apps via sub, stop — use email or federated identity instead.
2. Access tokens are opaque on Okta Org AS
Okta's Org Authorization Server emits opaque access tokens that must be introspected. UniAuth always emits JWT access tokens (HS256). If your resource server was calling /introspect on every request, switch to local JWT verification via our JWKS — faster, cheaper, no network.
3. Hooks / Inline Hooks → Custom Claims
Okta Inline Hooks run a synchronous webhook during token issuance to inject claims. UniAuth equivalents:
- Static / DB-driven claims → per-client Custom Claim Mappings in the developer console (
static:value,user.field,role) - Dynamic / external lookup → call your backend from the client after login; do not block token issuance
4. Authorization Policies
Okta has per-AS policies with client / user / MFA / network conditions. UniAuth equivalents live in the admin console:
- Network zones / IP allowlist →
ip_access_list(admin → Conditional Access) - MFA step-up → request
acr_values=urn:uniauth:acr:mfain the authorize request - User group restrictions → restrict per client via
access_policies - Risk-based auth → built-in threat detection (new IP / new UA / impossible travel); surfaces as access decisions
5. Sign-on rules / Device Trust
Okta Device Trust requires their MDM integration. UniAuth uses cookie-based Trusted Devices (signed, expiring, revocable) that skip 2FA on known devices — configurable lifetime, user-revocable from /account/security.
User Migration
Three common strategies:
Gradual (recommended)
Keep Okta live. When a user signs in to UniAuth for the first time, provision the account via SCIM from Okta or via bulk import (POST /api/admin/users/import).
Passwords: users reset on first login (magic link or password reset) — password hashes don't migrate.
Export + bulk import
Export users via Okta Users API (GET /api/v1/users), transform to the UniAuth import JSON schema, POST to /api/admin/users/import (max 10,000 per request).
Users will need to set a password or use magic links on first login.
SCIM from Okta
UniAuth exposes SCIM 2.0. Configure Okta as the SCIM client pointing at your UniAuth tenant; Okta pushes users + groups. Useful during coexistence.
Minimal Code Diff
If you used a certified OIDC library (openid-client, spring-boot-starter-oauth2-client, mozilla-django-oidc, omniauth_openid_connect), usually this is it:
- issuer: https://{yourOrg}.okta.com/oauth2/default
- issuer: https://{yourOrg}.okta.com
+ issuer: https://uniauth.id
- client_id: 0oa…
- client_secret: …
+ client_id: uni_…
+ client_secret: unis_…