Okta OIDC Authentication
What you will build: A real Okta OIDC sign-in flow — browser → Okta → PKCE code exchange → RS256 token validation → role-mapped session.
What Happens End-to-End
Browser Astro Server Okta
│ │ │
│── Click "Sign in" ───► │ │
│ │── Build /authorize ──►│
│◄── Redirect to Okta ───│ (PKCE + state) │
│ │ │
│── Login at Okta ──────────────────────────────►│
│◄── Redirect /callback?code=... ────────────────│
│ │ │
│── GET /callback ──────►│ │
│ │── POST /token ────────►│
│ │◄─ id_token + access_token
│ │ │
│ │── Fetch JWKS ─────────►│
│ │◄─ Public Keys │
│ │ │
│ │ Verify RS256 sig │
│ │ Extract groups[] │
│ │ Map groups → roles │
│ │ Create session JWT │
│◄── Set cookie ─────────│ │
│── GET /dashboard ─────►│ │ Part A — Okta Developer Tenant Setup
Step 1: Create a free Okta Developer account
- Go to https://developer.okta.com/signup/
- Fill in your name, email, and company
- Click Sign up
- Check your email — click the activation link
- Set your password
dev-12345678.okta.com. Keep this handy.
Step 2: Log in to your Okta Admin Console
URL: https://dev-XXXXXX-admin.okta.com (with -admin in the URL)
You should see the Okta Admin Dashboard.
Part B — Create the OIDC Application in Okta
Step 3: Navigate to Applications
- In the left sidebar, click Applications
- Click Applications again (the sub-item)
- Click the blue Create App Integration button
Step 4: Select the application type
A dialog box appears:
- Under Sign-in method, select OIDC — OpenID Connect
- Under Application type, select Web Application
- Click Next
Step 5: Configure the app settings
Fill in the form:
| Field | Value |
|---|---|
| App integration name | AuthMatrix Lab |
| Grant types | ✅ Authorization Code (already checked) |
| Sign-in redirect URIs | http://localhost:3000/api/auth/okta-callback |
| Sign-out redirect URIs | http://localhost:3000 |
| Controlled access | Select Allow everyone in your organization to access |
Click Save.
Step 6: Record your credentials
After saving, you land on the app's General tab. You need:
| Value | Where to find it |
|---|---|
| Client ID | Listed on the General tab as "Client ID" |
| Client Secret | Click Edit → scroll to "CLIENT SECRETS" section |
| Okta Domain | Top-right of the Admin Console (e.g., dev-12345678.okta.com) |
.env file only.
Part C — Configure the Groups Claim
Okta's OIDC tokens do not include group membership by default. You must add a custom claim to include groups.
Step 7: Navigate to the Authorization Server
- In the left sidebar, click Security
- Click API
- Under Authorization Servers, click default
Step 8: Add the groups claim
- Click the Claims tab
- Click Add Claim
- Fill in the form:
| Field | Value |
|---|---|
| Name | groups |
| Include in token type | Access Token · Always |
| Value type | Groups |
| Filter | Matches regex: .* |
| Include in | Any scope |
Click Create.
.* includes ALL groups. In production, filter to specific groups only.
Step 9: Verify the issuer
Still on the Authorization Server page, note the Issuer field at the top. It will look like:
https://dev-XXXXXX.okta.com/oauth2/default Copy this — it is your OKTA_ISSUER.
Part D — Create Okta Groups and Assign Users
Step 10: Create the AuthMatrix groups
- In the left sidebar, click Directory → Groups
- Click Add Group and create each group:
| Group Name | Description |
|---|---|
Admin | AuthMatrix Administrators |
Managers | AuthMatrix Managers |
Developers | AuthMatrix Developers |
Auditors | AuthMatrix Auditors |
Create all four groups by repeating the Add Group action.
Step 11: Assign your user to a group
- Click on the Admin group you just created
- Click the People tab
- Click Assign People
- Search for your user account name
- Click the + icon next to your name
- Click Save
"groups": ["Admin", "Everyone"] in the access token. The AuthMatrix app maps "Admin" → internal Admin role with all permissions.
Part E — Configure Your Local Environment
Step 12: Update your .env file
Open c:\GitHub\Learn IDM\.env in a text editor. Fill in the Okta section:
# —— OKTA DEVELOPER SETTINGS ——————————————————————————————————————
OKTA_ISSUER=https://dev-XXXXXX.okta.com/oauth2/default
OKTA_CLIENT_ID=0oaXXXXXXXXXXXXXXXX
OKTA_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
OKTA_REDIRECT_URI=http://localhost:3000/api/auth/okta-callback Replace the XXXXXX values with your actual values from Step 6 and Step 9.
Step 13: Restart the Astro server
Stop the Astro dev server (Ctrl+C) and restart it so it picks up the new .env:
npm run dev --workspace=apps/astro-frontend Part F — Test Okta Sign-In
Step 14: Open the login page
Navigate to: http://localhost:3000/login
The Okta button should now show:
🔵 Sign in with Okta
✅ Configured .env. Make sure you restarted it and the file is named .env (not .env.txt).
Step 15: Click "Sign in with Okta"
What happens:
- The browser hits
/api/auth/okta-loginon the Astro server - The server generates a PKCE
code_verifierandcode_challenge - Sets two short-lived HttpOnly cookies:
okta_pkce_verifierandokta_oauth_state - Redirects your browser to Okta
You should now see the Okta login page.
Step 16: Authenticate at Okta
- Enter your Okta account email and password
- Complete MFA if prompted
- Click Sign In
Okta redirects your browser back to:
http://localhost:3000/api/auth/okta-callback?code=XXXXXXXX&state=YYYYYYYY Step 17: Observe the callback processing
The Astro server's okta-callback.ts runs:
- ✅ Validates
statecookie matches URL parameter (CSRF check) - ✅ POSTs to
https://dev-XXXXX.okta.com/oauth2/default/v1/tokenwith the authorization code andcode_verifier - ✅ Receives
id_token(RS256 signed JWT) - ✅ Fetches Okta's JWKS from
https://dev-XXXXX.okta.com/oauth2/default/v1/keys - ✅ Verifies the RS256 signature cryptographically
- ✅ Extracts
groups[]claim → maps to internal roles - ✅ Creates session JWT → sets
auth_tokenHttpOnly cookie - ✅ Redirects to
/dashboard
Step 18: Verify on the Dashboard
On the dashboard you should see:
- Identity Provider badge: 🔵 Okta
- Subject (sub):
00u...— Okta's user ID (format:00u+ alphanumeric) - Email: Your Okta account email
- Issuer (iss):
https://authmatrix.local(our normalized internal issuer) - Assigned Roles: The group you assigned yourself to (e.g.,
Admin) - Granted Permissions: The permissions for that role
https://authmatrix.local — not dev-XXXXX.okta.com. This is by design: the session token is our own normalized JWT, not the raw Okta token. The Okta token is validated and discarded server-side.
Part G — Test Role-Based Access
Step 19: Test API endpoints
On the Dashboard, click the API Endpoint Tester buttons. Since you logged in as Admin (from the Okta group you set up), all endpoints should return 200.
Step 20: Test with a different group (optional)
- Log out
- In Okta Admin → Directory → Groups, add yourself to
Developersgroup instead - Remove yourself from
Admingroup - Sign back in with Okta
- Dashboard should show role
Developerwith onlyread:reports,execute:jobspermissions - Clicking
POST /usersorDELETE /auditshould return 403
Part H — Token Inspection
Step 21: Inspect the JWT in the dashboard
On the Dashboard JWT Inspector panel:
HEADER should show:
{
"alg": "HS256",
"typ": "JWT"
} JWT_SECRET. The original Okta token (RS256) was validated server-side and converted to our normalized session format.
PAYLOAD should show:
{
"sub": "00uXXXXXXXXXXXXXXXX",
"name": "Your Name",
"email": "you@yourcompany.com",
"roles": ["Admin"],
"permissions": ["read:users", "write:users", ...],
"idp": "okta",
"iss": "https://authmatrix.local",
"aud": "https://api.authmatrix.local"
} Step 22: Inspect the original Okta token (Advanced)
To see the raw RS256 token Okta issued, open browser DevTools during the sign-in:
- Open DevTools → Network tab
- Sign in with Okta
- In the Network tab, look for the request to
/api/auth/okta-callback - The
okta_pkce_verifiercookie is visible in the Request Headers before it's deleted
Alternatively, add a temporary console.log(tokens.id_token) to okta-callback.ts, restart the server, sign in, and check the Astro server console output. Copy the token and paste it into https://jwt.io to see the raw Okta claims including groups[].
✅ Lab 2 Complete — Validation Checklist
- Created Okta Developer account and Admin Console access
- Created OIDC Web Application in Okta with correct redirect URI
- Added
groupsclaim to thedefaultAuthorization Server - Created 4 Okta groups (Admin, Managers, Developers, Auditors)
- Assigned yourself to the Admin group
- Filled in
.envwith correctOKTA_ISSUER,OKTA_CLIENT_ID,OKTA_CLIENT_SECRET - Login page shows "✅ Configured" for Okta
- Clicked "Sign in with Okta" → redirected to Okta login page
- Authenticated at Okta → returned to dashboard
- Dashboard shows 🔵 Okta badge and correct email/role/permissions
- API endpoint tests show expected 200/403 responses per role
- JWT Inspector shows
"idp": "okta"in payload
Next: Lab 3 — Microsoft Entra ID OIDC
Or skip to: Lab 4 — Azure APIM API Gateway