Skip to content

External Identity Providers

External identity providers allow your end-users to authenticate with their own accounts (Auth0, Clerk, Firebase, etc.) and call the Workspace API directly — no SchemaStack account needed.

This is ideal for building customer-facing SPAs where users sign in through your identity provider and interact with your workspace data.

How It Works

  1. Your end-user authenticates with your identity provider and receives a JWT
  2. Your app sends API requests with that JWT in the Authorization header
  3. SchemaStack validates the JWT against your provider's JWKS endpoint
  4. If valid, the request is processed with the permissions you configured
http
GET /api/v1/acme-corp/sales/Customer
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

SchemaStack inspects the iss (issuer) claim in the JWT to determine whether it's an internal SchemaStack token or an external provider token. External tokens are then validated against the JWKS keys published by your provider.

Configuring an External Identity Provider

  1. Open your workspace in the Admin app
  2. Navigate to Settings > Identity Provider
  3. Fill in the configuration:
FieldRequiredDescription
Issuer URLYesYour provider's issuer URL — must exactly match the iss claim in your JWTs
JWKS URINoURL to the provider's public keys. Leave blank to auto-discover via OIDC discovery
AudienceNoExpected aud claim. Leave blank to skip audience validation
Default PermissionsYesPermission level for all external users: Read Only or Read & Write
EnabledYesToggle to enable/disable external authentication
  1. Click Save Provider

Auto-Discovery

If you leave the JWKS URI blank, SchemaStack will automatically discover it from your provider's /.well-known/openid-configuration endpoint. This works with all OIDC-compliant providers.

JWT Requirements

External JWTs must include the following claims:

ClaimRequiredDescription
issYesMust match the configured Issuer URL
subYesSubject identifier — uniquely identifies the user
expYesExpiration time — expired tokens are rejected
audConditionalMust contain the configured Audience value, if set

The JWT must be signed with an RSA or EC key that is published in the provider's JWKS endpoint.

Row-Level Security (RLS)

By default, all external users see all data in the workspace. Row-Level Security lets you restrict each user to only their own rows based on JWT claims.

How It Works

You configure per-view rules that map a table column to a JWT claim. When an external user makes a request, SchemaStack automatically adds a WHERE clause to every query.

Example: Your orders table has a customer_id column. You create an RLS policy: customer_id = {jwt.sub}. When user auth0|abc123 calls the API, they only see orders where customer_id = 'auth0|abc123'.

Configuring RLS Policies

In the Spread app, open the view properties panel and add RLS rules:

FieldDescription
ColumnThe table column to filter on (e.g., customer_id)
JWT ClaimThe JWT claim to match against (e.g., sub, email)
EnabledToggle to enable/disable the rule

You can add multiple rules per view — they are combined with AND logic.

Enforcement by Operation

OperationBehavior
List / QueryWHERE clause automatically added — user only sees matching rows
Read by IDReturns 404 if the row doesn't belong to the user
CreateRLS column is auto-set from the JWT claim. If the request includes a different value, it's rejected with 403
UpdateRow must belong to the user (404 otherwise). Cannot change the RLS column to a different value (403)
DeleteRow must belong to the user (404 otherwise)

RLS Scope

RLS only applies to external IdP tokens. API keys and SchemaStack OAuth2 tokens are workspace-owner credentials — they bypass RLS and see all data.

Example JWT Claims for RLS

ClaimDescriptionExample Value
subSubject (user ID)auth0|69d120454a06869772a10d84
emailUser's email[email protected]
Custom claimsProvider-specificorg_id, tenant_id, etc.

Index Your RLS Columns

For best performance, create a database index on the column used in your RLS policy (e.g., customer_id). Without an index, every query requires a full table scan.

Permission Model

All users authenticating via an external provider receive the same permission level — the Default Permissions you configured. There is no per-user permission differentiation for external users.

PermissionGETPOSTPUTDELETE
Read & WriteYesYesYesYes
Read OnlyYesNoNoNo

WARNING

External users get broad access to all entities in the workspace. Use Read Only unless your application genuinely needs write access.

Auth0 Setup Guide

Step 1: Create an Auth0 Application

  1. Log in to Auth0 Dashboard
  2. Go to Applications > Applications > Create Application
  3. Choose Single Page Application (for SPAs) or Regular Web Application (for server-side apps)
  4. Give it a name (e.g., "My App - SchemaStack")
  5. Click Create

Step 2: Configure Application Settings

In your new application's Settings tab:

  • Allowed Callback URLs: Add your app's callback URL (e.g., https://myapp.com/callback)
  • Allowed Logout URLs: Add your app's logout URL
  • Allowed Web Origins: Add your app's origin for CORS (e.g., https://myapp.com)

Step 3: Create an API

Required

