Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Data API builder supports third-party identity providers through the Custom authentication provider using JSON Web Token (JWT) validation. Use this approach when your organization uses Okta, Auth0, or another OAuth 2.0/OpenID Connect-compliant identity provider.
Authentication flow
With a custom identity provider, your client app handles user authentication and then sends the access token to Data API builder:
| Phase | What happens |
|---|---|
| User auth | User signs in through the identity provider (Okta, Auth0, etc.) |
| Token acquisition | Client app receives an access token from the IdP |
| API call | Client sends the token to DAB in the Authorization header |
| Validation | DAB validates the JWT (issuer, audience, signature) |
| Authorization | DAB extracts roles and evaluates permissions |
Prerequisites
- An account with your identity provider (Okta, Auth0, etc.)
- An application registered in your identity provider
- Data API builder CLI installed (installation guide)
- An existing
dab-config.jsonwith at least one entity
Quick reference
| Setting | Value |
|---|---|
| Provider | Custom |
| Required for validation | iss, aud, exp, valid signature |
| Required for authorization | roles claim that contains the selected role |
| Token header | Authorization: Bearer <token> |
| Role claim type | roles (fixed, not configurable) |
| Role selection header | X-MS-API-ROLE |
Step 1: Configure your identity provider
The exact steps depend on your provider. Here are the key values you need:
Values to collect
| Value | Where to find it | Used for |
|---|---|---|
| Issuer URL | Provider's documentation or OAuth metadata endpoint | DAB jwt.issuer (used as JWT Authority) |
| Audience | Your application's client ID or a custom API identifier | DAB jwt.audience |
Note
DAB uses the configured jwt.issuer as the JWT Authority. Signing keys are discovered automatically via standard OpenID Connect metadata (typically <issuer>/.well-known/openid-configuration).
Okta example
- Sign in to the Okta Admin Console.
- Navigate to Applications > Applications.
- Create or select an application.
- Note the Client ID (use as audience).
- Your issuer is typically
https://<your-domain>.okta.com.
Auth0 example
- Sign in to the Auth0 Dashboard.
- Navigate to Applications > APIs.
- Create or select an API.
- Note the Identifier (use as audience).
- Your issuer is
https://<your-tenant>.auth0.com/.
Important
Data API builder uses a fixed claim type of roles for role-based authorization. This value can't be configured. If your identity provider emits roles in a different claim (such as groups or permissions), configure it to also emit a roles claim. Auth0 users should review the known namespacing conflict before proceeding.
Step 2: Configure Data API builder
Set the authentication provider to Custom and configure the JWT settings:
CLI
# Set the authentication provider
dab configure \
--runtime.host.authentication.provider Custom
# Set the expected audience
dab configure \
--runtime.host.authentication.jwt.audience "<your-api-identifier>"
# Set the expected issuer
dab configure \
--runtime.host.authentication.jwt.issuer "https://<your-issuer>/"
Resulting configuration
{
"runtime": {
"host": {
"authentication": {
"provider": "Custom",
"jwt": {
"audience": "<your-api-identifier>",
"issuer": "https://<your-issuer>/"
}
}
}
}
}
Step 3: Configure entity permissions
Define permissions for the roles your identity provider assigns:
CLI
# Allow authenticated users to read
dab update Book \
--permissions "authenticated:read"
# Allow users with 'admin' role full access
dab update Book \
--permissions "admin:*"
Resulting configuration
{
"entities": {
"Book": {
"source": "dbo.Books",
"permissions": [
{
"role": "authenticated",
"actions": ["read"]
},
{
"role": "admin",
"actions": ["*"]
}
]
}
}
}
Step 4: Configure roles in your identity provider
DAB expects roles in a roles claim. Configure your identity provider to include this claim.
Okta: Add groups as roles
- In the Okta Admin Console, go to Security > API.
- Select your authorization server.
- Go to the Claims tab.
- Add a claim:
- Name:
roles - Include in token type: Access Token
- Value type: Groups
- Filter: Select the groups to include
- Name:
Auth0: Add roles with an Action
Auth0 requires custom claims to use collision-resistant, namespaced names (for example, https://example.com/roles). Non-namespaced claims that collide with reserved names are silently excluded from the token. For more information, see Create custom claims in the Auth0 documentation.
Data API builder expects the exact claim name roles, not a namespaced variant. Whether Auth0 accepts a non-namespaced roles claim depends on your tenant configuration.
In the Auth0 Dashboard, go to Actions > Library.
Create a new Action (Post Login trigger).
Add code to include roles:
exports.onExecutePostLogin = async (event, api) => { const roles = event.authorization?.roles || []; if (roles.length > 0) { api.accessToken.setCustomClaim('roles', roles); } };Deploy the Action and add it to your Login flow.
Verify the decoded access token at jwt.io and confirm the
rolesclaim is present.
Warning
Auth0 may silently drop the non-namespaced roles claim depending on your tenant settings. If the claim is missing from the token, check Settings > Advanced in the Auth0 Dashboard for namespace enforcement. Tenants that require namespaced claims are currently incompatible with Data API builder's role-based authorization for custom roles. The built-in authenticated and anonymous roles still work because they don't depend on a roles claim.
Tip
For detailed guidance on configuring JWT claims with Okta, see Customize tokens returned from Okta.
Step 5: Test the configuration
Start Data API builder:
dab startAcquire a token from your identity provider. Use your provider's SDK or a tool like Postman.
Inspect the token at jwt.io to verify:
- The
audclaim matches your configured audience - The
issclaim matches your configured issuer - The
rolesclaim contains the expected values
- The
Call the API:
curl -X GET "http://localhost:5000/api/Book" \ -H "Authorization: Bearer <your-token>"To use a custom role, include the
X-MS-API-ROLEheader:curl -X GET "http://localhost:5000/api/Book" \ -H "Authorization: Bearer <your-token>" \ -H "X-MS-API-ROLE: admin"
JWT validation details
Data API builder validates these aspects of the JWT:
| Check | Description |
|---|---|
| Signature | Validated using signing keys discovered via the configured jwt.issuer authority (OpenID Connect metadata or JSON Web Key Set (JWKS)) |
| Issuer | Must exactly match jwt.issuer configuration |
| Audience | Must exactly match jwt.audience configuration |
| Expiration | Token must not be expired (exp claim) |
| Not Before | Token must be valid (nbf claim, if present) |
Troubleshooting
| Symptom | Possible cause | Solution |
|---|---|---|
401 Unauthorized |
Issuer mismatch | Check the iss claim matches exactly (including trailing slash) |
401 Unauthorized |
Audience mismatch | Check the aud claim matches your configured value |
401 Unauthorized |
Token expired | Acquire a fresh token |
401 Unauthorized |
Metadata unavailable | Ensure DAB can reach <issuer>/.well-known/openid-configuration |
403 Forbidden |
Role not in token | Add the role to your IdP configuration |
403 Forbidden |
No roles claim found |
Configure your IdP to include a roles claim |
403 Forbidden |
Wrong claim name | DAB uses claim type roles (fixed, not configurable) |
403 Forbidden |
Auth0 custom claim silently dropped | Auth0 may drop non-namespaced custom claims. Verify the roles claim exists in the decoded token at jwt.io. See Auth0: Add roles with an Action |
Important
The claim type roles is hardcoded for all role checks and can't be changed. Configure your identity provider to emit a claim named exactly roles. Auth0 users should review the namespacing conflict.
Common issuer formats
| Provider | Issuer format |
|---|---|
| Okta | https://<domain>.okta.com or https://<domain>.okta.com/oauth2/default |
| Auth0 | https://<tenant>.auth0.com/ (note the trailing slash) |
| Azure AD B2C | https://<tenant>.b2clogin.com/<tenant-id>/v2.0/ |
| Keycloak | https://<host>/realms/<realm> |
Complete configuration example
Okta configuration
{
"$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
"data-source": {
"database-type": "mssql",
"connection-string": "@env('SQL_CONNECTION_STRING')"
},
"runtime": {
"host": {
"authentication": {
"provider": "Custom",
"jwt": {
"audience": "0oa1234567890abcdef",
"issuer": "https://dev-12345.okta.com"
}
}
}
},
"entities": {
"Book": {
"source": "dbo.Books",
"permissions": [
{
"role": "authenticated",
"actions": ["read"]
},
{
"role": "editor",
"actions": ["create", "read", "update"]
}
]
}
}
}
Auth0 configuration
{
"$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
"data-source": {
"database-type": "mssql",
"connection-string": "@env('SQL_CONNECTION_STRING')"
},
"runtime": {
"host": {
"authentication": {
"provider": "Custom",
"jwt": {
"audience": "https://my-api.example.com",
"issuer": "https://my-tenant.auth0.com/"
}
}
}
},
"entities": {
"Book": {
"source": "dbo.Books",
"permissions": [
{
"role": "authenticated",
"actions": ["read"]
},
{
"role": "admin",
"actions": ["*"]
}
]
}
}
}