Protect a DaloyJS API with Okta
Okta provides workforce and customer identity with granular policies and the API Access Management add-on for issuing custom-scoped access tokens. This guide uses the official @okta/jwt-verifier package (4.x, stable) to validate tokens from a Custom Authorization Server.
- 01asyncClient appOkta Custom Auth ServerUser signs in; Okta issues a scoped access token (RS256)iss = https://{domain}/oauth2/{asId}
- 02requestClient appDaloyJS APICall API with Authorization: Bearer <access token>
- 03asyncDaloyJS APIOkta JWKSOktaJwtVerifier fetches signing keys (cached 1h)jwksRequestsPerMinute throttles fetches
- 04noteDaloyJS APIDaloyJS APIverifyAccessToken checks issuer, audience, scp & assertClaims
- 05responseDaloyJS APIClient appReturn protected data after requireAuth passes
1. Configure an Okta Authorization Server
- In the Okta admin console, go to Security → API → Authorization Servers. Use the built-in
defaultserver or create a new Custom Authorization Server (requires the API Access Management license). - Add scopes (e.g.
items:read,items:write) and an access policy that allows your client app to request them. - Note the Issuer URI (e.g.
https://dev-12345.okta.com/oauth2/default) and the client's Client ID.
2. Install
3. Environment variables
4. Plugin
5. Guard a route
Custom claim assertions
The verifier can enforce extra claims at construction time. For example, to require that the token includes both items:read and items:write in the space-separated scp claim:
Verifying ID tokens
Use verifyIdToken(token, expectedClientId, expectedNonce?) if your client also sends ID tokens (for example, to populate a user profile). Pass the nonce only when the original auth request included one.
Custom JWKS URI
When the JWKS isn't under the issuer (e.g. you front Okta with a proxy), pass jwksUri explicitly:
Runtimes
@okta/jwt-verifier is a Node-only library (it imports Node modules transitively). For Node, Bun, and AWS Lambda it works out of the box; for Cloudflare Workers or Vercel, use jose's createRemoteJWKSet + jwtVerify against the same issuer (the Auth0 page shows that exact pattern, only the issuer URL changes).
Org server vs Custom Authorization Server
Only tokens from a Custom Authorization Server are meant to be verified by your app, those issuers look like https://{domain}/oauth2/{asId}. The Org Authorization Server (https://{domain}) issues opaque tokens that only Okta should consume; validate those via the /introspect endpoint instead.
See also Auth0, Clerk, and the auth integrations overview.