# Okta Developer Documentation Okta is a cloud-based identity and access management (IAM) platform that provides authentication, authorization, and user management services for applications. The Okta platform enables developers to securely authenticate users using OAuth 2.0 and OpenID Connect (OIDC) protocols, manage user lifecycles through SCIM provisioning, and extend functionality through webhooks (event hooks and inline hooks). Okta supports multiple integration patterns including redirect-based authentication, embedded Sign-In Widget, and direct API access for server-side applications. The Okta APIs and SDKs allow developers to implement single sign-on (SSO) across web, mobile, and native applications. Key capabilities include user authentication flows (Authorization Code, Authorization Code with PKCE, Client Credentials), token management (access tokens, refresh tokens, ID tokens), multi-factor authentication (MFA), and real-time event notifications. Okta provides official SDKs for JavaScript, React, Angular, Vue, Node.js, Java Spring Boot, .NET Core, Python, Go, iOS, and Android platforms. --- ## OAuth 2.0 Authorization Code Flow The Authorization Code flow is the recommended OAuth 2.0 flow for server-side web applications that can securely store client secrets. The flow involves redirecting users to Okta for authentication and exchanging an authorization code for access and ID tokens. ```bash # Step 1: Request authorization code - redirect user to this URL https://{yourOktaDomain}/oauth2/v1/authorize? client_id=0oabucvyc38HLL1ef0h7& response_type=code& scope=openid%20profile%20email& redirect_uri=https%3A%2F%2Fexample.com%2Fcallback& state=state-296bc9a0-a2a2-4a57-be1a-d0e2fd9bb601 # After user authenticates, Okta redirects to: # https://example.com/callback?code=P5I7mdxxdv13_JfXrCSq&state=state-296bc9a0-a2a2-4a57-be1a-d0e2fd9bb601 # Step 2: Exchange authorization code for tokens curl --request POST \ --url https://{yourOktaDomain}/oauth2/v1/token \ --header 'accept: application/json' \ --header 'authorization: Basic MG9hY...' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=authorization_code&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&code=P5I7mdxxdv13_JfXrCSq' # Response: # { # "access_token": "eyJhbG[...]9pDQ", # "token_type": "Bearer", # "expires_in": 3600, # "scope": "openid profile email", # "id_token": "eyJhbG[...]RTM0A" # } ``` --- ## OAuth 2.0 Authorization Code Flow with PKCE The Authorization Code flow with Proof Key for Code Exchange (PKCE) is the recommended flow for single-page applications (SPAs), mobile apps, and native applications where client secrets cannot be securely stored. PKCE prevents authorization code interception attacks by using a code verifier and code challenge. ```bash # Step 1: Generate PKCE code verifier and challenge # Code verifier: Random URL-safe string with minimum length of 43 characters # Code challenge: Base64-encoded SHA-256 hash of the code verifier # Example PKCE values: # { # "code_verifier":"M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakxifmZHag", # "code_challenge":"qjrzSW9gMiUgpUvqgEPE4_-8swvyCtfOVvg55o5S_es" # } # Step 2: Request authorization code with code challenge https://{yourOktaDomain}/oauth2/v1/authorize? client_id=0oabygpxgk9lXaMgF0h7& response_type=code& scope=openid%20profile& redirect_uri=yourApp%3A%2Fcallback& state=state-8600b31f-52d1-4dca-987c-386e3d8967e9& code_challenge_method=S256& code_challenge=qjrzSW9gMiUgpUvqgEPE4_-8swvyCtfOVvg55o5S_es # Step 3: Exchange code for tokens using code verifier (no client secret required) curl --request POST \ --url https://{yourOktaDomain}/oauth2/v1/token \ --header 'accept: application/json' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=authorization_code&client_id=0oabygpxgk9lXaMgF0h7&redirect_uri=yourApp%3A%2Fcallback&code=CKA9Utz2GkWlsrmnqehz&code_verifier=M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakxifmZHag' # Response: # { # "access_token": "eyJhb[...]Hozw", # "expires_in": 3600, # "id_token": "eyJhb[...]jvCw", # "scope": "openid profile", # "token_type": "Bearer" # } ``` --- ## OAuth 2.0 Client Credentials Flow The Client Credentials flow is used for machine-to-machine (M2M) communication where there is no end user involved. This flow is appropriate for server-side applications, daemons, and backend services that need to authenticate with their own credentials. ```bash # Base64-encode client credentials: echo -n 'clientId:clientSecret' | base64 # Request access token using client credentials curl --request POST \ --url https://{yourOktaDomain}/oauth2/default/v1/token \ --header 'accept: application/json' \ --header 'authorization: Basic MG9hY...' \ --header 'cache-control: no-cache' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=client_credentials&scope=customScope' # Response: # { # "access_token": "eyJhbG[...]1LQ", # "token_type": "Bearer", # "expires_in": 3600, # "scope": "customScope" # } ``` --- ## Refresh Access Tokens Refresh tokens allow applications to obtain new access tokens without requiring the user to re-authenticate. Include the `offline_access` scope in your initial authorization request to receive a refresh token. ```bash # Get authorization code with offline_access scope curl -X GET 'https://{yourOktaDomain}/oauth2/v1/authorize?client_id={clientId}&response_type=code&scope=openid%20offline_access&redirect_uri=yourApp%3A%2Fcallback&state=237c671a-29d7-11eb-adc1-0242ac120002' # Exchange code for tokens (includes refresh_token) curl --location --request POST 'https://{yourOktaDomain}/oauth2/v1/token' \ -H 'Accept: application/json' \ -H 'Authorization: Basic {Base64({clientId}:{clientSecret})}' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=authorization_code' \ -d 'redirect_uri={redirectUri}' \ -d 'code=iyz1Lpim4NgN6gDQdT1a9PJDVTaCdxG1wJMYiUkfGts' \ -d 'scope=openid offline_access' # Use refresh token to get new access token curl --form POST https://{yourOktaDomain}/oauth2/v1/token \ -H 'accept: application/json' \ -H 'authorization: Basic MG9hYmg3M...' \ -H 'content-type: application/x-www-form-urlencoded' \ -d 'grant_type=refresh_token' \ -d 'redirect_uri=http://localhost:8080' \ -d 'scope=offline_access%20openid' \ -d 'refresh_token=MIOf-U1zQbyfa3MUfJHhvnUqIut9ClH0xjlDXGJAyqo' # Response: # { # "access_token": "eyJhbGciOiJ[...]K1Sun9bA", # "token_type": "Bearer", # "expires_in": 3600, # "scope": "offline_access openid", # "refresh_token": "MIOf-U1zQbyfa3MUfJHhvnUqIut9ClH0xjlDXGJAyqo", # "id_token": "eyJraWQiO[...]hMEJQX6WRQ" # } ``` --- ## Node.js Express OIDC Integration Integrate Okta authentication into a Node.js Express application using the passport-openidconnect strategy. This approach handles the OAuth 2.0 flow automatically and manages user sessions. ```javascript // Install required packages // npm install express-session passport passport-openidconnect // app.js - Configure Express with Okta OIDC const express = require('express'); const session = require('express-session'); const passport = require('passport'); const { Strategy } = require('passport-openidconnect'); const app = express(); // Session configuration app.use(session({ secret: 'your-secure-session-secret', resave: false, saveUninitialized: true })); app.use(passport.initialize()); app.use(passport.session()); // Configure Okta OIDC Strategy passport.use('oidc', new Strategy({ issuer: 'https://{yourOktaDomain}', authorizationURL: 'https://{yourOktaDomain}/oauth2/v1/authorize', tokenURL: 'https://{yourOktaDomain}/oauth2/v1/token', userInfoURL: 'https://{yourOktaDomain}/oauth2/v1/userinfo', clientID: '{clientID}', clientSecret: '{clientSecret}', callbackURL: 'http://localhost:3000/authorization-code/callback', scope: 'openid profile' }, (issuer, profile, done) => { return done(null, profile); })); passport.serializeUser((user, next) => { next(null, user); }); passport.deserializeUser((obj, next) => { next(null, obj); }); // Login route - redirects to Okta app.get('/login', passport.authenticate('oidc')); // Callback route - handles OAuth response app.use('/authorization-code/callback', passport.authenticate('oidc', { failureMessage: true, failWithError: true }), (req, res) => { res.redirect('/profile'); } ); // Protected profile route app.get('/profile', (req, res) => { if (!req.isAuthenticated()) { return res.redirect('/login'); } res.json(req.user); }); // Logout route app.post('/signout', (req, res) => { req.logout(); res.redirect('/'); }); app.listen(3000, () => console.log('Server running on http://localhost:3000')); ``` --- ## Protect API Endpoints with JWT Verification Secure your Node.js API endpoints by validating Okta-issued JWT access tokens. The @okta/jwt-verifier package handles token validation including signature verification and claims checking. ```javascript // Install: npm install @okta/jwt-verifier express const express = require('express'); const OktaJwtVerifier = require('@okta/jwt-verifier'); const app = express(); // Configure JWT Verifier const oktaJwtVerifier = new OktaJwtVerifier({ issuer: 'https://{yourOktaDomain}/oauth2/{yourAuthServerName}' }); const audience = '{yourAudience}'; // e.g., 'api://default' // Authentication middleware const authenticationRequired = async (req, res, next) => { const authHeader = req.headers.authorization || ''; const match = authHeader.match(/Bearer (.+)/); if (!match) { return res.status(401).send('Authorization header required'); } try { const accessToken = match[1]; if (!accessToken) { return res.status(401).send('Not authorized'); } // Verify and decode the JWT req.jwt = await oktaJwtVerifier.verifyAccessToken(accessToken, audience); next(); } catch (err) { return res.status(401).send(err.message); } }; // Public endpoint app.get('/api/hello', (req, res) => { res.send('Hello world!'); }); // Protected endpoint - requires valid access token app.get('/api/whoami', authenticationRequired, (req, res) => { res.json(req.jwt?.claims); }); // Protect all routes under /api/secure app.use('/api/secure', authenticationRequired); app.get('/api/secure/data', (req, res) => { res.json({ message: 'This is protected data', user: req.jwt.claims.sub }); }); app.listen(3000, () => console.log('API server running on port 3000')); // Example curl command to test protected endpoint: // curl -H "Authorization: Bearer eyJhbG..." http://localhost:3000/api/whoami ``` --- ## Okta API Token Authentication Use Okta API tokens to authenticate requests to Okta Management APIs. API tokens use the SSWS authentication scheme and inherit the privilege level of the admin account that created them. ```bash # Using API token in Authorization header curl --request GET \ --url https://{yourOktaDomain}/api/v1/users \ --header 'Accept: application/json' \ --header 'Authorization: SSWS 00QCjAl4MlV-WPXM...0HmjFx-vbGua' # Create a new user curl --request POST \ --url https://{yourOktaDomain}/api/v1/users?activate=true \ --header 'Accept: application/json' \ --header 'Authorization: SSWS {api_token}' \ --header 'Content-Type: application/json' \ --data '{ "profile": { "firstName": "John", "lastName": "Doe", "email": "john.doe@example.com", "login": "john.doe@example.com" }, "credentials": { "password": { "value": "TempPassword123!" } } }' # List all applications curl --request GET \ --url https://{yourOktaDomain}/api/v1/apps \ --header 'Accept: application/json' \ --header 'Authorization: SSWS {api_token}' # Get System Log events curl --request GET \ --url 'https://{yourOktaDomain}/api/v1/logs?filter=eventType eq "user.lifecycle.deactivate"' \ --header 'Accept: application/json' \ --header 'Authorization: SSWS {api_token}' ``` --- ## Token Introspection Endpoint Validate access or refresh tokens remotely using the Token Introspection endpoint. This is useful when you need to verify a token hasn't been revoked, though it adds network latency compared to local JWT validation. ```bash # Introspect an access token curl --request POST \ --url https://{yourOktaDomain}/oauth2/default/v1/introspect \ --header 'Accept: application/json' \ --header 'Authorization: Basic {Base64(clientId:clientSecret)}' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data 'token=eyJhbGciOiJSUzI1NiJ9...&token_type_hint=access_token' # Response for active token: # { # "active": true, # "scope": "openid profile", # "username": "john.doe@example.com", # "exp": 1640000000, # "iat": 1639996400, # "sub": "john.doe@example.com", # "aud": "api://default", # "iss": "https://{yourOktaDomain}/oauth2/default", # "jti": "AT.xyz123", # "token_type": "Bearer", # "client_id": "0oabcdefg" # } # Response for inactive/revoked token: # { # "active": false # } ``` --- ## Event Hooks Implementation Event hooks are outbound calls from Okta that notify your external service when events occur in your Okta org. Implement event hooks to sync user data, trigger workflows, or integrate with external systems. ```javascript // Node.js Express event hook endpoint const express = require('express'); const app = express(); app.use(express.json()); // One-time verification endpoint (Okta calls this to verify your endpoint) app.get('/userDeactivated', (req, res) => { const returnValue = { verification: req.headers['x-okta-verification-challenge'] }; console.log('Event hook verification request received.'); res.json(returnValue); }); // Event hook handler for user deactivation events app.post('/userDeactivated', (req, res) => { // Extract user information from the event const event = req.body.data.events[0]; const userId = event.target[0].id; const userEmail = event.target[0].alternateId; const displayName = event.target[0].displayName; console.log(`User ${displayName} (${userEmail}) has been deactivated!`); // Process the event (e.g., update external systems, send notifications) // Your custom logic here... // Respond with 200 OK to acknowledge receipt res.sendStatus(200); }); app.listen(3000); // Event hook payload structure: // { // "eventType": "com.okta.event_hook", // "data": { // "events": [{ // "eventType": "user.lifecycle.deactivate", // "target": [{ // "id": "00u3m90rsKgGQ0G6L1d76", // "type": "User", // "alternateId": "john.doe@example.com", // "displayName": "John Doe" // }] // }] // } // } ``` --- ## SCIM 2.0 Provisioning API SCIM (System for Cross-domain Identity Management) enables automatic user provisioning between Okta and your application. Implement SCIM endpoints to create, update, deactivate, and sync users from Okta to your service. ```bash # SCIM 2.0 Base URL structure # https://your-app.example.com/scim/v2 # Required SCIM endpoints: # GET /Users - List users # GET /Users/{id} - Get user by ID # POST /Users - Create user # PUT /Users/{id} - Replace user # PATCH /Users/{id} - Update user attributes # DELETE /Users/{id} - Delete user # GET /ServiceProviderConfig - SCIM configuration # Example: Create user request from Okta # POST /scim/v2/Users # Content-Type: application/scim+json # Authorization: Bearer {token} # # { # "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], # "userName": "john.doe@example.com", # "name": { # "givenName": "John", # "familyName": "Doe" # }, # "emails": [{ # "primary": true, # "value": "john.doe@example.com", # "type": "work" # }], # "active": true # } # Example: Create user response # HTTP/1.1 201 Created # Content-Type: application/scim+json # # { # "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], # "id": "unique-user-id-12345", # "userName": "john.doe@example.com", # "name": { # "givenName": "John", # "familyName": "Doe" # }, # "emails": [{ # "primary": true, # "value": "john.doe@example.com", # "type": "work" # }], # "active": true, # "meta": { # "resourceType": "User", # "created": "2024-01-15T10:30:00Z", # "lastModified": "2024-01-15T10:30:00Z" # } # } # Example: Deactivate user (PATCH) # PATCH /scim/v2/Users/{id} # { # "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], # "Operations": [{ # "op": "replace", # "value": { "active": false } # }] # } ``` --- ## Sign-In Widget Integration The Okta Sign-In Widget is a JavaScript library that provides a fully-featured and customizable login experience. It handles authentication flows, MFA enrollment, and password recovery out of the box. ```html
``` --- ## React SPA with Okta Auth Integrate Okta authentication into a React single-page application using the @okta/okta-react SDK. This provides React components and hooks for managing authentication state. ```jsx // Install: npm install @okta/okta-react @okta/okta-auth-js react-router-dom // App.jsx import React from 'react'; import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import { Security, LoginCallback, useOktaAuth } from '@okta/okta-react'; import { OktaAuth } from '@okta/okta-auth-js'; const oktaAuth = new OktaAuth({ issuer: 'https://{yourOktaDomain}/oauth2/default', clientId: '{clientId}', redirectUri: window.location.origin + '/login/callback', scopes: ['openid', 'profile', 'email'], pkce: true }); // Protected component that requires authentication const Profile = () => { const { authState, oktaAuth } = useOktaAuth(); if (!authState || !authState.isAuthenticated) { returnEmail: {authState.idToken?.claims.email}