Appearance
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
- Your end-user authenticates with your identity provider and receives a JWT
- Your app sends API requests with that JWT in the
Authorizationheader - SchemaStack validates the JWT against your provider's JWKS endpoint
- 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
- Open your workspace in the Admin app
- Navigate to Settings > Identity Provider
- Fill in the configuration:
| Field | Required | Description |
|---|---|---|
| Issuer URL | Yes | Your provider's issuer URL — must exactly match the iss claim in your JWTs |
| JWKS URI | No | URL to the provider's public keys. Leave blank to auto-discover via OIDC discovery |
| Audience | No | Expected aud claim. Leave blank to skip audience validation |
| Default Permissions | Yes | Permission level for all external users: Read Only or Read & Write |
| Enabled | Yes | Toggle to enable/disable external authentication |
- 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:
| Claim | Required | Description |
|---|---|---|
iss | Yes | Must match the configured Issuer URL |
sub | Yes | Subject identifier — uniquely identifies the user |
exp | Yes | Expiration time — expired tokens are rejected |
aud | Conditional | Must 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:
| Field | Description |
|---|---|
| Column | The table column to filter on (e.g., customer_id) |
| JWT Claim | The JWT claim to match against (e.g., sub, email) |
| Enabled | Toggle to enable/disable the rule |
You can add multiple rules per view — they are combined with AND logic.
Enforcement by Operation
| Operation | Behavior |
|---|---|
| List / Query | WHERE clause automatically added — user only sees matching rows |
| Read by ID | Returns 404 if the row doesn't belong to the user |
| Create | RLS column is auto-set from the JWT claim. If the request includes a different value, it's rejected with 403 |
| Update | Row must belong to the user (404 otherwise). Cannot change the RLS column to a different value (403) |
| Delete | Row 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
| Claim | Description | Example Value |
|---|---|---|
sub | Subject (user ID) | auth0|69d120454a06869772a10d84 |
email | User's email | [email protected] |
| Custom claims | Provider-specific | org_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.
| Permission | GET | POST | PUT | DELETE |
|---|---|---|---|---|
| Read & Write | Yes | Yes | Yes | Yes |
| Read Only | Yes | No | No | No |
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
- Log in to Auth0 Dashboard
- Go to Applications > Applications > Create Application
- Choose Single Page Application (for SPAs) or Regular Web Application (for server-side apps)
- Give it a name (e.g., "My App - SchemaStack")
- 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.
- Go to Applications > APIs > Create API
- Set a name (e.g., "SchemaStack Workspace API")
- Set an Identifier — this becomes the
audclaim (e.g.,https://api.myapp.com) - Click Create
Step 3b: Authorize Your Application
After creating the API, you need to grant your application access:
- Go to Applications > APIs > your new API > Application Access
- Find your application in the list
- If User Access shows "UNAUTHORIZED", click Edit and enable it
- Your application must be AUTHORIZED for User Access to request JWTs
Step 4: Note Your Auth0 Values
From your Auth0 dashboard, collect:
| Value | Where to Find | Example |
|---|---|---|
| Domain | Applications > Your App > Settings | casino.eu.auth0.com |
| Audience | Applications > APIs > Your API > Identifier | https://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:
| Field | Value |
|---|---|
| Issuer URL | https://casino.eu.auth0.com/ (add https:// and trailing /) |
| JWKS URI | (leave blank — auto-discovered) |
| Audience | https://api.myapp.com (if you created an API) |
| Default Permissions | Read Only (recommended to start) |
| Enabled | On |
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/CustomerExpected results:
- Valid token:
200with data - Expired token:
401 Unauthorized - Wrong issuer:
401 Unauthorized - Provider disabled:
401 Unauthorized
Clerk Setup Guide
Step 1: Get Your Clerk Values
- Log in to Clerk Dashboard
- Go to API Keys
- Find your Frontend API URL — this is your issuer
| Value | Where to Find | Example |
|---|---|---|
| Issuer URL | Clerk Dashboard > API Keys | https://myapp.clerk.accounts.dev |
Step 2: Configure SchemaStack
| Field | Value |
|---|---|
| Issuer URL | https://myapp.clerk.accounts.dev |
| JWKS URI | (leave blank — auto-discovered) |
| Audience | (leave blank — Clerk doesn't use aud by default) |
| Default Permissions | Read Only |
| Enabled | On |
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
- Open Firebase Console
- Your issuer URL follows the pattern:
https://securetoken.google.com/{project-id}
| Value | Pattern | Example |
|---|---|---|
| Issuer URL | https://securetoken.google.com/{project-id} | https://securetoken.google.com/my-app-12345 |
| Audience | Your Firebase project ID | my-app-12345 |
Step 2: Configure SchemaStack
| Field | Value |
|---|---|
| Issuer URL | https://securetoken.google.com/my-app-12345 |
| JWKS URI | (leave blank — auto-discovered) |
| Audience | my-app-12345 |
| Default Permissions | Read Only |
| Enabled | On |
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.