webiny-configure-okta
Configuring Okta as an identity provider (IDP) for Webiny projects. Use this skill when the developer asks about Okta authentication, Okta SSO, replacing Cognito with Okta, setting up external identity providers, configuring OIDC authentication, mapping JWT claims to Webiny identities, or customizing the Okta login flow. Also relevant when asking about OKTA_ISSUER, OKTA_CLIENT_ID environment variables, OktaIdpConfig, or the MyOktaExtension pattern.
Best use case
webiny-configure-okta is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Configuring Okta as an identity provider (IDP) for Webiny projects. Use this skill when the developer asks about Okta authentication, Okta SSO, replacing Cognito with Okta, setting up external identity providers, configuring OIDC authentication, mapping JWT claims to Webiny identities, or customizing the Okta login flow. Also relevant when asking about OKTA_ISSUER, OKTA_CLIENT_ID environment variables, OktaIdpConfig, or the MyOktaExtension pattern.
Teams using webiny-configure-okta should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/configure-okta/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How webiny-configure-okta Compares
| Feature / Agent | webiny-configure-okta | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Configuring Okta as an identity provider (IDP) for Webiny projects. Use this skill when the developer asks about Okta authentication, Okta SSO, replacing Cognito with Okta, setting up external identity providers, configuring OIDC authentication, mapping JWT claims to Webiny identities, or customizing the Okta login flow. Also relevant when asking about OKTA_ISSUER, OKTA_CLIENT_ID environment variables, OktaIdpConfig, or the MyOktaExtension pattern.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Cursor vs Codex for AI Workflows
Compare Cursor and Codex for AI coding workflows, repository assistance, debugging, refactoring, and reusable developer skills.
AI Agents for Freelancers
Browse AI agent skills for freelancers handling client research, proposals, outreach, delivery systems, documentation, and repeatable admin work.
SKILL.md Source
# 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:
1. **API Config** — A class implementing `OktaIdpConfig.Interface` that maps JWT token claims to Webiny's identity structure. Registered via `OktaIdpConfig.createImplementation()` (the universal DI pattern).
2. **Extension Component** — A React component that renders `<Okta />` from `@webiny/okta`, passing the issuer URL, client ID, and path to the API config file. The `<Okta />` component handles environment variable injection, API extension registration, and Admin login screen setup automatically.
### How `<Okta />` Works Internally
The `<Okta />` component (from `@webiny/okta`) is a `defineExtension` that:
- Sets Lambda env vars: `OKTA_ISSUER`, `OKTA_CLIENT_ID`
- Sets Admin app env vars: `REACT_APP_IDP_TYPE=okta`, `REACT_APP_OKTA_ISSUER`, `REACT_APP_OKTA_CLIENT_ID`
- Registers the internal `OktaIdpFeature` API extension (OIDC token verification)
- Registers your custom API config extension (identity mapping)
- Registers the Admin Okta login screen extension
## Reference Tables
### `OktaIdpConfig.Interface`
| Method | Signature | Required | Description |
| ------------------- | -------------------------------------------------------------- | -------- | ----------------------------------------------------- |
| `getIdentity` | `(token: JwtPayload) => OktaIdentity \| Promise<OktaIdentity>` | Yes | Maps JWT claims to Webiny identity data |
| `verifyTokenClaims` | `(token: JwtPayload) => void \| Promise<void>` | No | Custom claim verification (throw to reject the token) |
### `OktaIdentity` (Return Type of `getIdentity`)
| Field | Type | Description |
| ------------- | -------------------------------- | ------------------------------------------------ |
| `id` | `string` | Unique user ID (typically `token["sub"]`) |
| `displayName` | `string` | User's display name |
| `roles` | `string[]` | Webiny security roles to assign |
| `teams` | `string[]` | Webiny teams (optional, filter out falsy values) |
| `profile` | `{ firstName, lastName, email }` | User profile fields |
| `context` | `object` | Runtime data (not stored in DB) |
### `<Okta />` Component Props
| Prop | Type | Description |
| ----------- | -------- | -------------------------------------------------- |
| `issuer` | `string` | Okta issuer URL (e.g., `https://dev-xxx.okta.com`) |
| `clientId` | `string` | Okta application client ID |
| `apiConfig` | `string` | Absolute path to the API config file |
### Environment Variables
| Variable | Used By | Description |
| ---------------- | ----------- | -------------------------- |
| `OKTA_ISSUER` | API + Admin | Okta issuer URL |
| `OKTA_CLIENT_ID` | API + Admin | Okta application client ID |
## Full Examples
### Example 1: Basic Okta Configuration
**Step 0: Install the `@webiny/okta` dependency**
`@webiny/okta` is an optional dependency. Add it to `package.json` using the same version as the `webiny` dependency, then install:
```bash
# 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 `yarn` to install it. Do NOT run `yarn` automatically — let the user do it.
**Step 1: Create the API config**
Create `extensions/okta/MyOktaConfig.ts`:
```typescript
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`:
```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`**
```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**
```bash
yarn webiny deploy
```
### Example 2: Custom Claim Verification
If your Okta setup uses custom claims that need validation:
```typescript
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):
```typescript
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
```typescript
// API config
import { OktaIdpConfig } from "@webiny/okta";
// Extension component
import { Okta } from "@webiny/okta";
```
### Key Interfaces
| Interface | Package | Purpose |
| ---------------------------- | -------------- | -------------------------------- |
| `OktaIdpConfig.Interface` | `@webiny/okta` | API-side JWT-to-identity mapping |
| `OktaIdpConfig.JwtPayload` | `@webiny/okta` | JWT token payload type |
| `OktaIdpConfig.IdentityData` | `@webiny/okta` | 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
```bash
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 `webiny.config.tsx` and extensions are organized
- **webiny-local-development** — Deploying and testing your Okta configurationRelated Skills
webiny-v5-to-v6-migration
Migration patterns for converting v5 Webiny code to v6 architecture. Use this skill when migrating existing v5 plugins to v6 features, converting context plugins to DI services, adapting v5 event subscriptions to v6 EventHandlers, or understanding how v5 patterns translate to v6. Targeted at AI agents performing migrations.
webiny-api-permissions
Schema-based permission system for API features. Use this skill when implementing authorization in use cases, defining permission schemas with createPermissionSchema, creating injectable permissions via createPermissionsAbstraction/createPermissionsFeature, checking read/write/delete/publish permissions, handling own-record scoping, or testing permission scenarios. Covers the full pattern from schema definition to use case integration to test matrices.
webiny-admin-permissions
Admin-side permission UI registration and DI-backed permission checking. Use this skill when adding permission controls to the admin UI — schema-based auto-generated forms, injectable permissions via createPermissionsAbstraction/ createPermissionsFeature, typed hooks (createUsePermissions), the HasPermission component (createHasPermission), and the Security.Permissions component props. Covers both simple apps and complex multi-entity permission schemas.
webiny-sdk
Using @webiny/sdk to read and write CMS data from external applications. Use this skill when the developer is building a Next.js, Vue, Node.js, or any external app that needs to fetch or write content to Webiny, set up the SDK, use the Result pattern, list/get/create/update/publish entries, filter and sort queries, use TypeScript generics for type safety, work with the File Manager, or create API keys programmatically. Covers read vs preview mode, the `values` wrapper requirement, correct method names, and the `fields` required parameter.
webiny-project-structure
Webiny project layout, webiny.config.tsx anatomy, and extension registration. Use this skill when the developer asks about folder structure, where custom code goes, how to register extensions, what webiny.config.tsx does, or how the project is organized. Also use when they need to understand the relationship between extensions/, webiny.config.tsx, and the different extension types (Api, Admin, Infra, CLI).
webiny-local-development
Deploying, developing locally, managing environments, and debugging Webiny projects. Use this skill when the developer asks about deployment commands (deploy, destroy, info), local development with watch mode (API or Admin), the Local Lambda Development system, environment management (long-lived vs short-lived, production vs dev modes), build parameters, state files, debugging API/Admin/Infrastructure errors, or the redeploy-after-watch requirement.
webiny-infrastructure-extensions
Modifying AWS infrastructure using Pulumi handlers and declarative Infra components. Use this skill when the developer wants to customize AWS infrastructure, add Pulumi handlers, configure OpenSearch, VPC, resource tags, regions, custom domains, blue-green deployments, environment-conditional config, or manage production vs development infrastructure modes. Covers CorePulumi.Interface, all <Infra.*> declarative components, and <Infra.Env.Is>.
webiny-infra-catalog
Infrastructure — 33 abstractions. Infrastructure extensions.
webiny-extensions-catalog
extensions — 5 abstractions.
webiny-cli-command-catalog
cli/command — 1 abstractions.
webiny-cli-catalog
cli — 2 abstractions.
webiny-api-tenant-manager-catalog
API — Tenant Manager — 2 abstractions. Tenant management event handlers and use cases.