Okta
The @mastra/auth-okta package provides authentication and role-based access control for Mastra using Okta. It supports an OAuth 2.0 / OIDC login flow with encrypted session cookies and maps Okta groups to Mastra permissions.
PrerequisitesDirect link to Prerequisites
This guide uses Okta authentication. Make sure to:
- Create an Okta account at okta.com
- Set up an OAuth application in the Okta Admin Console (Web app, Authorization Code grant)
- Add your redirect URI to the application's sign-in redirect URIs
- Create an API token (required for RBAC)
Make sure your environment variables are set.
OKTA_DOMAIN=dev-123456.okta.com
OKTA_CLIENT_ID=your-client-id
OKTA_CLIENT_SECRET=your-client-secret
OKTA_REDIRECT_URI=http://localhost:4111/api/auth/callback
OKTA_COOKIE_PASSWORD=a-random-string-at-least-32-characters-long
OKTA_API_TOKEN=your-api-token
OKTA_COOKIE_PASSWORD encrypts session cookies. If omitted, an auto-generated value is used that does not survive server restarts. Set it explicitly for production.
OKTA_API_TOKEN is only required when using MastraRBACOkta to map Okta groups to permissions.
InstallationDirect link to Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/auth-okta
pnpm add @mastra/auth-okta
yarn add @mastra/auth-okta
bun add @mastra/auth-okta
Usage examplesDirect link to Usage examples
Basic usage with environment variablesDirect link to Basic usage with environment variables
With the environment variables above set, all constructor parameters are optional:
import { Mastra } from '@mastra/core'
import { MastraAuthOkta } from '@mastra/auth-okta'
export const mastra = new Mastra({
server: {
auth: new MastraAuthOkta(),
},
})
Auth with RBACDirect link to Auth with RBAC
Add MastraRBACOkta to map Okta groups to Mastra permissions:
import { Mastra } from '@mastra/core'
import { MastraAuthOkta, MastraRBACOkta } from '@mastra/auth-okta'
export const mastra = new Mastra({
server: {
auth: new MastraAuthOkta(),
rbac: new MastraRBACOkta({
roleMapping: {
Admin: ['*'],
Engineering: ['agents:*', 'workflows:*', 'tools:*'],
Viewer: ['agents:read', 'workflows:read'],
_default: [], // users with unmapped groups get no permissions
},
}),
},
})
Cross-provider usageDirect link to Cross-provider usage
Use a different auth provider (Auth0, Clerk, etc.) for login and Okta for RBAC. Pass a getUserId function to resolve the Okta user ID from the other provider's user object:
import { Mastra } from '@mastra/core'
import { MastraAuthAuth0 } from '@mastra/auth-auth0'
import { MastraRBACOkta } from '@mastra/auth-okta'
export const mastra = new Mastra({
server: {
auth: new MastraAuthAuth0(),
rbac: new MastraRBACOkta({
getUserId: user => user.metadata?.oktaUserId || user.email,
roleMapping: {
Engineering: ['agents:*', 'workflows:*'],
Admin: ['*'],
_default: [],
},
}),
},
})
To link users between providers, store the Okta user ID in the other provider's user metadata. Mastra uses this ID to fetch groups from Okta.
Visit MastraAuthOkta for all available configuration options.
Role mappingDirect link to Role mapping
The roleMapping option maps Okta group names to arrays of Mastra permission strings. Permissions follow a resource:action pattern and support wildcards:
const rbac = new MastraRBACOkta({
roleMapping: {
// full access to everything
Admin: ['*'],
// full access to agents and workflows
Engineering: ['agents:*', 'workflows:*'],
// read-only access
Viewer: ['agents:read', 'workflows:read'],
// users whose groups don't match any key above
_default: [],
},
})
The _default key assigns permissions to users whose Okta groups do not match any other key.
Client-side setupDirect link to Client-side setup
When auth is enabled, requests to Mastra routes require authentication. MastraAuthOkta uses SSO, so users authenticate through Okta's hosted login page. After login, an encrypted session cookie is set automatically.
Cookie session (recommended)Direct link to Cookie session (recommended)
For cross-origin requests (e.g. a frontend on :3000 calling Mastra on :4111), enable CORS credentials on the Mastra server:
export const mastra = new Mastra({
server: {
auth: new MastraAuthOkta(),
cors: {
origin: 'http://localhost:3000',
credentials: true,
},
},
})
Configure the client to include credentials:
import { MastraClient } from '@mastra/client-js'
export const mastraClient = new MastraClient({
baseUrl: 'http://localhost:4111',
credentials: 'include',
})
Bearer tokenDirect link to Bearer token
You can also pass an Okta access token as a Bearer token. The token is verified against Okta's JWKS endpoint:
import { MastraClient } from '@mastra/client-js'
export const createMastraClient = (accessToken: string) => {
return new MastraClient({
baseUrl: 'http://localhost:4111',
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
}
Visit Mastra Client SDK for more configuration options.
Making authenticated requestsDirect link to Making authenticated requests
- MastraClient
- cURL
import { mastraClient } from '../lib/mastra-client'
const agent = mastraClient.getAgent('weatherAgent')
const response = await agent.generate('Weather in London')
console.log(response)
curl -X POST http://localhost:4111/api/agents/weatherAgent/generate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-okta-access-token>" \
-d '{
"messages": "Weather in London"
}'
TroubleshootingDirect link to Troubleshooting
- 401 on every request: Verify your Okta domain, client ID, and client secret are correct. Check that the redirect URI in your Okta application matches
OKTA_REDIRECT_URI. - Cookies not sent cross-origin: Set
credentials: "include"inMastraClientand configureserver.corswith your frontend origin andcredentials: true. - Session lost on restart: Set
OKTA_COOKIE_PASSWORDto a stable value (at least 32 characters). Without it, an auto-generated key is used that changes on each restart. - RBAC returns empty permissions: Verify
OKTA_API_TOKENis set and the token has permission to list user groups. Check that group names inroleMappingmatch your Okta group names exactly.