Configuring Auth0 as an identity provider (IDP) for Webiny projects. Use this skill when the developer asks about Auth0 authentication, Auth0 SSO, replacing Cognito with Auth0, setting up external identity providers, configuring OIDC authentication, mapping JWT claims to Webiny identities, or customizing the Auth0 login flow. Also relevant when asking about AUTH0_ISSUER, AUTH0_CLIENT_ID environment variables, Auth0IdpConfig, or the MyAuth0Extension pattern.
Webiny supports Auth0 as an external identity provider (IDP) to replace the default Cognito authentication. First, install the @webiny/auth0 package (using the same version as the webiny dependency in package.json). Then create two files: an API config class that maps Auth0 JWT claims to Webiny identity data (Auth0IdpConfig), and a React extension component (<Auth0 />) that wires issuer URL, client ID, and the API config path. Register the extension in webiny.config.tsx, set two environment variables (AUTH0_ISSUER, AUTH0_CLIENT_ID), and deploy.
Auth0 integration has two parts:
Auth0IdpConfig.Interface that maps JWT token claims to Webiny's identity structure. Registered via Auth0IdpConfig.createImplementation() (the universal DI pattern).<Auth0 /> from @webiny/auth0, passing the issuer URL, client ID, and path to the API config file. The component handles environment variable injection, API extension registration, and Admin login screen setup automatically.<Auth0 /><Auth0 /> Works InternallyThe <Auth0 /> component (from @webiny/auth0) is a defineExtension that:
AUTH0_ISSUER, AUTH0_CLIENT_IDREACT_APP_IDP_TYPE=auth0, REACT_APP_AUTH0_ISSUER, REACT_APP_AUTH0_CLIENT_IDAuth0IdpFeature API extension (OIDC token verification)Auth0IdpConfig.Interface| Method | Signature | Required | Description |
|---|---|---|---|
getIdentity | (token: JwtPayload) => Auth0Identity | Promise<Auth0Identity> | Yes | Maps JWT claims to Webiny identity data |
verifyTokenClaims | (token: JwtPayload) => void | Promise<void> | No | Custom claim verification (throw to reject the token) |
Auth0Identity (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) |
<Auth0 /> Component Props| Prop | Type | Description |
|---|---|---|
issuer | string | Auth0 issuer URL (e.g., https://your-tenant.auth0.com) |
clientId | string | Auth0 application client ID |
apiConfig | string | Absolute path to the API config file |
| Variable | Used By | Description |
|---|---|---|
AUTH0_ISSUER | API + Admin | Auth0 issuer URL |
AUTH0_CLIENT_ID | API + Admin | Auth0 application client ID |
Step 0: Install the @webiny/auth0 dependency
@webiny/auth0 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/auth0 with the same version
# For example, if "webiny": "^0.0.0-unstable.xxx":
yarn add @webiny/auth0@^0.0.0-unstable.xxx
Important: After adding the dependency, tell the user to run
yarnto install it. Do NOT runyarnautomatically — let the user do it.
Step 1: Create the API config
Create extensions/auth0/MyAuth0Config.ts:
import { Auth0IdpConfig } from "@webiny/auth0";
class MyIdpConfig implements Auth0IdpConfig.Interface {
getIdentity(token: Auth0IdpConfig.JwtPayload) {
return {
id: String(token["sub"]),
displayName: token["name"],
roles: ["full-access"],
profile: {
firstName: token["given_name"],
lastName: token["family_name"],
email: token["email"]
},
context: {
canAccessTenant: true,
defaultTenant: "root"
}
};
}
}
const MyAuth0Config = Auth0IdpConfig.createImplementation({
implementation: MyIdpConfig,
dependencies: []
});
export default MyAuth0Config;
Step 2: Create the extension component
Create extensions/auth0/MyAuth0Extension.tsx:
import React from "react";
import { Auth0 } from "@webiny/auth0";
export const MyAuth0Extension = () => {
return (
<Auth0
issuer={String(process.env.AUTH0_ISSUER)}
clientId={String(process.env.AUTH0_CLIENT_ID)}
apiConfig={import.meta.dirname + "/MyAuth0Config.ts"}
/>
);
};
Step 3: Register in webiny.config.tsx
import React from "react";
import { MyAuth0Extension } from "./extensions/auth0/MyAuth0Extension.js";
export const Extensions = () => {
return (
<>
{/* Replace <Cognito /> with Auth0 */}
<MyAuth0Extension />
{/* ... other extensions ... */}
</>
);
};
Step 4: Set environment variables
Add to your .env file (or CI/CD environment):
AUTH0_ISSUER=https://your-tenant.auth0.com/
AUTH0_CLIENT_ID=your-auth0-client-id
Step 5: Deploy
yarn webiny deploy
If your Auth0 setup uses custom claims (e.g., via Auth0 Actions or Rules) that need validation:
import { Auth0IdpConfig } from "@webiny/auth0";
class MyIdpConfig implements Auth0IdpConfig.Interface {
getIdentity(token: Auth0IdpConfig.JwtPayload) {
return {
id: String(token["sub"]),
displayName: token["name"],
roles: [token["https://webiny.com/role"]],
profile: {
firstName: token["given_name"],
lastName: token["family_name"],
email: token["email"]
},
context: {
canAccessTenant: true,
defaultTenant: "root"
}
};
}
verifyTokenClaims(token: Auth0IdpConfig.JwtPayload) {
// Reject tokens without the required custom claim
if (!token["https://webiny.com/role"]) {
throw new Error("Token is missing the 'https://webiny.com/role' claim.");
}
// Reject tokens from unauthorized organizations
if (token["org_id"] && token["org_id"] !== "org_expected") {
throw new Error("User does not belong to the authorized organization.");
}
}
}
const MyAuth0Config = Auth0IdpConfig.createImplementation({
implementation: MyIdpConfig,
dependencies: []
});
export default MyAuth0Config;
If your config needs access to other Webiny services (e.g., to look up tenant-specific roles):
import { Auth0IdpConfig } from "@webiny/auth0";
import { TenantContext } from "webiny/api/tenancy";
class MyIdpConfig implements Auth0IdpConfig.Interface {
constructor(private tenantContext: TenantContext.Interface) {}
getIdentity(token: Auth0IdpConfig.JwtPayload) {
const tenant = this.tenantContext.getTenant();
return {
id: String(token["sub"]),
displayName: token["name"],
roles: [token["https://webiny.com/role"]],
profile: {
firstName: token["given_name"],
lastName: token["family_name"],
email: token["email"]
},
context: {
canAccessTenant: true,
defaultTenant: tenant?.id ?? "root"
}
};
}
}
const MyAuth0Config = Auth0IdpConfig.createImplementation({
implementation: MyIdpConfig,
dependencies: [TenantContext]
});
export default MyAuth0Config;
// API config
import { Auth0IdpConfig } from "@webiny/auth0";
// Extension component
import { Auth0 } from "@webiny/auth0";
| Interface | Package | Purpose |
|---|---|---|
Auth0IdpConfig.Interface | @webiny/auth0 | API-side JWT-to-identity mapping |
Auth0IdpConfig.JwtPayload | @webiny/auth0 | JWT token payload type |
Auth0IdpConfig.IdentityData | @webiny/auth0 | Identity return type |
extensions/auth0/
├── MyAuth0Config.ts # API config (JWT claim mapping)
└── MyAuth0Extension.tsx # Extension component (Auth0 setup)
In webiny.config.tsx, replace <Cognito /> with <MyAuth0Extension />.
yarn webiny deploy # Deploy all (Core + API + Admin)
Both API and Admin need to be redeployed since Auth0 affects both the backend (token verification, identity mapping) and the frontend (login screen).
Auth0IdpConfig.createImplementation()webiny.config.tsx and extensions are organized