@mastra/auth-okta 0.0.2 → 0.0.3-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/auth-provider.d.ts +1 -0
- package/dist/auth-provider.d.ts.map +1 -1
- package/dist/index.cjs +7 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @mastra/auth-okta
|
|
2
2
|
|
|
3
|
+
## 0.0.3-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix endpoint URL construction for Okta org authorization servers. ([#15694](https://github.com/mastra-ai/mastra/pull/15694))
|
|
8
|
+
|
|
9
|
+
`MastraAuthOkta` concatenated `/v1/authorize` (and `/token`, `/keys`, `/logout`) directly onto `OKTA_ISSUER`. That yields the right endpoint for a custom authorization server (`https://{domain}/oauth2/default` → `.../oauth2/default/v1/authorize`), but 404s on an Okta org authorization server (`https://{domain}` → `.../v1/authorize`, whereas the real org endpoint is `.../oauth2/v1/authorize`).
|
|
10
|
+
|
|
11
|
+
An internal `endpointBase` is now derived from the issuer — verbatim when it already contains `/oauth2/`, otherwise `${issuer}/oauth2` — and used for the authorize, token, keys, and logout URLs. JWT `iss`-claim validation still uses the raw issuer so token validation stays correct on both server types. Trailing slashes on the issuer are also normalized so `OKTA_ISSUER=https://{domain}/` no longer produces `.../oauth2//v1/...`.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`27fd1b7`](https://github.com/mastra-ai/mastra/commit/27fd1b79ac62eb7694f92587eb7d1be05b59be01), [`a702009`](https://github.com/mastra-ai/mastra/commit/a702009d3cfaa745120f501e21c783ed4d6a3072), [`8534d79`](https://github.com/mastra-ai/mastra/commit/8534d791fa1cb70fe1c19e2604c4b63cc10dd051), [`c78f8cd`](https://github.com/mastra-ai/mastra/commit/c78f8cd6222a86e6c60ae5210b6929ad5221b6fb), [`e146aad`](https://github.com/mastra-ai/mastra/commit/e146aadbba66c410ba0e74bac4c50135495cb8dd), [`1a0ec78`](https://github.com/mastra-ai/mastra/commit/1a0ec789a26cae443744e9abbd62ed6ee676af39), [`d52b6fe`](https://github.com/mastra-ai/mastra/commit/d52b6fe1c56853eb38864baae0bbfa75cc739ccb)]:
|
|
14
|
+
- @mastra/core@1.36.0-alpha.10
|
|
15
|
+
|
|
3
16
|
## 0.0.2
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/auth-provider.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare class MastraAuthOkta extends MastraAuthProvider<OktaUser> impleme
|
|
|
29
29
|
protected clientId: string;
|
|
30
30
|
protected clientSecret: string;
|
|
31
31
|
protected issuer: string;
|
|
32
|
+
protected endpointBase: string;
|
|
32
33
|
protected redirectUri: string;
|
|
33
34
|
protected scopes: string[];
|
|
34
35
|
protected cookieName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAGxC,OAAO,KAAK,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AA0ElE;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cACX,SAAQ,kBAAkB,CAAC,QAAQ,CACnC,YAAW,YAAY,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC;IAErF,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAwC;gBAExC,OAAO,CAAC,EAAE,qBAAqB;
|
|
1
|
+
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -232,6 +232,7 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
232
232
|
clientId;
|
|
233
233
|
clientSecret;
|
|
234
234
|
issuer;
|
|
235
|
+
endpointBase;
|
|
235
236
|
redirectUri;
|
|
236
237
|
scopes;
|
|
237
238
|
cookieName;
|
|
@@ -272,7 +273,8 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
272
273
|
this.domain = domain;
|
|
273
274
|
this.clientId = clientId;
|
|
274
275
|
this.clientSecret = clientSecret;
|
|
275
|
-
this.issuer = issuer ?? `https://${domain}/oauth2/default
|
|
276
|
+
this.issuer = (issuer ?? `https://${domain}/oauth2/default`).replace(/\/+$/, "");
|
|
277
|
+
this.endpointBase = this.issuer.includes("/oauth2/") || this.issuer.endsWith("/oauth2") ? this.issuer : `${this.issuer}/oauth2`;
|
|
276
278
|
this.redirectUri = redirectUri;
|
|
277
279
|
this.scopes = options?.scopes ?? DEFAULT_SCOPES;
|
|
278
280
|
this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;
|
|
@@ -280,7 +282,7 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
280
282
|
this.cookiePassword = cookiePassword;
|
|
281
283
|
this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === "production";
|
|
282
284
|
this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;
|
|
283
|
-
this.jwks = jose.createRemoteJWKSet(new URL(`${this.
|
|
285
|
+
this.jwks = jose.createRemoteJWKSet(new URL(`${this.endpointBase}/v1/keys`));
|
|
284
286
|
if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {
|
|
285
287
|
console.warn(
|
|
286
288
|
"[MastraAuthOkta] No cookie password set \u2014 using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use."
|
|
@@ -431,7 +433,7 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
431
433
|
redirect_uri: actualRedirectUri,
|
|
432
434
|
state
|
|
433
435
|
});
|
|
434
|
-
return `${this.
|
|
436
|
+
return `${this.endpointBase}/v1/authorize?${params.toString()}`;
|
|
435
437
|
}
|
|
436
438
|
/**
|
|
437
439
|
* Handle the OAuth callback from Okta.
|
|
@@ -446,7 +448,7 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
446
448
|
if (stored.expiresAt < Date.now()) {
|
|
447
449
|
throw new Error("State parameter has expired");
|
|
448
450
|
}
|
|
449
|
-
const tokenResponse = await fetch(`${this.
|
|
451
|
+
const tokenResponse = await fetch(`${this.endpointBase}/v1/token`, {
|
|
450
452
|
method: "POST",
|
|
451
453
|
headers: {
|
|
452
454
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -501,7 +503,7 @@ var MastraAuthOkta = class extends server.MastraAuthProvider {
|
|
|
501
503
|
params.set("id_token_hint", idToken);
|
|
502
504
|
}
|
|
503
505
|
}
|
|
504
|
-
return `${this.
|
|
506
|
+
return `${this.endpointBase}/v1/logout?${params.toString()}`;
|
|
505
507
|
}
|
|
506
508
|
/**
|
|
507
509
|
* Get cookies to set during login.
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rbac-provider.ts","../src/types.ts","../src/auth-provider.ts"],"names":["pkg","LRUCache","resolvePermissionsFromMapping","matchesPermission","MastraAuthProvider","createRemoteJWKSet","jwtVerify"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Okta RBAC provider for Mastra.\n *\n * Maps Okta groups to Mastra permissions using a configurable role mapping.\n * Can be used with any auth provider (Auth0, Clerk, etc.) or with MastraAuthOkta.\n */\n\nimport type { IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport pkg from '@okta/okta-sdk-nodejs';\nconst { Client } = pkg;\nimport { LRUCache } from 'lru-cache';\n\nimport type { OktaUser, MastraRBACOktaOptions } from './types.js';\n\n/** Default cache TTL in milliseconds (60 seconds) */\nconst DEFAULT_CACHE_TTL_MS = 60 * 1000;\n\n/** Default max cache size (number of users) */\nconst DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Okta RBAC provider that maps Okta groups to Mastra permissions.\n *\n * This provider fetches user groups from Okta and translates them into\n * Mastra permissions using a configurable role mapping.\n *\n * @example Basic usage with Okta auth\n * ```typescript\n * import { MastraAuthOkta, MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthOkta(),\n * rbac: new MastraRBACOkta({\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n *\n * @example Cross-provider usage (Auth0 + Okta RBAC)\n * ```typescript\n * import { MastraAuthAuth0 } from '@mastra/auth-auth0';\n * import { MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthAuth0(),\n * rbac: new MastraRBACOkta({\n * getUserId: (user) => user.metadata?.oktaUserId || user.email,\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n */\nexport class MastraRBACOkta implements IRBACProvider<OktaUser> {\n private oktaClient: InstanceType<typeof Client>;\n private options: MastraRBACOktaOptions;\n /**\n * Single cache for roles (the expensive Okta API call).\n * Permissions are derived from roles on-the-fly (cheap, synchronous).\n * Storing promises handles concurrent request deduplication.\n */\n private rolesCache: LRUCache<string, Promise<string[]>>;\n\n /**\n * Expose roleMapping for middleware access.\n * This allows the authorization middleware to resolve permissions\n * without needing to call the async methods.\n */\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n /**\n * Create a new Okta RBAC provider.\n *\n * @param options - RBAC configuration options\n */\n constructor(options: MastraRBACOktaOptions) {\n const domain = options.domain ?? process.env.OKTA_DOMAIN;\n const apiToken = options.apiToken ?? process.env.OKTA_API_TOKEN;\n\n if (!domain) {\n throw new Error(\n 'Okta domain is required. ' + 'Provide it in the options or set OKTA_DOMAIN environment variable.',\n );\n }\n\n if (!apiToken) {\n throw new Error(\n 'Okta API token is required for RBAC. ' +\n 'Provide it in the options or set OKTA_API_TOKEN environment variable.',\n );\n }\n\n this.oktaClient = new Client({\n orgUrl: `https://${domain}`,\n token: apiToken,\n });\n\n this.options = options;\n\n // Initialize LRU cache with configurable size and TTL\n this.rolesCache = new LRUCache<string, Promise<string[]>>({\n max: options.cache?.maxSize ?? DEFAULT_CACHE_MAX_SIZE,\n ttl: options.cache?.ttlMs ?? DEFAULT_CACHE_TTL_MS,\n });\n }\n\n /**\n * Get all roles (groups) for a user from Okta.\n *\n * If the user object already has groups attached, uses those.\n * Otherwise, fetches groups from Okta API and caches the result.\n *\n * @param user - User to get roles for\n * @returns Array of group names\n */\n async getRoles(user: OktaUser): Promise<string[]> {\n // If groups are already present on the user object, use them\n if (user.groups && user.groups.length > 0) {\n return user.groups;\n }\n\n // Determine the user ID to use for Okta API lookup\n const userId = this.resolveUserId(user);\n if (!userId) {\n return [];\n }\n\n // Check cache - returns existing promise (resolved or in-flight)\n const cached = this.rolesCache.get(userId);\n if (cached) {\n return cached;\n }\n\n // Create and cache the group fetch promise.\n // On failure, evict from cache so the next request retries,\n // then fall back to empty groups (which applies _default permissions).\n const groupsPromise = this.fetchGroupsFromOkta(userId).catch(err => {\n console.error(`[MastraRBACOkta] Failed to fetch groups for user ${userId}:`, err);\n this.rolesCache.delete(userId);\n return [];\n });\n this.rolesCache.set(userId, groupsPromise);\n\n return groupsPromise;\n }\n\n /**\n * Resolve the Okta user ID from the user object.\n * Uses custom getUserId function if provided, otherwise falls back to oktaId or id.\n */\n private resolveUserId(user: OktaUser): string | undefined {\n if (this.options.getUserId) {\n return this.options.getUserId(user);\n }\n return user.oktaId ?? user.id;\n }\n\n /**\n * Fetch groups from Okta API.\n * Errors propagate to the caller so the cache eviction in getRoles() works.\n */\n private async fetchGroupsFromOkta(userId: string): Promise<string[]> {\n const groups = await this.oktaClient.userApi.listUserGroups({ userId });\n const groupNames: string[] = [];\n\n for await (const group of groups) {\n if (group && group.profile?.name) {\n groupNames.push(group.profile.name);\n }\n }\n\n return groupNames;\n }\n\n /**\n * Check if a user has a specific role (group).\n *\n * @param user - User to check\n * @param role - Group name to check for\n * @returns True if user has the group\n */\n async hasRole(user: OktaUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n /**\n * Get all permissions for a user by mapping their Okta groups.\n *\n * @param user - User to get permissions for\n * @returns Array of permission strings\n */\n async getPermissions(user: OktaUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n /**\n * Check if a user has a specific permission.\n *\n * @param user - User to check\n * @param permission - Permission to check for (supports wildcards)\n * @returns True if user has the permission\n */\n async hasPermission(user: OktaUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n\n // Check if any granted permission matches the required permission\n return permissions.some(granted => matchesPermission(granted, permission));\n }\n\n /**\n * Check if a user has ALL of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has all permissions\n */\n async hasAllPermissions(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.every(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n\n /**\n * Check if a user has ANY of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has at least one permission\n */\n async hasAnyPermission(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.some(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n}\n","/**\n * Shared types for Okta integration.\n */\n\nimport type { EEUser, RoleMapping } from '@mastra/core/auth/ee';\nimport type { JWTPayload } from 'jose';\n\n// ============================================================================\n// User Types\n// ============================================================================\n\n/**\n * Extended EEUser with Okta-specific fields.\n */\nexport interface OktaUser extends EEUser {\n /** Okta user ID */\n oktaId: string;\n /** User's Okta groups (if fetched) */\n groups?: string[];\n}\n\n/**\n * Maps Okta JWT claims to OktaUser format.\n *\n * @param payload - JWT payload from Okta token\n * @returns OktaUser object\n */\nexport function mapOktaClaimsToUser(payload: JWTPayload): OktaUser {\n return {\n id: (payload.sub as string) || (payload.uid as string) || '',\n oktaId: (payload.sub as string) || (payload.uid as string) || '',\n email: payload.email as string | undefined,\n name:\n (payload.name as string) ||\n [payload.given_name, payload.family_name].filter(Boolean).join(' ') ||\n (payload.email as string) ||\n undefined,\n avatarUrl: payload.picture as string | undefined,\n groups: payload.groups as string[] | undefined,\n metadata: {\n oktaId: payload.sub,\n emailVerified: payload.email_verified,\n updatedAt: payload.updated_at,\n },\n };\n}\n\n// ============================================================================\n// Auth Provider Options\n// ============================================================================\n\n/**\n * Session configuration options for MastraAuthOkta.\n */\nexport interface OktaSessionOptions {\n /** Cookie name (default: 'okta_session') */\n cookieName?: string;\n /** Cookie max age in seconds (default: 86400 = 24 hours) */\n cookieMaxAge?: number;\n /**\n * Password for encrypting session cookies.\n * Must be at least 32 characters.\n * Defaults to OKTA_COOKIE_PASSWORD env var.\n */\n cookiePassword?: string;\n /**\n * Set the Secure flag on session cookies.\n * Defaults to true when NODE_ENV=production, false otherwise.\n */\n secureCookies?: boolean;\n}\n\n/**\n * Options for MastraAuthOkta.\n */\nexport interface MastraAuthOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n /** Okta OAuth client ID. Defaults to OKTA_CLIENT_ID env var. */\n clientId?: string;\n /** Okta OAuth client secret. Defaults to OKTA_CLIENT_SECRET env var. Required for SSO. */\n clientSecret?: string;\n /**\n * Token issuer URL.\n * Defaults to OKTA_ISSUER env var or `https://{domain}/oauth2/default`.\n */\n issuer?: string;\n /**\n * OAuth redirect URI for SSO callback.\n * Defaults to OKTA_REDIRECT_URI env var.\n */\n redirectUri?: string;\n /**\n * OAuth scopes to request.\n * Default: ['openid', 'profile', 'email', 'groups']\n */\n scopes?: string[];\n /**\n * Okta API token for user lookups via the Users API.\n * Required for getUser() to return user data by ID.\n * Defaults to OKTA_API_TOKEN env var.\n */\n apiToken?: string;\n /** Session configuration */\n session?: OktaSessionOptions;\n /** Custom provider name (default: 'okta') */\n name?: string;\n}\n\n// ============================================================================\n// RBAC Provider Options\n// ============================================================================\n\n/**\n * Cache configuration options for RBAC permission caching.\n */\nexport interface PermissionCacheOptions {\n /** Maximum number of users to cache (default: 1000) */\n maxSize?: number;\n /** Time-to-live in milliseconds (default: 60000) */\n ttlMs?: number;\n}\n\n/**\n * Options for MastraRBACOkta.\n */\nexport interface MastraRBACOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n\n /** Okta API token for management SDK. Defaults to OKTA_API_TOKEN env var. */\n apiToken?: string;\n\n /**\n * Map Okta groups to Mastra permissions.\n *\n * @example\n * ```typescript\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * 'Viewer': ['agents:read', 'workflows:read'],\n * '_default': [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n\n /**\n * Function to extract Okta user ID from any user object.\n * Use this when using a different auth provider (e.g., Auth0) with Okta RBAC.\n *\n * @example\n * ```typescript\n * getUserId: (user) => user.metadata?.oktaUserId || user.email\n * ```\n */\n getUserId?: (user: unknown) => string | undefined;\n\n /** Permission cache configuration */\n cache?: PermissionCacheOptions;\n}\n","/**\n * MastraAuthOkta - Okta authentication provider for Mastra with SSO support.\n *\n * Supports OAuth 2.0 / OIDC login flow with client_secret and session management.\n */\n\nimport type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { HonoRequest } from 'hono';\nimport { createRemoteJWKSet, jwtVerify } from 'jose';\n\nimport type { OktaUser, MastraAuthOktaOptions } from './types.js';\nimport { mapOktaClaimsToUser } from './types.js';\n\n/** Default cookie name for Okta sessions */\nconst DEFAULT_COOKIE_NAME = 'okta_session';\n\n/** Default cookie max age (24 hours) */\nconst DEFAULT_COOKIE_MAX_AGE = 86400;\n\n/** Default OAuth scopes */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'email', 'groups'];\n\n/** PBKDF2 salt length in bytes */\nconst SALT_LENGTH = 16;\n\n/** AES-GCM IV length in bytes */\nconst IV_LENGTH = 12;\n\n/**\n * Derive an AES-GCM key from password + salt using PBKDF2.\n */\nasync function deriveKey(password: string, salt: Uint8Array, usage: 'encrypt' | 'decrypt') {\n const encoder = new TextEncoder();\n const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ]);\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n [usage],\n );\n}\n\n/**\n * Encrypt session data for cookie storage.\n * Format: base64(salt || iv || ciphertext)\n * Salt is random per-encryption to ensure unique derived keys.\n */\nasync function encryptSession(data: unknown, password: string): Promise<string> {\n const encoder = new TextEncoder();\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const key = await deriveKey(password, salt, 'encrypt');\n const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoder.encode(JSON.stringify(data)));\n const combined = new Uint8Array(salt.length + iv.length + new Uint8Array(encrypted).length);\n combined.set(salt);\n combined.set(iv, salt.length);\n combined.set(new Uint8Array(encrypted), salt.length + iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\n/**\n * Decrypt session data from cookie.\n * Reads the random salt from the ciphertext prefix to derive the same key.\n */\nasync function decryptSession(encrypted: string, password: string): Promise<unknown> {\n const combined = Uint8Array.from(atob(encrypted), c => c.charCodeAt(0));\n const salt = combined.slice(0, SALT_LENGTH);\n const iv = combined.slice(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n const data = combined.slice(SALT_LENGTH + IV_LENGTH);\n const key = await deriveKey(password, salt, 'decrypt');\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, data);\n return JSON.parse(new TextDecoder().decode(decrypted));\n}\n\n/**\n * In-memory store for state validation (keyed by state).\n * Used to validate that callback state matches the login request.\n */\nconst stateStore = new Map<string, { expiresAt: number; redirectUri: string }>();\n\n/**\n * Mastra authentication provider for Okta with SSO support.\n *\n * Implements OAuth 2.0 / OIDC login flow with encrypted session cookies.\n *\n * @example Basic usage with SSO\n * ```typescript\n * import { MastraAuthOkta } from '@mastra/auth-okta';\n *\n * const auth = new MastraAuthOkta({\n * domain: 'dev-123456.okta.com',\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUri: 'http://localhost:4111/api/auth/callback',\n * });\n * ```\n */\nexport class MastraAuthOkta\n extends MastraAuthProvider<OktaUser>\n implements ISSOProvider<OktaUser>, ISessionProvider<Session>, IUserProvider<OktaUser>\n{\n protected domain: string;\n protected clientId: string;\n protected clientSecret: string;\n protected issuer: string;\n protected redirectUri: string;\n protected scopes: string[];\n protected cookieName: string;\n protected cookieMaxAge: number;\n protected cookiePassword: string;\n protected secureCookies: boolean;\n protected apiToken?: string;\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(options?: MastraAuthOktaOptions) {\n super({ name: options?.name ?? 'okta' });\n\n const domain = options?.domain ?? process.env.OKTA_DOMAIN;\n const clientId = options?.clientId ?? process.env.OKTA_CLIENT_ID;\n const clientSecret = options?.clientSecret ?? process.env.OKTA_CLIENT_SECRET;\n const issuer = options?.issuer ?? process.env.OKTA_ISSUER;\n const redirectUri = options?.redirectUri ?? process.env.OKTA_REDIRECT_URI;\n const cookiePassword =\n options?.session?.cookiePassword ?? process.env.OKTA_COOKIE_PASSWORD ?? crypto.randomUUID() + crypto.randomUUID();\n\n if (!domain) {\n throw new Error('Okta domain is required. Provide it in the options or set OKTA_DOMAIN environment variable.');\n }\n\n if (!clientId) {\n throw new Error(\n 'Okta client ID is required. Provide it in the options or set OKTA_CLIENT_ID environment variable.',\n );\n }\n\n if (!clientSecret) {\n throw new Error(\n 'Okta client secret is required for SSO. Provide it in the options or set OKTA_CLIENT_SECRET environment variable.',\n );\n }\n\n if (!redirectUri) {\n throw new Error(\n 'Okta redirect URI is required for SSO. Provide it in the options or set OKTA_REDIRECT_URI environment variable.',\n );\n }\n\n if (cookiePassword.length < 32) {\n throw new Error('Cookie password must be at least 32 characters. Set OKTA_COOKIE_PASSWORD environment variable.');\n }\n\n this.domain = domain;\n this.clientId = clientId;\n this.clientSecret = clientSecret;\n this.issuer = issuer ?? `https://${domain}/oauth2/default`;\n this.redirectUri = redirectUri;\n this.scopes = options?.scopes ?? DEFAULT_SCOPES;\n this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;\n this.cookieMaxAge = options?.session?.cookieMaxAge ?? DEFAULT_COOKIE_MAX_AGE;\n this.cookiePassword = cookiePassword;\n this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === 'production';\n this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;\n this.jwks = createRemoteJWKSet(new URL(`${this.issuer}/v1/keys`));\n\n // Warn about insecure defaults in production\n if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {\n console.warn(\n '[MastraAuthOkta] No cookie password set — using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use.',\n );\n }\n\n if (process.env.NODE_ENV === 'production') {\n console.warn(\n '[MastraAuthOkta] Using in-memory OAuth state store. This will not work in serverless or multi-instance deployments. Consider implementing a custom state store for production.',\n );\n }\n\n this.registerOptions(options as MastraAuthProviderOptions<OktaUser>);\n }\n\n // ============================================================================\n // MastraAuthProvider Implementation\n // ============================================================================\n\n /**\n * Authenticate a token from the request.\n * First tries to read from session cookie, then falls back to Authorization header.\n */\n async authenticateToken(token: string, request: HonoRequest | Request): Promise<OktaUser | null> {\n // Try session cookie first\n const sessionUser = await this.getUserFromSession(request);\n if (sessionUser) {\n return sessionUser;\n }\n\n // Fall back to JWT verification from Authorization header\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n try {\n const { payload } = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n\n return mapOktaClaimsToUser(payload);\n } catch (err) {\n console.error('Okta token verification failed:', err);\n return null;\n }\n }\n\n /**\n * Authorize a user.\n */\n authorizeUser(user: OktaUser, _request: HonoRequest): boolean {\n if (!user || !user.oktaId) return false;\n return true;\n }\n\n // ============================================================================\n // IUserProvider Implementation\n // ============================================================================\n\n /**\n * Get the current user from the request session.\n */\n async getCurrentUser(request: Request): Promise<OktaUser | null> {\n return this.getUserFromSession(request);\n }\n\n /**\n * Get a user by ID via the Okta Users API.\n * Requires an API token (set OKTA_API_TOKEN or pass apiToken in options).\n * Returns null if no API token is configured or user is not found.\n */\n async getUser(userId: string): Promise<OktaUser | null> {\n if (!this.apiToken) {\n return null;\n }\n\n try {\n const response = await fetch(`https://${this.domain}/api/v1/users/${userId}`, {\n headers: {\n Authorization: `SSWS ${this.apiToken}`,\n Accept: 'application/json',\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n const oktaProfile = (await response.json()) as {\n id: string;\n profile: {\n login: string;\n email: string;\n firstName?: string;\n lastName?: string;\n };\n };\n\n return {\n id: oktaProfile.id,\n oktaId: oktaProfile.id,\n email: oktaProfile.profile.email,\n name: [oktaProfile.profile.firstName, oktaProfile.profile.lastName].filter(Boolean).join(' ') || undefined,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get user from session cookie.\n */\n private async getUserFromSession(request: HonoRequest | Request): Promise<OktaUser | null> {\n try {\n // Handle both HonoRequest and standard Request\n const cookieHeader = 'header' in request ? request.header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n user: OktaUser;\n idToken?: string;\n expiresAt: number;\n };\n\n // Check if session is expired\n if (session.expiresAt && session.expiresAt < Date.now()) {\n return null;\n }\n\n return session.user;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract the raw ID token from the encrypted session cookie.\n * Used to provide id_token_hint for Okta logout.\n */\n private async getIdTokenFromSession(request: Request): Promise<string | null> {\n try {\n const cookieHeader =\n 'header' in request ? (request as unknown as HonoRequest).header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n idToken?: string;\n };\n return session.idToken ?? null;\n } catch {\n return null;\n }\n }\n\n // ============================================================================\n // ISSOProvider Implementation\n // ============================================================================\n\n /**\n * Get the URL to redirect users to for Okta login.\n * Uses client_secret authentication (no PKCE) since this is a confidential client.\n */\n getLoginUrl(redirectUri: string, state: string): string {\n // State format from server: \"uuid|encodedRedirect\"\n // Extract just the UUID for storage (callback receives only UUID)\n const stateId = state.includes('|') ? state.split('|')[0]! : state;\n\n // Store state ID with redirect_uri for validation (expires in 10 minutes)\n const actualRedirectUri = redirectUri ?? this.redirectUri;\n stateStore.set(stateId, {\n expiresAt: Date.now() + 10 * 60 * 1000,\n redirectUri: actualRedirectUri,\n });\n\n // Clean up expired states\n for (const [key, value] of stateStore.entries()) {\n if (value.expiresAt < Date.now()) {\n stateStore.delete(key);\n }\n }\n\n const params = new URLSearchParams({\n client_id: this.clientId,\n response_type: 'code',\n scope: this.scopes.join(' '),\n redirect_uri: actualRedirectUri,\n state,\n });\n\n return `${this.issuer}/v1/authorize?${params.toString()}`;\n }\n\n /**\n * Handle the OAuth callback from Okta.\n * Note: The server passes only the stateId (UUID part), not the full state.\n */\n async handleCallback(code: string, stateId: string): Promise<SSOCallbackResult<OktaUser>> {\n // Validate state parameter (server passes only the UUID part)\n const stored = stateStore.get(stateId);\n if (!stored) {\n throw new Error('Invalid or expired state parameter');\n }\n stateStore.delete(stateId);\n\n if (stored.expiresAt < Date.now()) {\n throw new Error('State parameter has expired');\n }\n\n // Exchange code for tokens using client_secret (confidential client)\n const tokenResponse = await fetch(`${this.issuer}/v1/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${btoa(`${this.clientId}:${this.clientSecret}`)}`,\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: stored.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as {\n access_token: string;\n id_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n // Verify and decode ID token\n const { payload: idTokenPayload } = await jwtVerify(tokens.id_token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n const user = mapOktaClaimsToUser(idTokenPayload);\n\n // Create encrypted session cookie.\n // Only store user claims, id_token (for logout hint), and expiry.\n // Access/refresh tokens are NOT stored to keep cookie under 4KB browser limit.\n const sessionData = {\n user,\n idToken: tokens.id_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n\n const encryptedSession = await encryptSession(sessionData, this.cookiePassword);\n const cookieValue = `${this.cookieName}=${encodeURIComponent(encryptedSession)}; ${this.cookieFlags(this.cookieMaxAge)}`;\n\n return {\n user,\n tokens: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000),\n },\n cookies: [cookieValue],\n };\n }\n\n /**\n * Get the URL to redirect users to for logout.\n * Includes id_token_hint from session when available (required by Okta).\n */\n async getLogoutUrl(redirectUri: string, request?: Request): Promise<string | null> {\n const params = new URLSearchParams({\n post_logout_redirect_uri: redirectUri,\n client_id: this.clientId,\n });\n\n // Try to extract id_token from session for id_token_hint (Okta requires this)\n if (request) {\n const idToken = await this.getIdTokenFromSession(request);\n if (idToken) {\n params.set('id_token_hint', idToken);\n }\n }\n\n return `${this.issuer}/v1/logout?${params.toString()}`;\n }\n\n /**\n * Get cookies to set during login.\n */\n getLoginCookies(_state: string): string[] {\n return [];\n }\n\n /**\n * Get the configuration for rendering the login button.\n */\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'okta',\n text: 'Sign in with Okta',\n };\n }\n\n // ============================================================================\n // ISessionProvider Implementation\n // ============================================================================\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: crypto.randomUUID(),\n userId,\n createdAt: now,\n expiresAt: new Date(now.getTime() + this.cookieMaxAge * 1000),\n metadata,\n };\n }\n\n async validateSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n async destroySession(_sessionId: string): Promise<void> {\n // Session is cleared via cookie\n }\n\n async refreshSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n getSessionIdFromRequest(_request: Request): string | null {\n return null;\n }\n\n getSessionHeaders(_session: Session): Record<string, string> {\n return {};\n }\n\n getClearSessionHeaders(): Record<string, string> {\n return {\n 'Set-Cookie': `${this.cookieName}=; ${this.cookieFlags(0)}`,\n };\n }\n\n /**\n * Build consistent cookie attribute string for set/clear operations.\n */\n private cookieFlags(maxAge: number): string {\n const flags = `Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`;\n return this.secureCookies ? `${flags}; Secure` : flags;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Get the Okta domain.\n */\n getDomain(): string {\n return this.domain;\n }\n\n /**\n * Get the configured client ID.\n */\n getClientId(): string {\n return this.clientId;\n }\n\n /**\n * Get the configured redirect URI.\n */\n getRedirectUri(): string {\n return this.redirectUri;\n }\n\n /**\n * Get the issuer URL.\n */\n getIssuer(): string {\n return this.issuer;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rbac-provider.ts","../src/types.ts","../src/auth-provider.ts"],"names":["pkg","LRUCache","resolvePermissionsFromMapping","matchesPermission","MastraAuthProvider","createRemoteJWKSet","jwtVerify"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Okta RBAC provider for Mastra.\n *\n * Maps Okta groups to Mastra permissions using a configurable role mapping.\n * Can be used with any auth provider (Auth0, Clerk, etc.) or with MastraAuthOkta.\n */\n\nimport type { IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport pkg from '@okta/okta-sdk-nodejs';\nconst { Client } = pkg;\nimport { LRUCache } from 'lru-cache';\n\nimport type { OktaUser, MastraRBACOktaOptions } from './types.js';\n\n/** Default cache TTL in milliseconds (60 seconds) */\nconst DEFAULT_CACHE_TTL_MS = 60 * 1000;\n\n/** Default max cache size (number of users) */\nconst DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Okta RBAC provider that maps Okta groups to Mastra permissions.\n *\n * This provider fetches user groups from Okta and translates them into\n * Mastra permissions using a configurable role mapping.\n *\n * @example Basic usage with Okta auth\n * ```typescript\n * import { MastraAuthOkta, MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthOkta(),\n * rbac: new MastraRBACOkta({\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n *\n * @example Cross-provider usage (Auth0 + Okta RBAC)\n * ```typescript\n * import { MastraAuthAuth0 } from '@mastra/auth-auth0';\n * import { MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthAuth0(),\n * rbac: new MastraRBACOkta({\n * getUserId: (user) => user.metadata?.oktaUserId || user.email,\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n */\nexport class MastraRBACOkta implements IRBACProvider<OktaUser> {\n private oktaClient: InstanceType<typeof Client>;\n private options: MastraRBACOktaOptions;\n /**\n * Single cache for roles (the expensive Okta API call).\n * Permissions are derived from roles on-the-fly (cheap, synchronous).\n * Storing promises handles concurrent request deduplication.\n */\n private rolesCache: LRUCache<string, Promise<string[]>>;\n\n /**\n * Expose roleMapping for middleware access.\n * This allows the authorization middleware to resolve permissions\n * without needing to call the async methods.\n */\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n /**\n * Create a new Okta RBAC provider.\n *\n * @param options - RBAC configuration options\n */\n constructor(options: MastraRBACOktaOptions) {\n const domain = options.domain ?? process.env.OKTA_DOMAIN;\n const apiToken = options.apiToken ?? process.env.OKTA_API_TOKEN;\n\n if (!domain) {\n throw new Error(\n 'Okta domain is required. ' + 'Provide it in the options or set OKTA_DOMAIN environment variable.',\n );\n }\n\n if (!apiToken) {\n throw new Error(\n 'Okta API token is required for RBAC. ' +\n 'Provide it in the options or set OKTA_API_TOKEN environment variable.',\n );\n }\n\n this.oktaClient = new Client({\n orgUrl: `https://${domain}`,\n token: apiToken,\n });\n\n this.options = options;\n\n // Initialize LRU cache with configurable size and TTL\n this.rolesCache = new LRUCache<string, Promise<string[]>>({\n max: options.cache?.maxSize ?? DEFAULT_CACHE_MAX_SIZE,\n ttl: options.cache?.ttlMs ?? DEFAULT_CACHE_TTL_MS,\n });\n }\n\n /**\n * Get all roles (groups) for a user from Okta.\n *\n * If the user object already has groups attached, uses those.\n * Otherwise, fetches groups from Okta API and caches the result.\n *\n * @param user - User to get roles for\n * @returns Array of group names\n */\n async getRoles(user: OktaUser): Promise<string[]> {\n // If groups are already present on the user object, use them\n if (user.groups && user.groups.length > 0) {\n return user.groups;\n }\n\n // Determine the user ID to use for Okta API lookup\n const userId = this.resolveUserId(user);\n if (!userId) {\n return [];\n }\n\n // Check cache - returns existing promise (resolved or in-flight)\n const cached = this.rolesCache.get(userId);\n if (cached) {\n return cached;\n }\n\n // Create and cache the group fetch promise.\n // On failure, evict from cache so the next request retries,\n // then fall back to empty groups (which applies _default permissions).\n const groupsPromise = this.fetchGroupsFromOkta(userId).catch(err => {\n console.error(`[MastraRBACOkta] Failed to fetch groups for user ${userId}:`, err);\n this.rolesCache.delete(userId);\n return [];\n });\n this.rolesCache.set(userId, groupsPromise);\n\n return groupsPromise;\n }\n\n /**\n * Resolve the Okta user ID from the user object.\n * Uses custom getUserId function if provided, otherwise falls back to oktaId or id.\n */\n private resolveUserId(user: OktaUser): string | undefined {\n if (this.options.getUserId) {\n return this.options.getUserId(user);\n }\n return user.oktaId ?? user.id;\n }\n\n /**\n * Fetch groups from Okta API.\n * Errors propagate to the caller so the cache eviction in getRoles() works.\n */\n private async fetchGroupsFromOkta(userId: string): Promise<string[]> {\n const groups = await this.oktaClient.userApi.listUserGroups({ userId });\n const groupNames: string[] = [];\n\n for await (const group of groups) {\n if (group && group.profile?.name) {\n groupNames.push(group.profile.name);\n }\n }\n\n return groupNames;\n }\n\n /**\n * Check if a user has a specific role (group).\n *\n * @param user - User to check\n * @param role - Group name to check for\n * @returns True if user has the group\n */\n async hasRole(user: OktaUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n /**\n * Get all permissions for a user by mapping their Okta groups.\n *\n * @param user - User to get permissions for\n * @returns Array of permission strings\n */\n async getPermissions(user: OktaUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n /**\n * Check if a user has a specific permission.\n *\n * @param user - User to check\n * @param permission - Permission to check for (supports wildcards)\n * @returns True if user has the permission\n */\n async hasPermission(user: OktaUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n\n // Check if any granted permission matches the required permission\n return permissions.some(granted => matchesPermission(granted, permission));\n }\n\n /**\n * Check if a user has ALL of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has all permissions\n */\n async hasAllPermissions(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.every(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n\n /**\n * Check if a user has ANY of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has at least one permission\n */\n async hasAnyPermission(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.some(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n}\n","/**\n * Shared types for Okta integration.\n */\n\nimport type { EEUser, RoleMapping } from '@mastra/core/auth/ee';\nimport type { JWTPayload } from 'jose';\n\n// ============================================================================\n// User Types\n// ============================================================================\n\n/**\n * Extended EEUser with Okta-specific fields.\n */\nexport interface OktaUser extends EEUser {\n /** Okta user ID */\n oktaId: string;\n /** User's Okta groups (if fetched) */\n groups?: string[];\n}\n\n/**\n * Maps Okta JWT claims to OktaUser format.\n *\n * @param payload - JWT payload from Okta token\n * @returns OktaUser object\n */\nexport function mapOktaClaimsToUser(payload: JWTPayload): OktaUser {\n return {\n id: (payload.sub as string) || (payload.uid as string) || '',\n oktaId: (payload.sub as string) || (payload.uid as string) || '',\n email: payload.email as string | undefined,\n name:\n (payload.name as string) ||\n [payload.given_name, payload.family_name].filter(Boolean).join(' ') ||\n (payload.email as string) ||\n undefined,\n avatarUrl: payload.picture as string | undefined,\n groups: payload.groups as string[] | undefined,\n metadata: {\n oktaId: payload.sub,\n emailVerified: payload.email_verified,\n updatedAt: payload.updated_at,\n },\n };\n}\n\n// ============================================================================\n// Auth Provider Options\n// ============================================================================\n\n/**\n * Session configuration options for MastraAuthOkta.\n */\nexport interface OktaSessionOptions {\n /** Cookie name (default: 'okta_session') */\n cookieName?: string;\n /** Cookie max age in seconds (default: 86400 = 24 hours) */\n cookieMaxAge?: number;\n /**\n * Password for encrypting session cookies.\n * Must be at least 32 characters.\n * Defaults to OKTA_COOKIE_PASSWORD env var.\n */\n cookiePassword?: string;\n /**\n * Set the Secure flag on session cookies.\n * Defaults to true when NODE_ENV=production, false otherwise.\n */\n secureCookies?: boolean;\n}\n\n/**\n * Options for MastraAuthOkta.\n */\nexport interface MastraAuthOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n /** Okta OAuth client ID. Defaults to OKTA_CLIENT_ID env var. */\n clientId?: string;\n /** Okta OAuth client secret. Defaults to OKTA_CLIENT_SECRET env var. Required for SSO. */\n clientSecret?: string;\n /**\n * Token issuer URL.\n * Defaults to OKTA_ISSUER env var or `https://{domain}/oauth2/default`.\n */\n issuer?: string;\n /**\n * OAuth redirect URI for SSO callback.\n * Defaults to OKTA_REDIRECT_URI env var.\n */\n redirectUri?: string;\n /**\n * OAuth scopes to request.\n * Default: ['openid', 'profile', 'email', 'groups']\n */\n scopes?: string[];\n /**\n * Okta API token for user lookups via the Users API.\n * Required for getUser() to return user data by ID.\n * Defaults to OKTA_API_TOKEN env var.\n */\n apiToken?: string;\n /** Session configuration */\n session?: OktaSessionOptions;\n /** Custom provider name (default: 'okta') */\n name?: string;\n}\n\n// ============================================================================\n// RBAC Provider Options\n// ============================================================================\n\n/**\n * Cache configuration options for RBAC permission caching.\n */\nexport interface PermissionCacheOptions {\n /** Maximum number of users to cache (default: 1000) */\n maxSize?: number;\n /** Time-to-live in milliseconds (default: 60000) */\n ttlMs?: number;\n}\n\n/**\n * Options for MastraRBACOkta.\n */\nexport interface MastraRBACOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n\n /** Okta API token for management SDK. Defaults to OKTA_API_TOKEN env var. */\n apiToken?: string;\n\n /**\n * Map Okta groups to Mastra permissions.\n *\n * @example\n * ```typescript\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * 'Viewer': ['agents:read', 'workflows:read'],\n * '_default': [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n\n /**\n * Function to extract Okta user ID from any user object.\n * Use this when using a different auth provider (e.g., Auth0) with Okta RBAC.\n *\n * @example\n * ```typescript\n * getUserId: (user) => user.metadata?.oktaUserId || user.email\n * ```\n */\n getUserId?: (user: unknown) => string | undefined;\n\n /** Permission cache configuration */\n cache?: PermissionCacheOptions;\n}\n","/**\n * MastraAuthOkta - Okta authentication provider for Mastra with SSO support.\n *\n * Supports OAuth 2.0 / OIDC login flow with client_secret and session management.\n */\n\nimport type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { HonoRequest } from 'hono';\nimport { createRemoteJWKSet, jwtVerify } from 'jose';\n\nimport type { OktaUser, MastraAuthOktaOptions } from './types.js';\nimport { mapOktaClaimsToUser } from './types.js';\n\n/** Default cookie name for Okta sessions */\nconst DEFAULT_COOKIE_NAME = 'okta_session';\n\n/** Default cookie max age (24 hours) */\nconst DEFAULT_COOKIE_MAX_AGE = 86400;\n\n/** Default OAuth scopes */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'email', 'groups'];\n\n/** PBKDF2 salt length in bytes */\nconst SALT_LENGTH = 16;\n\n/** AES-GCM IV length in bytes */\nconst IV_LENGTH = 12;\n\n/**\n * Derive an AES-GCM key from password + salt using PBKDF2.\n */\nasync function deriveKey(password: string, salt: Uint8Array, usage: 'encrypt' | 'decrypt') {\n const encoder = new TextEncoder();\n const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ]);\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n [usage],\n );\n}\n\n/**\n * Encrypt session data for cookie storage.\n * Format: base64(salt || iv || ciphertext)\n * Salt is random per-encryption to ensure unique derived keys.\n */\nasync function encryptSession(data: unknown, password: string): Promise<string> {\n const encoder = new TextEncoder();\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const key = await deriveKey(password, salt, 'encrypt');\n const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoder.encode(JSON.stringify(data)));\n const combined = new Uint8Array(salt.length + iv.length + new Uint8Array(encrypted).length);\n combined.set(salt);\n combined.set(iv, salt.length);\n combined.set(new Uint8Array(encrypted), salt.length + iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\n/**\n * Decrypt session data from cookie.\n * Reads the random salt from the ciphertext prefix to derive the same key.\n */\nasync function decryptSession(encrypted: string, password: string): Promise<unknown> {\n const combined = Uint8Array.from(atob(encrypted), c => c.charCodeAt(0));\n const salt = combined.slice(0, SALT_LENGTH);\n const iv = combined.slice(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n const data = combined.slice(SALT_LENGTH + IV_LENGTH);\n const key = await deriveKey(password, salt, 'decrypt');\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, data);\n return JSON.parse(new TextDecoder().decode(decrypted));\n}\n\n/**\n * In-memory store for state validation (keyed by state).\n * Used to validate that callback state matches the login request.\n */\nconst stateStore = new Map<string, { expiresAt: number; redirectUri: string }>();\n\n/**\n * Mastra authentication provider for Okta with SSO support.\n *\n * Implements OAuth 2.0 / OIDC login flow with encrypted session cookies.\n *\n * @example Basic usage with SSO\n * ```typescript\n * import { MastraAuthOkta } from '@mastra/auth-okta';\n *\n * const auth = new MastraAuthOkta({\n * domain: 'dev-123456.okta.com',\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUri: 'http://localhost:4111/api/auth/callback',\n * });\n * ```\n */\nexport class MastraAuthOkta\n extends MastraAuthProvider<OktaUser>\n implements ISSOProvider<OktaUser>, ISessionProvider<Session>, IUserProvider<OktaUser>\n{\n protected domain: string;\n protected clientId: string;\n protected clientSecret: string;\n protected issuer: string;\n protected endpointBase: string;\n protected redirectUri: string;\n protected scopes: string[];\n protected cookieName: string;\n protected cookieMaxAge: number;\n protected cookiePassword: string;\n protected secureCookies: boolean;\n protected apiToken?: string;\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(options?: MastraAuthOktaOptions) {\n super({ name: options?.name ?? 'okta' });\n\n const domain = options?.domain ?? process.env.OKTA_DOMAIN;\n const clientId = options?.clientId ?? process.env.OKTA_CLIENT_ID;\n const clientSecret = options?.clientSecret ?? process.env.OKTA_CLIENT_SECRET;\n const issuer = options?.issuer ?? process.env.OKTA_ISSUER;\n const redirectUri = options?.redirectUri ?? process.env.OKTA_REDIRECT_URI;\n const cookiePassword =\n options?.session?.cookiePassword ?? process.env.OKTA_COOKIE_PASSWORD ?? crypto.randomUUID() + crypto.randomUUID();\n\n if (!domain) {\n throw new Error('Okta domain is required. Provide it in the options or set OKTA_DOMAIN environment variable.');\n }\n\n if (!clientId) {\n throw new Error(\n 'Okta client ID is required. Provide it in the options or set OKTA_CLIENT_ID environment variable.',\n );\n }\n\n if (!clientSecret) {\n throw new Error(\n 'Okta client secret is required for SSO. Provide it in the options or set OKTA_CLIENT_SECRET environment variable.',\n );\n }\n\n if (!redirectUri) {\n throw new Error(\n 'Okta redirect URI is required for SSO. Provide it in the options or set OKTA_REDIRECT_URI environment variable.',\n );\n }\n\n if (cookiePassword.length < 32) {\n throw new Error('Cookie password must be at least 32 characters. Set OKTA_COOKIE_PASSWORD environment variable.');\n }\n\n this.domain = domain;\n this.clientId = clientId;\n this.clientSecret = clientSecret;\n // Normalize trailing slashes so a stray `OKTA_ISSUER=https://domain/` doesn't produce `.../oauth2//v1/...`\n this.issuer = (issuer ?? `https://${domain}/oauth2/default`).replace(/\\/+$/, '');\n // Org authorization servers use issuer `https://{domain}` but serve endpoints under `/oauth2/v1/*`.\n // Custom authorization servers use issuer `https://{domain}/oauth2/<name>` and serve endpoints under `<issuer>/v1/*`.\n // `issuer` is still used verbatim for JWT `iss`-claim validation on both server types.\n this.endpointBase =\n this.issuer.includes('/oauth2/') || this.issuer.endsWith('/oauth2') ? this.issuer : `${this.issuer}/oauth2`;\n this.redirectUri = redirectUri;\n this.scopes = options?.scopes ?? DEFAULT_SCOPES;\n this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;\n this.cookieMaxAge = options?.session?.cookieMaxAge ?? DEFAULT_COOKIE_MAX_AGE;\n this.cookiePassword = cookiePassword;\n this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === 'production';\n this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;\n this.jwks = createRemoteJWKSet(new URL(`${this.endpointBase}/v1/keys`));\n\n // Warn about insecure defaults in production\n if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {\n console.warn(\n '[MastraAuthOkta] No cookie password set — using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use.',\n );\n }\n\n if (process.env.NODE_ENV === 'production') {\n console.warn(\n '[MastraAuthOkta] Using in-memory OAuth state store. This will not work in serverless or multi-instance deployments. Consider implementing a custom state store for production.',\n );\n }\n\n this.registerOptions(options as MastraAuthProviderOptions<OktaUser>);\n }\n\n // ============================================================================\n // MastraAuthProvider Implementation\n // ============================================================================\n\n /**\n * Authenticate a token from the request.\n * First tries to read from session cookie, then falls back to Authorization header.\n */\n async authenticateToken(token: string, request: HonoRequest | Request): Promise<OktaUser | null> {\n // Try session cookie first\n const sessionUser = await this.getUserFromSession(request);\n if (sessionUser) {\n return sessionUser;\n }\n\n // Fall back to JWT verification from Authorization header\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n try {\n const { payload } = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n\n return mapOktaClaimsToUser(payload);\n } catch (err) {\n console.error('Okta token verification failed:', err);\n return null;\n }\n }\n\n /**\n * Authorize a user.\n */\n authorizeUser(user: OktaUser, _request: HonoRequest): boolean {\n if (!user || !user.oktaId) return false;\n return true;\n }\n\n // ============================================================================\n // IUserProvider Implementation\n // ============================================================================\n\n /**\n * Get the current user from the request session.\n */\n async getCurrentUser(request: Request): Promise<OktaUser | null> {\n return this.getUserFromSession(request);\n }\n\n /**\n * Get a user by ID via the Okta Users API.\n * Requires an API token (set OKTA_API_TOKEN or pass apiToken in options).\n * Returns null if no API token is configured or user is not found.\n */\n async getUser(userId: string): Promise<OktaUser | null> {\n if (!this.apiToken) {\n return null;\n }\n\n try {\n const response = await fetch(`https://${this.domain}/api/v1/users/${userId}`, {\n headers: {\n Authorization: `SSWS ${this.apiToken}`,\n Accept: 'application/json',\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n const oktaProfile = (await response.json()) as {\n id: string;\n profile: {\n login: string;\n email: string;\n firstName?: string;\n lastName?: string;\n };\n };\n\n return {\n id: oktaProfile.id,\n oktaId: oktaProfile.id,\n email: oktaProfile.profile.email,\n name: [oktaProfile.profile.firstName, oktaProfile.profile.lastName].filter(Boolean).join(' ') || undefined,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get user from session cookie.\n */\n private async getUserFromSession(request: HonoRequest | Request): Promise<OktaUser | null> {\n try {\n // Handle both HonoRequest and standard Request\n const cookieHeader = 'header' in request ? request.header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n user: OktaUser;\n idToken?: string;\n expiresAt: number;\n };\n\n // Check if session is expired\n if (session.expiresAt && session.expiresAt < Date.now()) {\n return null;\n }\n\n return session.user;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract the raw ID token from the encrypted session cookie.\n * Used to provide id_token_hint for Okta logout.\n */\n private async getIdTokenFromSession(request: Request): Promise<string | null> {\n try {\n const cookieHeader =\n 'header' in request ? (request as unknown as HonoRequest).header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n idToken?: string;\n };\n return session.idToken ?? null;\n } catch {\n return null;\n }\n }\n\n // ============================================================================\n // ISSOProvider Implementation\n // ============================================================================\n\n /**\n * Get the URL to redirect users to for Okta login.\n * Uses client_secret authentication (no PKCE) since this is a confidential client.\n */\n getLoginUrl(redirectUri: string, state: string): string {\n // State format from server: \"uuid|encodedRedirect\"\n // Extract just the UUID for storage (callback receives only UUID)\n const stateId = state.includes('|') ? state.split('|')[0]! : state;\n\n // Store state ID with redirect_uri for validation (expires in 10 minutes)\n const actualRedirectUri = redirectUri ?? this.redirectUri;\n stateStore.set(stateId, {\n expiresAt: Date.now() + 10 * 60 * 1000,\n redirectUri: actualRedirectUri,\n });\n\n // Clean up expired states\n for (const [key, value] of stateStore.entries()) {\n if (value.expiresAt < Date.now()) {\n stateStore.delete(key);\n }\n }\n\n const params = new URLSearchParams({\n client_id: this.clientId,\n response_type: 'code',\n scope: this.scopes.join(' '),\n redirect_uri: actualRedirectUri,\n state,\n });\n\n return `${this.endpointBase}/v1/authorize?${params.toString()}`;\n }\n\n /**\n * Handle the OAuth callback from Okta.\n * Note: The server passes only the stateId (UUID part), not the full state.\n */\n async handleCallback(code: string, stateId: string): Promise<SSOCallbackResult<OktaUser>> {\n // Validate state parameter (server passes only the UUID part)\n const stored = stateStore.get(stateId);\n if (!stored) {\n throw new Error('Invalid or expired state parameter');\n }\n stateStore.delete(stateId);\n\n if (stored.expiresAt < Date.now()) {\n throw new Error('State parameter has expired');\n }\n\n // Exchange code for tokens using client_secret (confidential client)\n const tokenResponse = await fetch(`${this.endpointBase}/v1/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${btoa(`${this.clientId}:${this.clientSecret}`)}`,\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: stored.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as {\n access_token: string;\n id_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n // Verify and decode ID token\n const { payload: idTokenPayload } = await jwtVerify(tokens.id_token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n const user = mapOktaClaimsToUser(idTokenPayload);\n\n // Create encrypted session cookie.\n // Only store user claims, id_token (for logout hint), and expiry.\n // Access/refresh tokens are NOT stored to keep cookie under 4KB browser limit.\n const sessionData = {\n user,\n idToken: tokens.id_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n\n const encryptedSession = await encryptSession(sessionData, this.cookiePassword);\n const cookieValue = `${this.cookieName}=${encodeURIComponent(encryptedSession)}; ${this.cookieFlags(this.cookieMaxAge)}`;\n\n return {\n user,\n tokens: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000),\n },\n cookies: [cookieValue],\n };\n }\n\n /**\n * Get the URL to redirect users to for logout.\n * Includes id_token_hint from session when available (required by Okta).\n */\n async getLogoutUrl(redirectUri: string, request?: Request): Promise<string | null> {\n const params = new URLSearchParams({\n post_logout_redirect_uri: redirectUri,\n client_id: this.clientId,\n });\n\n // Try to extract id_token from session for id_token_hint (Okta requires this)\n if (request) {\n const idToken = await this.getIdTokenFromSession(request);\n if (idToken) {\n params.set('id_token_hint', idToken);\n }\n }\n\n return `${this.endpointBase}/v1/logout?${params.toString()}`;\n }\n\n /**\n * Get cookies to set during login.\n */\n getLoginCookies(_state: string): string[] {\n return [];\n }\n\n /**\n * Get the configuration for rendering the login button.\n */\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'okta',\n text: 'Sign in with Okta',\n };\n }\n\n // ============================================================================\n // ISessionProvider Implementation\n // ============================================================================\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: crypto.randomUUID(),\n userId,\n createdAt: now,\n expiresAt: new Date(now.getTime() + this.cookieMaxAge * 1000),\n metadata,\n };\n }\n\n async validateSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n async destroySession(_sessionId: string): Promise<void> {\n // Session is cleared via cookie\n }\n\n async refreshSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n getSessionIdFromRequest(_request: Request): string | null {\n return null;\n }\n\n getSessionHeaders(_session: Session): Record<string, string> {\n return {};\n }\n\n getClearSessionHeaders(): Record<string, string> {\n return {\n 'Set-Cookie': `${this.cookieName}=; ${this.cookieFlags(0)}`,\n };\n }\n\n /**\n * Build consistent cookie attribute string for set/clear operations.\n */\n private cookieFlags(maxAge: number): string {\n const flags = `Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`;\n return this.secureCookies ? `${flags}; Secure` : flags;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Get the Okta domain.\n */\n getDomain(): string {\n return this.domain;\n }\n\n /**\n * Get the configured client ID.\n */\n getClientId(): string {\n return this.clientId;\n }\n\n /**\n * Get the configured redirect URI.\n */\n getRedirectUri(): string {\n return this.redirectUri;\n }\n\n /**\n * Get the issuer URL.\n */\n getIssuer(): string {\n return this.issuer;\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -226,6 +226,7 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
226
226
|
clientId;
|
|
227
227
|
clientSecret;
|
|
228
228
|
issuer;
|
|
229
|
+
endpointBase;
|
|
229
230
|
redirectUri;
|
|
230
231
|
scopes;
|
|
231
232
|
cookieName;
|
|
@@ -266,7 +267,8 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
266
267
|
this.domain = domain;
|
|
267
268
|
this.clientId = clientId;
|
|
268
269
|
this.clientSecret = clientSecret;
|
|
269
|
-
this.issuer = issuer ?? `https://${domain}/oauth2/default
|
|
270
|
+
this.issuer = (issuer ?? `https://${domain}/oauth2/default`).replace(/\/+$/, "");
|
|
271
|
+
this.endpointBase = this.issuer.includes("/oauth2/") || this.issuer.endsWith("/oauth2") ? this.issuer : `${this.issuer}/oauth2`;
|
|
270
272
|
this.redirectUri = redirectUri;
|
|
271
273
|
this.scopes = options?.scopes ?? DEFAULT_SCOPES;
|
|
272
274
|
this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;
|
|
@@ -274,7 +276,7 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
274
276
|
this.cookiePassword = cookiePassword;
|
|
275
277
|
this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === "production";
|
|
276
278
|
this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;
|
|
277
|
-
this.jwks = createRemoteJWKSet(new URL(`${this.
|
|
279
|
+
this.jwks = createRemoteJWKSet(new URL(`${this.endpointBase}/v1/keys`));
|
|
278
280
|
if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {
|
|
279
281
|
console.warn(
|
|
280
282
|
"[MastraAuthOkta] No cookie password set \u2014 using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use."
|
|
@@ -425,7 +427,7 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
425
427
|
redirect_uri: actualRedirectUri,
|
|
426
428
|
state
|
|
427
429
|
});
|
|
428
|
-
return `${this.
|
|
430
|
+
return `${this.endpointBase}/v1/authorize?${params.toString()}`;
|
|
429
431
|
}
|
|
430
432
|
/**
|
|
431
433
|
* Handle the OAuth callback from Okta.
|
|
@@ -440,7 +442,7 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
440
442
|
if (stored.expiresAt < Date.now()) {
|
|
441
443
|
throw new Error("State parameter has expired");
|
|
442
444
|
}
|
|
443
|
-
const tokenResponse = await fetch(`${this.
|
|
445
|
+
const tokenResponse = await fetch(`${this.endpointBase}/v1/token`, {
|
|
444
446
|
method: "POST",
|
|
445
447
|
headers: {
|
|
446
448
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -495,7 +497,7 @@ var MastraAuthOkta = class extends MastraAuthProvider {
|
|
|
495
497
|
params.set("id_token_hint", idToken);
|
|
496
498
|
}
|
|
497
499
|
}
|
|
498
|
-
return `${this.
|
|
500
|
+
return `${this.endpointBase}/v1/logout?${params.toString()}`;
|
|
499
501
|
}
|
|
500
502
|
/**
|
|
501
503
|
* Get cookies to set during login.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rbac-provider.ts","../src/types.ts","../src/auth-provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Okta RBAC provider for Mastra.\n *\n * Maps Okta groups to Mastra permissions using a configurable role mapping.\n * Can be used with any auth provider (Auth0, Clerk, etc.) or with MastraAuthOkta.\n */\n\nimport type { IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport pkg from '@okta/okta-sdk-nodejs';\nconst { Client } = pkg;\nimport { LRUCache } from 'lru-cache';\n\nimport type { OktaUser, MastraRBACOktaOptions } from './types.js';\n\n/** Default cache TTL in milliseconds (60 seconds) */\nconst DEFAULT_CACHE_TTL_MS = 60 * 1000;\n\n/** Default max cache size (number of users) */\nconst DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Okta RBAC provider that maps Okta groups to Mastra permissions.\n *\n * This provider fetches user groups from Okta and translates them into\n * Mastra permissions using a configurable role mapping.\n *\n * @example Basic usage with Okta auth\n * ```typescript\n * import { MastraAuthOkta, MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthOkta(),\n * rbac: new MastraRBACOkta({\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n *\n * @example Cross-provider usage (Auth0 + Okta RBAC)\n * ```typescript\n * import { MastraAuthAuth0 } from '@mastra/auth-auth0';\n * import { MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthAuth0(),\n * rbac: new MastraRBACOkta({\n * getUserId: (user) => user.metadata?.oktaUserId || user.email,\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n */\nexport class MastraRBACOkta implements IRBACProvider<OktaUser> {\n private oktaClient: InstanceType<typeof Client>;\n private options: MastraRBACOktaOptions;\n /**\n * Single cache for roles (the expensive Okta API call).\n * Permissions are derived from roles on-the-fly (cheap, synchronous).\n * Storing promises handles concurrent request deduplication.\n */\n private rolesCache: LRUCache<string, Promise<string[]>>;\n\n /**\n * Expose roleMapping for middleware access.\n * This allows the authorization middleware to resolve permissions\n * without needing to call the async methods.\n */\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n /**\n * Create a new Okta RBAC provider.\n *\n * @param options - RBAC configuration options\n */\n constructor(options: MastraRBACOktaOptions) {\n const domain = options.domain ?? process.env.OKTA_DOMAIN;\n const apiToken = options.apiToken ?? process.env.OKTA_API_TOKEN;\n\n if (!domain) {\n throw new Error(\n 'Okta domain is required. ' + 'Provide it in the options or set OKTA_DOMAIN environment variable.',\n );\n }\n\n if (!apiToken) {\n throw new Error(\n 'Okta API token is required for RBAC. ' +\n 'Provide it in the options or set OKTA_API_TOKEN environment variable.',\n );\n }\n\n this.oktaClient = new Client({\n orgUrl: `https://${domain}`,\n token: apiToken,\n });\n\n this.options = options;\n\n // Initialize LRU cache with configurable size and TTL\n this.rolesCache = new LRUCache<string, Promise<string[]>>({\n max: options.cache?.maxSize ?? DEFAULT_CACHE_MAX_SIZE,\n ttl: options.cache?.ttlMs ?? DEFAULT_CACHE_TTL_MS,\n });\n }\n\n /**\n * Get all roles (groups) for a user from Okta.\n *\n * If the user object already has groups attached, uses those.\n * Otherwise, fetches groups from Okta API and caches the result.\n *\n * @param user - User to get roles for\n * @returns Array of group names\n */\n async getRoles(user: OktaUser): Promise<string[]> {\n // If groups are already present on the user object, use them\n if (user.groups && user.groups.length > 0) {\n return user.groups;\n }\n\n // Determine the user ID to use for Okta API lookup\n const userId = this.resolveUserId(user);\n if (!userId) {\n return [];\n }\n\n // Check cache - returns existing promise (resolved or in-flight)\n const cached = this.rolesCache.get(userId);\n if (cached) {\n return cached;\n }\n\n // Create and cache the group fetch promise.\n // On failure, evict from cache so the next request retries,\n // then fall back to empty groups (which applies _default permissions).\n const groupsPromise = this.fetchGroupsFromOkta(userId).catch(err => {\n console.error(`[MastraRBACOkta] Failed to fetch groups for user ${userId}:`, err);\n this.rolesCache.delete(userId);\n return [];\n });\n this.rolesCache.set(userId, groupsPromise);\n\n return groupsPromise;\n }\n\n /**\n * Resolve the Okta user ID from the user object.\n * Uses custom getUserId function if provided, otherwise falls back to oktaId or id.\n */\n private resolveUserId(user: OktaUser): string | undefined {\n if (this.options.getUserId) {\n return this.options.getUserId(user);\n }\n return user.oktaId ?? user.id;\n }\n\n /**\n * Fetch groups from Okta API.\n * Errors propagate to the caller so the cache eviction in getRoles() works.\n */\n private async fetchGroupsFromOkta(userId: string): Promise<string[]> {\n const groups = await this.oktaClient.userApi.listUserGroups({ userId });\n const groupNames: string[] = [];\n\n for await (const group of groups) {\n if (group && group.profile?.name) {\n groupNames.push(group.profile.name);\n }\n }\n\n return groupNames;\n }\n\n /**\n * Check if a user has a specific role (group).\n *\n * @param user - User to check\n * @param role - Group name to check for\n * @returns True if user has the group\n */\n async hasRole(user: OktaUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n /**\n * Get all permissions for a user by mapping their Okta groups.\n *\n * @param user - User to get permissions for\n * @returns Array of permission strings\n */\n async getPermissions(user: OktaUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n /**\n * Check if a user has a specific permission.\n *\n * @param user - User to check\n * @param permission - Permission to check for (supports wildcards)\n * @returns True if user has the permission\n */\n async hasPermission(user: OktaUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n\n // Check if any granted permission matches the required permission\n return permissions.some(granted => matchesPermission(granted, permission));\n }\n\n /**\n * Check if a user has ALL of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has all permissions\n */\n async hasAllPermissions(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.every(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n\n /**\n * Check if a user has ANY of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has at least one permission\n */\n async hasAnyPermission(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.some(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n}\n","/**\n * Shared types for Okta integration.\n */\n\nimport type { EEUser, RoleMapping } from '@mastra/core/auth/ee';\nimport type { JWTPayload } from 'jose';\n\n// ============================================================================\n// User Types\n// ============================================================================\n\n/**\n * Extended EEUser with Okta-specific fields.\n */\nexport interface OktaUser extends EEUser {\n /** Okta user ID */\n oktaId: string;\n /** User's Okta groups (if fetched) */\n groups?: string[];\n}\n\n/**\n * Maps Okta JWT claims to OktaUser format.\n *\n * @param payload - JWT payload from Okta token\n * @returns OktaUser object\n */\nexport function mapOktaClaimsToUser(payload: JWTPayload): OktaUser {\n return {\n id: (payload.sub as string) || (payload.uid as string) || '',\n oktaId: (payload.sub as string) || (payload.uid as string) || '',\n email: payload.email as string | undefined,\n name:\n (payload.name as string) ||\n [payload.given_name, payload.family_name].filter(Boolean).join(' ') ||\n (payload.email as string) ||\n undefined,\n avatarUrl: payload.picture as string | undefined,\n groups: payload.groups as string[] | undefined,\n metadata: {\n oktaId: payload.sub,\n emailVerified: payload.email_verified,\n updatedAt: payload.updated_at,\n },\n };\n}\n\n// ============================================================================\n// Auth Provider Options\n// ============================================================================\n\n/**\n * Session configuration options for MastraAuthOkta.\n */\nexport interface OktaSessionOptions {\n /** Cookie name (default: 'okta_session') */\n cookieName?: string;\n /** Cookie max age in seconds (default: 86400 = 24 hours) */\n cookieMaxAge?: number;\n /**\n * Password for encrypting session cookies.\n * Must be at least 32 characters.\n * Defaults to OKTA_COOKIE_PASSWORD env var.\n */\n cookiePassword?: string;\n /**\n * Set the Secure flag on session cookies.\n * Defaults to true when NODE_ENV=production, false otherwise.\n */\n secureCookies?: boolean;\n}\n\n/**\n * Options for MastraAuthOkta.\n */\nexport interface MastraAuthOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n /** Okta OAuth client ID. Defaults to OKTA_CLIENT_ID env var. */\n clientId?: string;\n /** Okta OAuth client secret. Defaults to OKTA_CLIENT_SECRET env var. Required for SSO. */\n clientSecret?: string;\n /**\n * Token issuer URL.\n * Defaults to OKTA_ISSUER env var or `https://{domain}/oauth2/default`.\n */\n issuer?: string;\n /**\n * OAuth redirect URI for SSO callback.\n * Defaults to OKTA_REDIRECT_URI env var.\n */\n redirectUri?: string;\n /**\n * OAuth scopes to request.\n * Default: ['openid', 'profile', 'email', 'groups']\n */\n scopes?: string[];\n /**\n * Okta API token for user lookups via the Users API.\n * Required for getUser() to return user data by ID.\n * Defaults to OKTA_API_TOKEN env var.\n */\n apiToken?: string;\n /** Session configuration */\n session?: OktaSessionOptions;\n /** Custom provider name (default: 'okta') */\n name?: string;\n}\n\n// ============================================================================\n// RBAC Provider Options\n// ============================================================================\n\n/**\n * Cache configuration options for RBAC permission caching.\n */\nexport interface PermissionCacheOptions {\n /** Maximum number of users to cache (default: 1000) */\n maxSize?: number;\n /** Time-to-live in milliseconds (default: 60000) */\n ttlMs?: number;\n}\n\n/**\n * Options for MastraRBACOkta.\n */\nexport interface MastraRBACOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n\n /** Okta API token for management SDK. Defaults to OKTA_API_TOKEN env var. */\n apiToken?: string;\n\n /**\n * Map Okta groups to Mastra permissions.\n *\n * @example\n * ```typescript\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * 'Viewer': ['agents:read', 'workflows:read'],\n * '_default': [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n\n /**\n * Function to extract Okta user ID from any user object.\n * Use this when using a different auth provider (e.g., Auth0) with Okta RBAC.\n *\n * @example\n * ```typescript\n * getUserId: (user) => user.metadata?.oktaUserId || user.email\n * ```\n */\n getUserId?: (user: unknown) => string | undefined;\n\n /** Permission cache configuration */\n cache?: PermissionCacheOptions;\n}\n","/**\n * MastraAuthOkta - Okta authentication provider for Mastra with SSO support.\n *\n * Supports OAuth 2.0 / OIDC login flow with client_secret and session management.\n */\n\nimport type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { HonoRequest } from 'hono';\nimport { createRemoteJWKSet, jwtVerify } from 'jose';\n\nimport type { OktaUser, MastraAuthOktaOptions } from './types.js';\nimport { mapOktaClaimsToUser } from './types.js';\n\n/** Default cookie name for Okta sessions */\nconst DEFAULT_COOKIE_NAME = 'okta_session';\n\n/** Default cookie max age (24 hours) */\nconst DEFAULT_COOKIE_MAX_AGE = 86400;\n\n/** Default OAuth scopes */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'email', 'groups'];\n\n/** PBKDF2 salt length in bytes */\nconst SALT_LENGTH = 16;\n\n/** AES-GCM IV length in bytes */\nconst IV_LENGTH = 12;\n\n/**\n * Derive an AES-GCM key from password + salt using PBKDF2.\n */\nasync function deriveKey(password: string, salt: Uint8Array, usage: 'encrypt' | 'decrypt') {\n const encoder = new TextEncoder();\n const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ]);\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n [usage],\n );\n}\n\n/**\n * Encrypt session data for cookie storage.\n * Format: base64(salt || iv || ciphertext)\n * Salt is random per-encryption to ensure unique derived keys.\n */\nasync function encryptSession(data: unknown, password: string): Promise<string> {\n const encoder = new TextEncoder();\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const key = await deriveKey(password, salt, 'encrypt');\n const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoder.encode(JSON.stringify(data)));\n const combined = new Uint8Array(salt.length + iv.length + new Uint8Array(encrypted).length);\n combined.set(salt);\n combined.set(iv, salt.length);\n combined.set(new Uint8Array(encrypted), salt.length + iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\n/**\n * Decrypt session data from cookie.\n * Reads the random salt from the ciphertext prefix to derive the same key.\n */\nasync function decryptSession(encrypted: string, password: string): Promise<unknown> {\n const combined = Uint8Array.from(atob(encrypted), c => c.charCodeAt(0));\n const salt = combined.slice(0, SALT_LENGTH);\n const iv = combined.slice(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n const data = combined.slice(SALT_LENGTH + IV_LENGTH);\n const key = await deriveKey(password, salt, 'decrypt');\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, data);\n return JSON.parse(new TextDecoder().decode(decrypted));\n}\n\n/**\n * In-memory store for state validation (keyed by state).\n * Used to validate that callback state matches the login request.\n */\nconst stateStore = new Map<string, { expiresAt: number; redirectUri: string }>();\n\n/**\n * Mastra authentication provider for Okta with SSO support.\n *\n * Implements OAuth 2.0 / OIDC login flow with encrypted session cookies.\n *\n * @example Basic usage with SSO\n * ```typescript\n * import { MastraAuthOkta } from '@mastra/auth-okta';\n *\n * const auth = new MastraAuthOkta({\n * domain: 'dev-123456.okta.com',\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUri: 'http://localhost:4111/api/auth/callback',\n * });\n * ```\n */\nexport class MastraAuthOkta\n extends MastraAuthProvider<OktaUser>\n implements ISSOProvider<OktaUser>, ISessionProvider<Session>, IUserProvider<OktaUser>\n{\n protected domain: string;\n protected clientId: string;\n protected clientSecret: string;\n protected issuer: string;\n protected redirectUri: string;\n protected scopes: string[];\n protected cookieName: string;\n protected cookieMaxAge: number;\n protected cookiePassword: string;\n protected secureCookies: boolean;\n protected apiToken?: string;\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(options?: MastraAuthOktaOptions) {\n super({ name: options?.name ?? 'okta' });\n\n const domain = options?.domain ?? process.env.OKTA_DOMAIN;\n const clientId = options?.clientId ?? process.env.OKTA_CLIENT_ID;\n const clientSecret = options?.clientSecret ?? process.env.OKTA_CLIENT_SECRET;\n const issuer = options?.issuer ?? process.env.OKTA_ISSUER;\n const redirectUri = options?.redirectUri ?? process.env.OKTA_REDIRECT_URI;\n const cookiePassword =\n options?.session?.cookiePassword ?? process.env.OKTA_COOKIE_PASSWORD ?? crypto.randomUUID() + crypto.randomUUID();\n\n if (!domain) {\n throw new Error('Okta domain is required. Provide it in the options or set OKTA_DOMAIN environment variable.');\n }\n\n if (!clientId) {\n throw new Error(\n 'Okta client ID is required. Provide it in the options or set OKTA_CLIENT_ID environment variable.',\n );\n }\n\n if (!clientSecret) {\n throw new Error(\n 'Okta client secret is required for SSO. Provide it in the options or set OKTA_CLIENT_SECRET environment variable.',\n );\n }\n\n if (!redirectUri) {\n throw new Error(\n 'Okta redirect URI is required for SSO. Provide it in the options or set OKTA_REDIRECT_URI environment variable.',\n );\n }\n\n if (cookiePassword.length < 32) {\n throw new Error('Cookie password must be at least 32 characters. Set OKTA_COOKIE_PASSWORD environment variable.');\n }\n\n this.domain = domain;\n this.clientId = clientId;\n this.clientSecret = clientSecret;\n this.issuer = issuer ?? `https://${domain}/oauth2/default`;\n this.redirectUri = redirectUri;\n this.scopes = options?.scopes ?? DEFAULT_SCOPES;\n this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;\n this.cookieMaxAge = options?.session?.cookieMaxAge ?? DEFAULT_COOKIE_MAX_AGE;\n this.cookiePassword = cookiePassword;\n this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === 'production';\n this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;\n this.jwks = createRemoteJWKSet(new URL(`${this.issuer}/v1/keys`));\n\n // Warn about insecure defaults in production\n if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {\n console.warn(\n '[MastraAuthOkta] No cookie password set — using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use.',\n );\n }\n\n if (process.env.NODE_ENV === 'production') {\n console.warn(\n '[MastraAuthOkta] Using in-memory OAuth state store. This will not work in serverless or multi-instance deployments. Consider implementing a custom state store for production.',\n );\n }\n\n this.registerOptions(options as MastraAuthProviderOptions<OktaUser>);\n }\n\n // ============================================================================\n // MastraAuthProvider Implementation\n // ============================================================================\n\n /**\n * Authenticate a token from the request.\n * First tries to read from session cookie, then falls back to Authorization header.\n */\n async authenticateToken(token: string, request: HonoRequest | Request): Promise<OktaUser | null> {\n // Try session cookie first\n const sessionUser = await this.getUserFromSession(request);\n if (sessionUser) {\n return sessionUser;\n }\n\n // Fall back to JWT verification from Authorization header\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n try {\n const { payload } = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n\n return mapOktaClaimsToUser(payload);\n } catch (err) {\n console.error('Okta token verification failed:', err);\n return null;\n }\n }\n\n /**\n * Authorize a user.\n */\n authorizeUser(user: OktaUser, _request: HonoRequest): boolean {\n if (!user || !user.oktaId) return false;\n return true;\n }\n\n // ============================================================================\n // IUserProvider Implementation\n // ============================================================================\n\n /**\n * Get the current user from the request session.\n */\n async getCurrentUser(request: Request): Promise<OktaUser | null> {\n return this.getUserFromSession(request);\n }\n\n /**\n * Get a user by ID via the Okta Users API.\n * Requires an API token (set OKTA_API_TOKEN or pass apiToken in options).\n * Returns null if no API token is configured or user is not found.\n */\n async getUser(userId: string): Promise<OktaUser | null> {\n if (!this.apiToken) {\n return null;\n }\n\n try {\n const response = await fetch(`https://${this.domain}/api/v1/users/${userId}`, {\n headers: {\n Authorization: `SSWS ${this.apiToken}`,\n Accept: 'application/json',\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n const oktaProfile = (await response.json()) as {\n id: string;\n profile: {\n login: string;\n email: string;\n firstName?: string;\n lastName?: string;\n };\n };\n\n return {\n id: oktaProfile.id,\n oktaId: oktaProfile.id,\n email: oktaProfile.profile.email,\n name: [oktaProfile.profile.firstName, oktaProfile.profile.lastName].filter(Boolean).join(' ') || undefined,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get user from session cookie.\n */\n private async getUserFromSession(request: HonoRequest | Request): Promise<OktaUser | null> {\n try {\n // Handle both HonoRequest and standard Request\n const cookieHeader = 'header' in request ? request.header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n user: OktaUser;\n idToken?: string;\n expiresAt: number;\n };\n\n // Check if session is expired\n if (session.expiresAt && session.expiresAt < Date.now()) {\n return null;\n }\n\n return session.user;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract the raw ID token from the encrypted session cookie.\n * Used to provide id_token_hint for Okta logout.\n */\n private async getIdTokenFromSession(request: Request): Promise<string | null> {\n try {\n const cookieHeader =\n 'header' in request ? (request as unknown as HonoRequest).header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n idToken?: string;\n };\n return session.idToken ?? null;\n } catch {\n return null;\n }\n }\n\n // ============================================================================\n // ISSOProvider Implementation\n // ============================================================================\n\n /**\n * Get the URL to redirect users to for Okta login.\n * Uses client_secret authentication (no PKCE) since this is a confidential client.\n */\n getLoginUrl(redirectUri: string, state: string): string {\n // State format from server: \"uuid|encodedRedirect\"\n // Extract just the UUID for storage (callback receives only UUID)\n const stateId = state.includes('|') ? state.split('|')[0]! : state;\n\n // Store state ID with redirect_uri for validation (expires in 10 minutes)\n const actualRedirectUri = redirectUri ?? this.redirectUri;\n stateStore.set(stateId, {\n expiresAt: Date.now() + 10 * 60 * 1000,\n redirectUri: actualRedirectUri,\n });\n\n // Clean up expired states\n for (const [key, value] of stateStore.entries()) {\n if (value.expiresAt < Date.now()) {\n stateStore.delete(key);\n }\n }\n\n const params = new URLSearchParams({\n client_id: this.clientId,\n response_type: 'code',\n scope: this.scopes.join(' '),\n redirect_uri: actualRedirectUri,\n state,\n });\n\n return `${this.issuer}/v1/authorize?${params.toString()}`;\n }\n\n /**\n * Handle the OAuth callback from Okta.\n * Note: The server passes only the stateId (UUID part), not the full state.\n */\n async handleCallback(code: string, stateId: string): Promise<SSOCallbackResult<OktaUser>> {\n // Validate state parameter (server passes only the UUID part)\n const stored = stateStore.get(stateId);\n if (!stored) {\n throw new Error('Invalid or expired state parameter');\n }\n stateStore.delete(stateId);\n\n if (stored.expiresAt < Date.now()) {\n throw new Error('State parameter has expired');\n }\n\n // Exchange code for tokens using client_secret (confidential client)\n const tokenResponse = await fetch(`${this.issuer}/v1/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${btoa(`${this.clientId}:${this.clientSecret}`)}`,\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: stored.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as {\n access_token: string;\n id_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n // Verify and decode ID token\n const { payload: idTokenPayload } = await jwtVerify(tokens.id_token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n const user = mapOktaClaimsToUser(idTokenPayload);\n\n // Create encrypted session cookie.\n // Only store user claims, id_token (for logout hint), and expiry.\n // Access/refresh tokens are NOT stored to keep cookie under 4KB browser limit.\n const sessionData = {\n user,\n idToken: tokens.id_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n\n const encryptedSession = await encryptSession(sessionData, this.cookiePassword);\n const cookieValue = `${this.cookieName}=${encodeURIComponent(encryptedSession)}; ${this.cookieFlags(this.cookieMaxAge)}`;\n\n return {\n user,\n tokens: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000),\n },\n cookies: [cookieValue],\n };\n }\n\n /**\n * Get the URL to redirect users to for logout.\n * Includes id_token_hint from session when available (required by Okta).\n */\n async getLogoutUrl(redirectUri: string, request?: Request): Promise<string | null> {\n const params = new URLSearchParams({\n post_logout_redirect_uri: redirectUri,\n client_id: this.clientId,\n });\n\n // Try to extract id_token from session for id_token_hint (Okta requires this)\n if (request) {\n const idToken = await this.getIdTokenFromSession(request);\n if (idToken) {\n params.set('id_token_hint', idToken);\n }\n }\n\n return `${this.issuer}/v1/logout?${params.toString()}`;\n }\n\n /**\n * Get cookies to set during login.\n */\n getLoginCookies(_state: string): string[] {\n return [];\n }\n\n /**\n * Get the configuration for rendering the login button.\n */\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'okta',\n text: 'Sign in with Okta',\n };\n }\n\n // ============================================================================\n // ISessionProvider Implementation\n // ============================================================================\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: crypto.randomUUID(),\n userId,\n createdAt: now,\n expiresAt: new Date(now.getTime() + this.cookieMaxAge * 1000),\n metadata,\n };\n }\n\n async validateSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n async destroySession(_sessionId: string): Promise<void> {\n // Session is cleared via cookie\n }\n\n async refreshSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n getSessionIdFromRequest(_request: Request): string | null {\n return null;\n }\n\n getSessionHeaders(_session: Session): Record<string, string> {\n return {};\n }\n\n getClearSessionHeaders(): Record<string, string> {\n return {\n 'Set-Cookie': `${this.cookieName}=; ${this.cookieFlags(0)}`,\n };\n }\n\n /**\n * Build consistent cookie attribute string for set/clear operations.\n */\n private cookieFlags(maxAge: number): string {\n const flags = `Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`;\n return this.secureCookies ? `${flags}; Secure` : flags;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Get the Okta domain.\n */\n getDomain(): string {\n return this.domain;\n }\n\n /**\n * Get the configured client ID.\n */\n getClientId(): string {\n return this.clientId;\n }\n\n /**\n * Get the configured redirect URI.\n */\n getRedirectUri(): string {\n return this.redirectUri;\n }\n\n /**\n * Get the issuer URL.\n */\n getIssuer(): string {\n return this.issuer;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/rbac-provider.ts","../src/types.ts","../src/auth-provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Okta RBAC provider for Mastra.\n *\n * Maps Okta groups to Mastra permissions using a configurable role mapping.\n * Can be used with any auth provider (Auth0, Clerk, etc.) or with MastraAuthOkta.\n */\n\nimport type { IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport pkg from '@okta/okta-sdk-nodejs';\nconst { Client } = pkg;\nimport { LRUCache } from 'lru-cache';\n\nimport type { OktaUser, MastraRBACOktaOptions } from './types.js';\n\n/** Default cache TTL in milliseconds (60 seconds) */\nconst DEFAULT_CACHE_TTL_MS = 60 * 1000;\n\n/** Default max cache size (number of users) */\nconst DEFAULT_CACHE_MAX_SIZE = 1000;\n\n/**\n * Okta RBAC provider that maps Okta groups to Mastra permissions.\n *\n * This provider fetches user groups from Okta and translates them into\n * Mastra permissions using a configurable role mapping.\n *\n * @example Basic usage with Okta auth\n * ```typescript\n * import { MastraAuthOkta, MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthOkta(),\n * rbac: new MastraRBACOkta({\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n *\n * @example Cross-provider usage (Auth0 + Okta RBAC)\n * ```typescript\n * import { MastraAuthAuth0 } from '@mastra/auth-auth0';\n * import { MastraRBACOkta } from '@mastra/auth-okta';\n *\n * const mastra = new Mastra({\n * server: {\n * auth: new MastraAuthAuth0(),\n * rbac: new MastraRBACOkta({\n * getUserId: (user) => user.metadata?.oktaUserId || user.email,\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * '_default': [],\n * },\n * }),\n * },\n * });\n * ```\n */\nexport class MastraRBACOkta implements IRBACProvider<OktaUser> {\n private oktaClient: InstanceType<typeof Client>;\n private options: MastraRBACOktaOptions;\n /**\n * Single cache for roles (the expensive Okta API call).\n * Permissions are derived from roles on-the-fly (cheap, synchronous).\n * Storing promises handles concurrent request deduplication.\n */\n private rolesCache: LRUCache<string, Promise<string[]>>;\n\n /**\n * Expose roleMapping for middleware access.\n * This allows the authorization middleware to resolve permissions\n * without needing to call the async methods.\n */\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n /**\n * Create a new Okta RBAC provider.\n *\n * @param options - RBAC configuration options\n */\n constructor(options: MastraRBACOktaOptions) {\n const domain = options.domain ?? process.env.OKTA_DOMAIN;\n const apiToken = options.apiToken ?? process.env.OKTA_API_TOKEN;\n\n if (!domain) {\n throw new Error(\n 'Okta domain is required. ' + 'Provide it in the options or set OKTA_DOMAIN environment variable.',\n );\n }\n\n if (!apiToken) {\n throw new Error(\n 'Okta API token is required for RBAC. ' +\n 'Provide it in the options or set OKTA_API_TOKEN environment variable.',\n );\n }\n\n this.oktaClient = new Client({\n orgUrl: `https://${domain}`,\n token: apiToken,\n });\n\n this.options = options;\n\n // Initialize LRU cache with configurable size and TTL\n this.rolesCache = new LRUCache<string, Promise<string[]>>({\n max: options.cache?.maxSize ?? DEFAULT_CACHE_MAX_SIZE,\n ttl: options.cache?.ttlMs ?? DEFAULT_CACHE_TTL_MS,\n });\n }\n\n /**\n * Get all roles (groups) for a user from Okta.\n *\n * If the user object already has groups attached, uses those.\n * Otherwise, fetches groups from Okta API and caches the result.\n *\n * @param user - User to get roles for\n * @returns Array of group names\n */\n async getRoles(user: OktaUser): Promise<string[]> {\n // If groups are already present on the user object, use them\n if (user.groups && user.groups.length > 0) {\n return user.groups;\n }\n\n // Determine the user ID to use for Okta API lookup\n const userId = this.resolveUserId(user);\n if (!userId) {\n return [];\n }\n\n // Check cache - returns existing promise (resolved or in-flight)\n const cached = this.rolesCache.get(userId);\n if (cached) {\n return cached;\n }\n\n // Create and cache the group fetch promise.\n // On failure, evict from cache so the next request retries,\n // then fall back to empty groups (which applies _default permissions).\n const groupsPromise = this.fetchGroupsFromOkta(userId).catch(err => {\n console.error(`[MastraRBACOkta] Failed to fetch groups for user ${userId}:`, err);\n this.rolesCache.delete(userId);\n return [];\n });\n this.rolesCache.set(userId, groupsPromise);\n\n return groupsPromise;\n }\n\n /**\n * Resolve the Okta user ID from the user object.\n * Uses custom getUserId function if provided, otherwise falls back to oktaId or id.\n */\n private resolveUserId(user: OktaUser): string | undefined {\n if (this.options.getUserId) {\n return this.options.getUserId(user);\n }\n return user.oktaId ?? user.id;\n }\n\n /**\n * Fetch groups from Okta API.\n * Errors propagate to the caller so the cache eviction in getRoles() works.\n */\n private async fetchGroupsFromOkta(userId: string): Promise<string[]> {\n const groups = await this.oktaClient.userApi.listUserGroups({ userId });\n const groupNames: string[] = [];\n\n for await (const group of groups) {\n if (group && group.profile?.name) {\n groupNames.push(group.profile.name);\n }\n }\n\n return groupNames;\n }\n\n /**\n * Check if a user has a specific role (group).\n *\n * @param user - User to check\n * @param role - Group name to check for\n * @returns True if user has the group\n */\n async hasRole(user: OktaUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n /**\n * Get all permissions for a user by mapping their Okta groups.\n *\n * @param user - User to get permissions for\n * @returns Array of permission strings\n */\n async getPermissions(user: OktaUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n /**\n * Check if a user has a specific permission.\n *\n * @param user - User to check\n * @param permission - Permission to check for (supports wildcards)\n * @returns True if user has the permission\n */\n async hasPermission(user: OktaUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n\n // Check if any granted permission matches the required permission\n return permissions.some(granted => matchesPermission(granted, permission));\n }\n\n /**\n * Check if a user has ALL of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has all permissions\n */\n async hasAllPermissions(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.every(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n\n /**\n * Check if a user has ANY of the specified permissions.\n *\n * @param user - User to check\n * @param permissions - Permissions to check for\n * @returns True if user has at least one permission\n */\n async hasAnyPermission(user: OktaUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n\n return permissions.some(required => userPermissions.some(granted => matchesPermission(granted, required)));\n }\n}\n","/**\n * Shared types for Okta integration.\n */\n\nimport type { EEUser, RoleMapping } from '@mastra/core/auth/ee';\nimport type { JWTPayload } from 'jose';\n\n// ============================================================================\n// User Types\n// ============================================================================\n\n/**\n * Extended EEUser with Okta-specific fields.\n */\nexport interface OktaUser extends EEUser {\n /** Okta user ID */\n oktaId: string;\n /** User's Okta groups (if fetched) */\n groups?: string[];\n}\n\n/**\n * Maps Okta JWT claims to OktaUser format.\n *\n * @param payload - JWT payload from Okta token\n * @returns OktaUser object\n */\nexport function mapOktaClaimsToUser(payload: JWTPayload): OktaUser {\n return {\n id: (payload.sub as string) || (payload.uid as string) || '',\n oktaId: (payload.sub as string) || (payload.uid as string) || '',\n email: payload.email as string | undefined,\n name:\n (payload.name as string) ||\n [payload.given_name, payload.family_name].filter(Boolean).join(' ') ||\n (payload.email as string) ||\n undefined,\n avatarUrl: payload.picture as string | undefined,\n groups: payload.groups as string[] | undefined,\n metadata: {\n oktaId: payload.sub,\n emailVerified: payload.email_verified,\n updatedAt: payload.updated_at,\n },\n };\n}\n\n// ============================================================================\n// Auth Provider Options\n// ============================================================================\n\n/**\n * Session configuration options for MastraAuthOkta.\n */\nexport interface OktaSessionOptions {\n /** Cookie name (default: 'okta_session') */\n cookieName?: string;\n /** Cookie max age in seconds (default: 86400 = 24 hours) */\n cookieMaxAge?: number;\n /**\n * Password for encrypting session cookies.\n * Must be at least 32 characters.\n * Defaults to OKTA_COOKIE_PASSWORD env var.\n */\n cookiePassword?: string;\n /**\n * Set the Secure flag on session cookies.\n * Defaults to true when NODE_ENV=production, false otherwise.\n */\n secureCookies?: boolean;\n}\n\n/**\n * Options for MastraAuthOkta.\n */\nexport interface MastraAuthOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n /** Okta OAuth client ID. Defaults to OKTA_CLIENT_ID env var. */\n clientId?: string;\n /** Okta OAuth client secret. Defaults to OKTA_CLIENT_SECRET env var. Required for SSO. */\n clientSecret?: string;\n /**\n * Token issuer URL.\n * Defaults to OKTA_ISSUER env var or `https://{domain}/oauth2/default`.\n */\n issuer?: string;\n /**\n * OAuth redirect URI for SSO callback.\n * Defaults to OKTA_REDIRECT_URI env var.\n */\n redirectUri?: string;\n /**\n * OAuth scopes to request.\n * Default: ['openid', 'profile', 'email', 'groups']\n */\n scopes?: string[];\n /**\n * Okta API token for user lookups via the Users API.\n * Required for getUser() to return user data by ID.\n * Defaults to OKTA_API_TOKEN env var.\n */\n apiToken?: string;\n /** Session configuration */\n session?: OktaSessionOptions;\n /** Custom provider name (default: 'okta') */\n name?: string;\n}\n\n// ============================================================================\n// RBAC Provider Options\n// ============================================================================\n\n/**\n * Cache configuration options for RBAC permission caching.\n */\nexport interface PermissionCacheOptions {\n /** Maximum number of users to cache (default: 1000) */\n maxSize?: number;\n /** Time-to-live in milliseconds (default: 60000) */\n ttlMs?: number;\n}\n\n/**\n * Options for MastraRBACOkta.\n */\nexport interface MastraRBACOktaOptions {\n /** Okta domain (e.g., 'dev-123456.okta.com'). Defaults to OKTA_DOMAIN env var. */\n domain?: string;\n\n /** Okta API token for management SDK. Defaults to OKTA_API_TOKEN env var. */\n apiToken?: string;\n\n /**\n * Map Okta groups to Mastra permissions.\n *\n * @example\n * ```typescript\n * roleMapping: {\n * 'Engineering': ['agents:*', 'workflows:*'],\n * 'Admin': ['*'],\n * 'Viewer': ['agents:read', 'workflows:read'],\n * '_default': [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n\n /**\n * Function to extract Okta user ID from any user object.\n * Use this when using a different auth provider (e.g., Auth0) with Okta RBAC.\n *\n * @example\n * ```typescript\n * getUserId: (user) => user.metadata?.oktaUserId || user.email\n * ```\n */\n getUserId?: (user: unknown) => string | undefined;\n\n /** Permission cache configuration */\n cache?: PermissionCacheOptions;\n}\n","/**\n * MastraAuthOkta - Okta authentication provider for Mastra with SSO support.\n *\n * Supports OAuth 2.0 / OIDC login flow with client_secret and session management.\n */\n\nimport type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { HonoRequest } from 'hono';\nimport { createRemoteJWKSet, jwtVerify } from 'jose';\n\nimport type { OktaUser, MastraAuthOktaOptions } from './types.js';\nimport { mapOktaClaimsToUser } from './types.js';\n\n/** Default cookie name for Okta sessions */\nconst DEFAULT_COOKIE_NAME = 'okta_session';\n\n/** Default cookie max age (24 hours) */\nconst DEFAULT_COOKIE_MAX_AGE = 86400;\n\n/** Default OAuth scopes */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'email', 'groups'];\n\n/** PBKDF2 salt length in bytes */\nconst SALT_LENGTH = 16;\n\n/** AES-GCM IV length in bytes */\nconst IV_LENGTH = 12;\n\n/**\n * Derive an AES-GCM key from password + salt using PBKDF2.\n */\nasync function deriveKey(password: string, salt: Uint8Array, usage: 'encrypt' | 'decrypt') {\n const encoder = new TextEncoder();\n const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ]);\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n [usage],\n );\n}\n\n/**\n * Encrypt session data for cookie storage.\n * Format: base64(salt || iv || ciphertext)\n * Salt is random per-encryption to ensure unique derived keys.\n */\nasync function encryptSession(data: unknown, password: string): Promise<string> {\n const encoder = new TextEncoder();\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const key = await deriveKey(password, salt, 'encrypt');\n const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoder.encode(JSON.stringify(data)));\n const combined = new Uint8Array(salt.length + iv.length + new Uint8Array(encrypted).length);\n combined.set(salt);\n combined.set(iv, salt.length);\n combined.set(new Uint8Array(encrypted), salt.length + iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\n/**\n * Decrypt session data from cookie.\n * Reads the random salt from the ciphertext prefix to derive the same key.\n */\nasync function decryptSession(encrypted: string, password: string): Promise<unknown> {\n const combined = Uint8Array.from(atob(encrypted), c => c.charCodeAt(0));\n const salt = combined.slice(0, SALT_LENGTH);\n const iv = combined.slice(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n const data = combined.slice(SALT_LENGTH + IV_LENGTH);\n const key = await deriveKey(password, salt, 'decrypt');\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, data);\n return JSON.parse(new TextDecoder().decode(decrypted));\n}\n\n/**\n * In-memory store for state validation (keyed by state).\n * Used to validate that callback state matches the login request.\n */\nconst stateStore = new Map<string, { expiresAt: number; redirectUri: string }>();\n\n/**\n * Mastra authentication provider for Okta with SSO support.\n *\n * Implements OAuth 2.0 / OIDC login flow with encrypted session cookies.\n *\n * @example Basic usage with SSO\n * ```typescript\n * import { MastraAuthOkta } from '@mastra/auth-okta';\n *\n * const auth = new MastraAuthOkta({\n * domain: 'dev-123456.okta.com',\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUri: 'http://localhost:4111/api/auth/callback',\n * });\n * ```\n */\nexport class MastraAuthOkta\n extends MastraAuthProvider<OktaUser>\n implements ISSOProvider<OktaUser>, ISessionProvider<Session>, IUserProvider<OktaUser>\n{\n protected domain: string;\n protected clientId: string;\n protected clientSecret: string;\n protected issuer: string;\n protected endpointBase: string;\n protected redirectUri: string;\n protected scopes: string[];\n protected cookieName: string;\n protected cookieMaxAge: number;\n protected cookiePassword: string;\n protected secureCookies: boolean;\n protected apiToken?: string;\n private jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(options?: MastraAuthOktaOptions) {\n super({ name: options?.name ?? 'okta' });\n\n const domain = options?.domain ?? process.env.OKTA_DOMAIN;\n const clientId = options?.clientId ?? process.env.OKTA_CLIENT_ID;\n const clientSecret = options?.clientSecret ?? process.env.OKTA_CLIENT_SECRET;\n const issuer = options?.issuer ?? process.env.OKTA_ISSUER;\n const redirectUri = options?.redirectUri ?? process.env.OKTA_REDIRECT_URI;\n const cookiePassword =\n options?.session?.cookiePassword ?? process.env.OKTA_COOKIE_PASSWORD ?? crypto.randomUUID() + crypto.randomUUID();\n\n if (!domain) {\n throw new Error('Okta domain is required. Provide it in the options or set OKTA_DOMAIN environment variable.');\n }\n\n if (!clientId) {\n throw new Error(\n 'Okta client ID is required. Provide it in the options or set OKTA_CLIENT_ID environment variable.',\n );\n }\n\n if (!clientSecret) {\n throw new Error(\n 'Okta client secret is required for SSO. Provide it in the options or set OKTA_CLIENT_SECRET environment variable.',\n );\n }\n\n if (!redirectUri) {\n throw new Error(\n 'Okta redirect URI is required for SSO. Provide it in the options or set OKTA_REDIRECT_URI environment variable.',\n );\n }\n\n if (cookiePassword.length < 32) {\n throw new Error('Cookie password must be at least 32 characters. Set OKTA_COOKIE_PASSWORD environment variable.');\n }\n\n this.domain = domain;\n this.clientId = clientId;\n this.clientSecret = clientSecret;\n // Normalize trailing slashes so a stray `OKTA_ISSUER=https://domain/` doesn't produce `.../oauth2//v1/...`\n this.issuer = (issuer ?? `https://${domain}/oauth2/default`).replace(/\\/+$/, '');\n // Org authorization servers use issuer `https://{domain}` but serve endpoints under `/oauth2/v1/*`.\n // Custom authorization servers use issuer `https://{domain}/oauth2/<name>` and serve endpoints under `<issuer>/v1/*`.\n // `issuer` is still used verbatim for JWT `iss`-claim validation on both server types.\n this.endpointBase =\n this.issuer.includes('/oauth2/') || this.issuer.endsWith('/oauth2') ? this.issuer : `${this.issuer}/oauth2`;\n this.redirectUri = redirectUri;\n this.scopes = options?.scopes ?? DEFAULT_SCOPES;\n this.cookieName = options?.session?.cookieName ?? DEFAULT_COOKIE_NAME;\n this.cookieMaxAge = options?.session?.cookieMaxAge ?? DEFAULT_COOKIE_MAX_AGE;\n this.cookiePassword = cookiePassword;\n this.secureCookies = options?.session?.secureCookies ?? process.env.NODE_ENV === 'production';\n this.apiToken = options?.apiToken ?? process.env.OKTA_API_TOKEN;\n this.jwks = createRemoteJWKSet(new URL(`${this.endpointBase}/v1/keys`));\n\n // Warn about insecure defaults in production\n if (!options?.session?.cookiePassword && !process.env.OKTA_COOKIE_PASSWORD) {\n console.warn(\n '[MastraAuthOkta] No cookie password set — using auto-generated value. Sessions will not survive restarts and will break in multi-instance deployments. Set OKTA_COOKIE_PASSWORD for production use.',\n );\n }\n\n if (process.env.NODE_ENV === 'production') {\n console.warn(\n '[MastraAuthOkta] Using in-memory OAuth state store. This will not work in serverless or multi-instance deployments. Consider implementing a custom state store for production.',\n );\n }\n\n this.registerOptions(options as MastraAuthProviderOptions<OktaUser>);\n }\n\n // ============================================================================\n // MastraAuthProvider Implementation\n // ============================================================================\n\n /**\n * Authenticate a token from the request.\n * First tries to read from session cookie, then falls back to Authorization header.\n */\n async authenticateToken(token: string, request: HonoRequest | Request): Promise<OktaUser | null> {\n // Try session cookie first\n const sessionUser = await this.getUserFromSession(request);\n if (sessionUser) {\n return sessionUser;\n }\n\n // Fall back to JWT verification from Authorization header\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n try {\n const { payload } = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n\n return mapOktaClaimsToUser(payload);\n } catch (err) {\n console.error('Okta token verification failed:', err);\n return null;\n }\n }\n\n /**\n * Authorize a user.\n */\n authorizeUser(user: OktaUser, _request: HonoRequest): boolean {\n if (!user || !user.oktaId) return false;\n return true;\n }\n\n // ============================================================================\n // IUserProvider Implementation\n // ============================================================================\n\n /**\n * Get the current user from the request session.\n */\n async getCurrentUser(request: Request): Promise<OktaUser | null> {\n return this.getUserFromSession(request);\n }\n\n /**\n * Get a user by ID via the Okta Users API.\n * Requires an API token (set OKTA_API_TOKEN or pass apiToken in options).\n * Returns null if no API token is configured or user is not found.\n */\n async getUser(userId: string): Promise<OktaUser | null> {\n if (!this.apiToken) {\n return null;\n }\n\n try {\n const response = await fetch(`https://${this.domain}/api/v1/users/${userId}`, {\n headers: {\n Authorization: `SSWS ${this.apiToken}`,\n Accept: 'application/json',\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n const oktaProfile = (await response.json()) as {\n id: string;\n profile: {\n login: string;\n email: string;\n firstName?: string;\n lastName?: string;\n };\n };\n\n return {\n id: oktaProfile.id,\n oktaId: oktaProfile.id,\n email: oktaProfile.profile.email,\n name: [oktaProfile.profile.firstName, oktaProfile.profile.lastName].filter(Boolean).join(' ') || undefined,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get user from session cookie.\n */\n private async getUserFromSession(request: HonoRequest | Request): Promise<OktaUser | null> {\n try {\n // Handle both HonoRequest and standard Request\n const cookieHeader = 'header' in request ? request.header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n user: OktaUser;\n idToken?: string;\n expiresAt: number;\n };\n\n // Check if session is expired\n if (session.expiresAt && session.expiresAt < Date.now()) {\n return null;\n }\n\n return session.user;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract the raw ID token from the encrypted session cookie.\n * Used to provide id_token_hint for Okta logout.\n */\n private async getIdTokenFromSession(request: Request): Promise<string | null> {\n try {\n const cookieHeader =\n 'header' in request ? (request as unknown as HonoRequest).header('cookie') : request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').map((c: string) => c.trim());\n const sessionCookie = cookies.find((c: string) => c.startsWith(`${this.cookieName}=`));\n if (!sessionCookie) return null;\n\n const sessionValue = sessionCookie.split('=')[1];\n if (!sessionValue) return null;\n\n const session = (await decryptSession(decodeURIComponent(sessionValue), this.cookiePassword)) as {\n idToken?: string;\n };\n return session.idToken ?? null;\n } catch {\n return null;\n }\n }\n\n // ============================================================================\n // ISSOProvider Implementation\n // ============================================================================\n\n /**\n * Get the URL to redirect users to for Okta login.\n * Uses client_secret authentication (no PKCE) since this is a confidential client.\n */\n getLoginUrl(redirectUri: string, state: string): string {\n // State format from server: \"uuid|encodedRedirect\"\n // Extract just the UUID for storage (callback receives only UUID)\n const stateId = state.includes('|') ? state.split('|')[0]! : state;\n\n // Store state ID with redirect_uri for validation (expires in 10 minutes)\n const actualRedirectUri = redirectUri ?? this.redirectUri;\n stateStore.set(stateId, {\n expiresAt: Date.now() + 10 * 60 * 1000,\n redirectUri: actualRedirectUri,\n });\n\n // Clean up expired states\n for (const [key, value] of stateStore.entries()) {\n if (value.expiresAt < Date.now()) {\n stateStore.delete(key);\n }\n }\n\n const params = new URLSearchParams({\n client_id: this.clientId,\n response_type: 'code',\n scope: this.scopes.join(' '),\n redirect_uri: actualRedirectUri,\n state,\n });\n\n return `${this.endpointBase}/v1/authorize?${params.toString()}`;\n }\n\n /**\n * Handle the OAuth callback from Okta.\n * Note: The server passes only the stateId (UUID part), not the full state.\n */\n async handleCallback(code: string, stateId: string): Promise<SSOCallbackResult<OktaUser>> {\n // Validate state parameter (server passes only the UUID part)\n const stored = stateStore.get(stateId);\n if (!stored) {\n throw new Error('Invalid or expired state parameter');\n }\n stateStore.delete(stateId);\n\n if (stored.expiresAt < Date.now()) {\n throw new Error('State parameter has expired');\n }\n\n // Exchange code for tokens using client_secret (confidential client)\n const tokenResponse = await fetch(`${this.endpointBase}/v1/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Basic ${btoa(`${this.clientId}:${this.clientSecret}`)}`,\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: stored.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as {\n access_token: string;\n id_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n // Verify and decode ID token\n const { payload: idTokenPayload } = await jwtVerify(tokens.id_token, this.jwks, {\n issuer: this.issuer,\n audience: this.clientId,\n });\n const user = mapOktaClaimsToUser(idTokenPayload);\n\n // Create encrypted session cookie.\n // Only store user claims, id_token (for logout hint), and expiry.\n // Access/refresh tokens are NOT stored to keep cookie under 4KB browser limit.\n const sessionData = {\n user,\n idToken: tokens.id_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n\n const encryptedSession = await encryptSession(sessionData, this.cookiePassword);\n const cookieValue = `${this.cookieName}=${encodeURIComponent(encryptedSession)}; ${this.cookieFlags(this.cookieMaxAge)}`;\n\n return {\n user,\n tokens: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000),\n },\n cookies: [cookieValue],\n };\n }\n\n /**\n * Get the URL to redirect users to for logout.\n * Includes id_token_hint from session when available (required by Okta).\n */\n async getLogoutUrl(redirectUri: string, request?: Request): Promise<string | null> {\n const params = new URLSearchParams({\n post_logout_redirect_uri: redirectUri,\n client_id: this.clientId,\n });\n\n // Try to extract id_token from session for id_token_hint (Okta requires this)\n if (request) {\n const idToken = await this.getIdTokenFromSession(request);\n if (idToken) {\n params.set('id_token_hint', idToken);\n }\n }\n\n return `${this.endpointBase}/v1/logout?${params.toString()}`;\n }\n\n /**\n * Get cookies to set during login.\n */\n getLoginCookies(_state: string): string[] {\n return [];\n }\n\n /**\n * Get the configuration for rendering the login button.\n */\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'okta',\n text: 'Sign in with Okta',\n };\n }\n\n // ============================================================================\n // ISessionProvider Implementation\n // ============================================================================\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: crypto.randomUUID(),\n userId,\n createdAt: now,\n expiresAt: new Date(now.getTime() + this.cookieMaxAge * 1000),\n metadata,\n };\n }\n\n async validateSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n async destroySession(_sessionId: string): Promise<void> {\n // Session is cleared via cookie\n }\n\n async refreshSession(_sessionId: string): Promise<Session | null> {\n return null;\n }\n\n getSessionIdFromRequest(_request: Request): string | null {\n return null;\n }\n\n getSessionHeaders(_session: Session): Record<string, string> {\n return {};\n }\n\n getClearSessionHeaders(): Record<string, string> {\n return {\n 'Set-Cookie': `${this.cookieName}=; ${this.cookieFlags(0)}`,\n };\n }\n\n /**\n * Build consistent cookie attribute string for set/clear operations.\n */\n private cookieFlags(maxAge: number): string {\n const flags = `Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`;\n return this.secureCookies ? `${flags}; Secure` : flags;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Get the Okta domain.\n */\n getDomain(): string {\n return this.domain;\n }\n\n /**\n * Get the configured client ID.\n */\n getClientId(): string {\n return this.clientId;\n }\n\n /**\n * Get the configured redirect URI.\n */\n getRedirectUri(): string {\n return this.redirectUri;\n }\n\n /**\n * Get the issuer URL.\n */\n getIssuer(): string {\n return this.issuer;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/auth-okta",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-alpha.0",
|
|
4
4
|
"description": "Mastra Okta Auth and RBAC integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "22.19.15",
|
|
36
|
-
"@vitest/coverage-v8": "4.
|
|
37
|
-
"@vitest/ui": "4.
|
|
38
|
-
"eslint": "^
|
|
36
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
37
|
+
"@vitest/ui": "4.1.5",
|
|
38
|
+
"eslint": "^10.2.1",
|
|
39
39
|
"hono": "^4.12.8",
|
|
40
40
|
"tsup": "^8.5.1",
|
|
41
|
-
"typescript": "^
|
|
42
|
-
"vitest": "4.
|
|
43
|
-
"@internal/
|
|
44
|
-
"@mastra/core": "1.
|
|
45
|
-
"@internal/
|
|
41
|
+
"typescript": "^6.0.3",
|
|
42
|
+
"vitest": "4.1.5",
|
|
43
|
+
"@internal/types-builder": "0.0.71",
|
|
44
|
+
"@mastra/core": "1.36.0-alpha.10",
|
|
45
|
+
"@internal/lint": "0.0.96"
|
|
46
46
|
},
|
|
47
47
|
"homepage": "https://mastra.ai",
|
|
48
48
|
"repository": {
|