Webiny-js webiny-configure-okta
install
source · Clone the upstream repo
git clone https://github.com/webiny/webiny-js
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/webiny/webiny-js "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/user-skills/configure-okta" ~/.claude/skills/webiny-webiny-js-webiny-configure-okta && rm -rf "$T"
manifest:
skills/user-skills/configure-okta/SKILL.mdsource content
Configure Okta Authentication
TL;DR
Webiny supports Okta as an external identity provider (IDP) to replace the default Cognito authentication. First, install the
@webiny/okta package (using the same version as the webiny dependency in package.json). Then create two files: an API config class that maps Okta JWT claims to Webiny identity data (OktaIdpConfig), and a React extension component (<Okta />) that wires issuer URL, client ID, and the API config path. Register the extension in webiny.config.tsx, set two environment variables (OKTA_ISSUER, OKTA_CLIENT_ID), and deploy.
Pattern / Core Concept
Okta integration has two parts:
- API Config — A class implementing
that maps JWT token claims to Webiny's identity structure. Registered viaOktaIdpConfig.Interface
(the universal DI pattern).OktaIdpConfig.createImplementation() - Extension Component — A React component that renders
from<Okta />
, passing the issuer URL, client ID, and path to the API config file. The@webiny/okta
component handles environment variable injection, API extension registration, and Admin login screen setup automatically.<Okta />
How <Okta />
Works Internally
<Okta />The
<Okta /> component (from @webiny/okta) is a defineExtension that:
- Sets Lambda env vars:
,OKTA_ISSUEROKTA_CLIENT_ID - Sets Admin app env vars:
,REACT_APP_IDP_TYPE=okta
,REACT_APP_OKTA_ISSUERREACT_APP_OKTA_CLIENT_ID - Registers the internal
API extension (OIDC token verification)OktaIdpFeature - Registers your custom API config extension (identity mapping)
- Registers the Admin Okta login screen extension
Reference Tables
OktaIdpConfig.Interface
OktaIdpConfig.Interface| Method | Signature | Required | Description |
|---|---|---|---|
| | Yes | Maps JWT claims to Webiny identity data |
| | No | Custom claim verification (throw to reject the token) |
OktaIdentity
(Return Type of getIdentity
)
OktaIdentitygetIdentity| Field | Type | Description |
|---|---|---|
| | Unique user ID (typically ) |
| | User's display name |
| | Webiny security roles to assign |
| | Webiny teams (optional, filter out falsy values) |
| | User profile fields |
| | Runtime data (not stored in DB) |
<Okta />
Component Props
<Okta />| Prop | Type | Description |
|---|---|---|
| | Okta issuer URL (e.g., ) |
| | Okta application client ID |
| | Absolute path to the API config file |
Environment Variables
| Variable | Used By | Description |
|---|---|---|
| API + Admin | Okta issuer URL |
| API + Admin | Okta application client ID |
Full Examples
Example 1: Basic Okta Configuration
Step 0: Install the
dependency@webiny/okta
@webiny/okta is an optional dependency. Add it to package.json using the same version as the webiny dependency, then install:
# Check the webiny version in package.json, then add @webiny/okta with the same version # For example, if "webiny": "^0.0.0-unstable.xxx": yarn add @webiny/okta@^0.0.0-unstable.xxx
Important: After adding the dependency, tell the user to run
to install it. Do NOT runyarnautomatically — let the user do it.yarn
Step 1: Create the API config
Create
extensions/okta/MyOktaConfig.ts:
import { OktaIdpConfig } from "@webiny/okta"; class MyIdpConfig implements OktaIdpConfig.Interface { getIdentity(token: OktaIdpConfig.JwtPayload) { return { id: String(token["sub"]), displayName: token["name"], roles: [token["webiny_group"]], teams: [token["team"]].filter(Boolean), profile: { firstName: token["first_name"], lastName: token["last_name"], email: token["email"] }, context: { canAccessTenant: true, defaultTenant: "root" } }; } } const MyOktaConfig = OktaIdpConfig.createImplementation({ implementation: MyIdpConfig, dependencies: [] }); export default MyOktaConfig;
Step 2: Create the extension component
Create
extensions/okta/MyOktaExtension.tsx:
import React from "react"; import { Okta } from "@webiny/okta"; export const MyOktaExtension = () => { return ( <Okta issuer={String(process.env.OKTA_ISSUER)} clientId={String(process.env.OKTA_CLIENT_ID)} apiConfig={import.meta.dirname + "/MyOktaConfig.ts"} /> ); };
Step 3: Register in webiny.config.tsx
import React from "react"; import { MyOktaExtension } from "./extensions/okta/MyOktaExtension.js"; export const Extensions = () => { return ( <> {/* Replace <Cognito /> with Okta */} <MyOktaExtension /> {/* ... other extensions ... */} </> ); };
Step 4: Set environment variables
Add to your
.env file (or CI/CD environment):
OKTA_ISSUER=https://dev-xxxxx.okta.com/oauth2/default OKTA_CLIENT_ID=your-okta-client-id
Step 5: Deploy
yarn webiny deploy
Example 2: Custom Claim Verification
If your Okta setup uses custom claims that need validation:
import { OktaIdpConfig } from "@webiny/okta"; class MyIdpConfig implements OktaIdpConfig.Interface { getIdentity(token: OktaIdpConfig.JwtPayload) { return { id: String(token["sub"]), displayName: token["name"], roles: [token["webiny_role"]], profile: { firstName: token["given_name"], lastName: token["family_name"], email: token["email"] }, context: { canAccessTenant: true, defaultTenant: "root" } }; } verifyTokenClaims(token: OktaIdpConfig.JwtPayload) { // Reject tokens without the required custom claim if (!token["webiny_role"]) { throw new Error("Token is missing the 'webiny_role' claim."); } // Reject tokens from unauthorized organizations const allowedOrgs = ["org_abc123", "org_def456"]; if (!allowedOrgs.includes(token["org_id"] as string)) { throw new Error("User does not belong to an authorized organization."); } } } const MyOktaConfig = OktaIdpConfig.createImplementation({ implementation: MyIdpConfig, dependencies: [] }); export default MyOktaConfig;
Example 3: Using DI Dependencies in Config
If your config needs access to other Webiny services (e.g., to look up tenant-specific roles):
import { OktaIdpConfig } from "@webiny/okta"; import { TenantContext } from "webiny/api/tenancy"; class MyIdpConfig implements OktaIdpConfig.Interface { constructor(private tenantContext: TenantContext.Interface) {} getIdentity(token: OktaIdpConfig.JwtPayload) { const tenant = this.tenantContext.getTenant(); return { id: String(token["sub"]), displayName: token["name"], roles: [token["webiny_group"]], profile: { firstName: token["first_name"], lastName: token["last_name"], email: token["email"] }, context: { canAccessTenant: true, defaultTenant: tenant?.id ?? "root" } }; } } const MyOktaConfig = OktaIdpConfig.createImplementation({ implementation: MyIdpConfig, dependencies: [TenantContext] }); export default MyOktaConfig;
Quick Reference
Imports
// API config import { OktaIdpConfig } from "@webiny/okta"; // Extension component import { Okta } from "@webiny/okta";
Key Interfaces
| Interface | Package | Purpose |
|---|---|---|
| | API-side JWT-to-identity mapping |
| | JWT token payload type |
| | Identity return type |
File Structure
extensions/okta/ ├── MyOktaConfig.ts # API config (JWT claim mapping) └── MyOktaExtension.tsx # Extension component (Okta setup)
Registration
In
webiny.config.tsx, replace <Cognito /> with <MyOktaExtension />.
Deploy
yarn webiny deploy # Deploy all (Core + API + Admin)
Both API and Admin need to be redeployed since Okta affects both the backend (token verification, identity mapping) and the frontend (login screen).
Related Skills
- webiny-dependency-injection — The universal DI pattern used by
OktaIdpConfig.createImplementation() - webiny-project-structure — How
and extensions are organizedwebiny.config.tsx - webiny-local-development — Deploying and testing your Okta configuration