Without an API, Auth0 returns an opaque token instead of a JWT. SchemaStack cannot validate opaque tokens — this step is mandatory.

  1. Go to Applications > APIs > Create API
  2. Set a name (e.g., "SchemaStack Workspace API")
  3. Set an Identifier — this becomes the aud claim (e.g., https://api.myapp.com)
  4. Click Create

Step 3b: Authorize Your Application

After creating the API, you need to grant your application access:

  1. Go to Applications > APIs > your new API > Application Access
  2. Find your application in the list
  3. If User Access shows "UNAUTHORIZED", click Edit and enable it
  4. Your application must be AUTHORIZED for User Access to request JWTs

Step 4: Note Your Auth0 Values

From your Auth0 dashboard, collect:

ValueWhere to FindExample
DomainApplications > Your App > Settingscasino.eu.auth0.com
AudienceApplications > APIs > Your API > Identifierhttps://api.myapp.com

Important

Auth0 shows the Domain without https:// and without a trailing /. You need to add both when entering the Issuer URL in SchemaStack:

  • Auth0 shows: casino.eu.auth0.com
  • You enter: https://casino.eu.auth0.com/

This must match exactly — Auth0 JWTs contain "iss": "https://casino.eu.auth0.com/" with both the scheme and trailing slash.

INFO

The JWKS URI is automatically published by Auth0 at https://{your-domain}/.well-known/jwks.json — you don't need to set it manually.

Step 5: Configure SchemaStack

In your workspace's Settings > Identity Provider:

FieldValue
Issuer URLhttps://casino.eu.auth0.com/ (add https:// and trailing /)
JWKS URI(leave blank — auto-discovered)
Audiencehttps://api.myapp.com (if you created an API)
Default PermissionsRead Only (recommended to start)
EnabledOn

Step 6: Get a Token and Test

Using your SPA or a test script, obtain a JWT from Auth0:

javascript
// Example using Auth0 SPA SDK
const token = await auth0.getTokenSilently({
  authorizationParams: {
    audience: 'https://api.myapp.com',
  },
});

Then call the SchemaStack Workspace API:

bash
curl -H "Authorization: Bearer <your-auth0-jwt>" \
  https://api.schemastack.io/api/v1/acme-corp/sales/Customer

Expected results:

  • Valid token: 200 with data
  • Expired token: 401 Unauthorized
  • Wrong issuer: 401 Unauthorized
  • Provider disabled: 401 Unauthorized

Clerk Setup Guide

Step 1: Get Your Clerk Values

  1. Log in to Clerk Dashboard
  2. Go to API Keys
  3. Find your Frontend API URL — this is your issuer
ValueWhere to FindExample
Issuer URLClerk Dashboard > API Keyshttps://myapp.clerk.accounts.dev

Step 2: Configure SchemaStack

FieldValue
Issuer URLhttps://myapp.clerk.accounts.dev
JWKS URI(leave blank — auto-discovered)
Audience(leave blank — Clerk doesn't use aud by default)
Default PermissionsRead Only
EnabledOn

Step 3: Get a Token and Test

javascript
// Example using Clerk React SDK
const { getToken } = useAuth();
const token = await getToken();

Firebase Auth Setup Guide

Step 1: Get Your Firebase Values

  1. Open Firebase Console
  2. Your issuer URL follows the pattern: https://securetoken.google.com/{project-id}
ValuePatternExample
Issuer URLhttps://securetoken.google.com/{project-id}https://securetoken.google.com/my-app-12345
AudienceYour Firebase project IDmy-app-12345

Step 2: Configure SchemaStack

FieldValue
Issuer URLhttps://securetoken.google.com/my-app-12345
JWKS URI(leave blank — auto-discovered)
Audiencemy-app-12345
Default PermissionsRead Only
EnabledOn

Step 3: Get a Token and Test

javascript
// Example using Firebase JS SDK
const token = await firebase.auth().currentUser.getIdToken();

Troubleshooting

401 — "No external identity provider configured for this workspace"

The workspace doesn't have an external IdP configured, or it's disabled. Check Settings > Identity Provider.

401 — "Token issuer does not match configured identity provider"

The iss claim in the JWT doesn't match the Issuer URL you configured. Common issues:

  • Missing trailing slash (Auth0 includes one: https://myapp.us.auth0.com/)
  • Wrong region or domain
  • Using a different Auth0 tenant

401 — "Token audience does not match configured audience"

The aud claim in the JWT doesn't include your configured audience. Make sure:

  • You're requesting the correct audience when obtaining the token
  • The audience value matches exactly (case-sensitive)

401 — "Token has expired"

The JWT's exp claim is in the past. Tokens have a limited lifetime (typically 1 hour for Auth0). Your app should refresh tokens automatically.

401 — "Failed to discover JWKS endpoint for issuer"

SchemaStack couldn't reach the provider's /.well-known/openid-configuration endpoint. Check that the Issuer URL is correct and the provider is accessible.

403 — "READ_ONLY permissions — data modifications are not allowed"

The external IdP is configured with Read Only permissions. Change to Read & Write in workspace settings if you need write access.

SchemaStack Documentation