@@ -18,46 +18,32 @@ NodeDB validates JWT bearer tokens against your OIDC provider's public key set (
1818Register your OIDC provider's details:
1919
2020```sql
21- CREATE OIDC PROVIDER okta WITH (
22- issuer = 'https://yourorgname.okta.com/',
23- jwks_url = 'https://yourorgname.okta.com/.well-known/oauth2/default/v1/keys',
24- audience = 'https://nodedb.example.com',
25- claim_mapping = [
26- { claim_name = 'email', claim_value = null, effect = {
27- default_database = 'self_service'
28- } },
29- { claim_name = 'groups', claim_value = 'engineering', effect = {
30- add_databases = ['engineering_prod'],
31- add_roles = ['data_analyst']
32- } }
33- ]
34- );
21+ CREATE OIDC PROVIDER okta ISSUER 'https://yourorgname.okta.com/' JWKS_URI 'https://yourorgname.okta.com/.well-known/oauth2/default/v1/keys' AUDIENCE 'https://nodedb.example.com'
22+ CLAIM MAPPING
23+ WHEN email = null SET DEFAULT_DATABASE = 1
24+ WHEN groups = 'engineering' SET ADD DATABASES [2] ADD ROLES ['data_analyst'];
3525```
3626
3727**Fields:**
3828
39- | Field | Required | Meaning |
40- |-------|----------|---------|
41- | `issuer` | Yes | Token issuer URL (e.g., https://accounts.google.com) |
42- | `jwks_url` | Yes | Public key set URL for signature validation |
43- | `audience` | Yes | Expected JWT `aud` claim; mismatches are rejected |
44- | `claim_mapping` | Yes | Array of rules mapping JWT claims to NodeDB identity fields |
29+ **Syntax:**
30+ - `ISSUER '<url>'` — Token issuer URL (e.g., https://accounts.google.com)
31+ - `JWKS_URI '<url>'` — Public key set URL for signature validation
32+ - `AUDIENCE '<aud>'` — (optional) Expected JWT `aud` claim; mismatches are rejected
33+ - `CLAIM MAPPING WHEN ... [SET DEFAULT_DATABASE = <id>] [ADD DATABASES [...]] [ADD ROLES [...]]` — Rules mapping JWT claims to NodeDB identity
4534
4635NodeDB fetches the JWKS once, caches it in memory, and refreshes it when:
4736- A token arrives with an unknown key ID (`kid`)
4837- The cache TTL expires (typically 24 hours)
49- - You explicitly reload via `ALTER OIDC PROVIDER ... REFRESH JWKS`
5038
5139## Claim Mapping
5240
53- Claim mapping rules translate JWT claims into NodeDB identity fields and access grants. Each rule specifies:
41+ Claim mapping rules translate JWT claims into NodeDB identity fields and access grants. Each rule in the `CLAIM MAPPING` clause specifies:
5442
55- - `claim_name` — JWT claim name to match (e.g., `email`, `groups`, `org_id`)
56- - `claim_value` — (optional) specific value to match; if omitted, rule applies to all values
57- - `effect` — what happens when the rule matches:
58- - `default_database` — set as the user's default database for queries
59- - `add_databases` — grant access to these databases
60- - `add_roles` — assign these roles to the session
43+ - `WHEN <claim> = '<value>'` — JWT claim name and value to match (e.g., `WHEN email = 'alice@example.com'` or `WHEN groups = 'engineering'`)
44+ - `SET DEFAULT_DATABASE = <db_id>` — (optional) set as the user's default database (numeric ID)
45+ - `ADD DATABASES [<id>, ...]` — (optional) grant access to these databases (numeric IDs)
46+ - `ADD ROLES ['<role>', ...]` — (optional) assign these roles to the session (quoted role names)
6147
6248**Example**: An Okta JWT like:
6349
@@ -73,18 +59,11 @@ Claim mapping rules translate JWT claims into NodeDB identity fields and access
7359Maps to:
7460
7561```sql
76- claim_mapping = [
77- { claim_name = 'email', claim_value = null, effect = {
78- default_database = 'analytics'
79- } },
80- { claim_name = 'groups', claim_value = 'engineering', effect = {
81- add_databases = ['engineering_db'],
82- add_roles = ['data_analyst']
83- } },
84- { claim_name = 'groups', claim_value = 'admins', effect = {
85- add_roles = ['cluster_admin']
86- } }
87- ]
62+ CREATE OIDC PROVIDER okta ISSUER 'https://yourorgname.okta.com/' JWKS_URI 'https://...' AUDIENCE 'api'
63+ CLAIM MAPPING
64+ WHEN email = 'alice@acme.com' SET DEFAULT_DATABASE = 2
65+ WHEN groups = 'engineering' ADD DATABASES [3] ADD ROLES ['data_analyst']
66+ WHEN groups = 'admins' ADD ROLES ['cluster_admin'];
8867```
8968
9069The session inherits all matching rules' effects. If multiple rules grant database access, the union is used.
@@ -96,26 +75,16 @@ The session inherits all matching rules' effects. If multiple rules grant databa
9675
9776## Updating a Provider
9877
99- Modify JWKS URL, audience, or claim mappings after creation:
78+ Replace the claim mapping rules after creation:
10079
10180```sql
102- ALTER OIDC PROVIDER okta SET (
103- audience = 'https://api.example.com'
104- );
105-
106- ALTER OIDC PROVIDER okta SET (
107- claim_mapping = [
108- { claim_name = 'email', claim_value = null, effect = {
109- default_database = 'analytics'
110- } },
111- { claim_name = 'dept_name', claim_value = 'sales', effect = {
112- add_databases = ['sales_db'],
113- add_roles = ['sales_role']
114- } }
115- ]
116- );
81+ ALTER OIDC PROVIDER okta SET CLAIM MAPPING
82+ WHEN email = 'alice@acme.com' SET DEFAULT_DATABASE = 2
83+ WHEN dept_name = 'sales' ADD DATABASES [5] ADD ROLES ['sales_role'];
11784```
11885
86+ `ALTER OIDC PROVIDER ... SET CLAIM MAPPING` replaces the full rule set. To change the issuer, JWKS URI, or audience, drop and recreate the provider.
87+
11988Changes take effect immediately for new logins. Existing sessions tied to the provider remain valid until token expiry.
12089
12190## Listing Providers
@@ -126,23 +95,14 @@ See all configured OIDC providers:
12695SHOW OIDC PROVIDERS;
12796```
12897
129- **Output columns:**
130-
131- | Column | Meaning |
132- |--------|---------|
133- | `name` | Provider name (e.g., `okta`) |
134- | `issuer` | Token issuer URL |
135- | `audience` | Expected `aud` claim |
136- | `jwks_url` | Public key set URL |
137- | `claim_mapping` | Array of mapping rules (summary) |
138- | `created_at` | Timestamp |
98+ **Output includes provider name, issuer, audience, JWKS URI, claim mapping rules, and creation timestamp.**
13999
140100## Removing a Provider
141101
142102Drop a provider:
143103
144104```sql
145- DROP OIDC PROVIDER okta;
105+ DROP OIDC PROVIDER IF EXISTS okta;
146106```
147107
148108Existing sessions using tokens from that provider are revoked at their next request.
@@ -167,19 +127,13 @@ NodeDB validates tokens in this order:
167127### Step 1: Configure the Provider
168128
169129```sql
170- CREATE OIDC PROVIDER auth0 WITH (
171- issuer = 'https://your-tenant.us.auth0.com/',
172- jwks_url = 'https://your-tenant.us.auth0.com/.well-known/jwks.json',
173- audience = 'https://api.example.com',
174- claim_mapping = [
175- { claim_name = 'email', claim_value = null, effect = {
176- default_database = 'production'
177- } },
178- { claim_name = 'https://api.example.com/roles', claim_value = 'readwrite', effect = {
179- add_roles = ['readwrite']
180- } }
181- ]
182- );
130+ CREATE OIDC PROVIDER auth0
131+ ISSUER 'https://your-tenant.us.auth0.com/'
132+ JWKS_URI 'https://your-tenant.us.auth0.com/.well-known/jwks.json'
133+ AUDIENCE 'https://api.example.com'
134+ CLAIM MAPPING
135+ WHEN email = null SET DEFAULT_DATABASE = 1
136+ WHEN https://api.example.com/roles = 'readwrite' ADD ROLES ['readwrite'];
183137```
184138
185139### Step 2: Get a Token from Auth0
@@ -204,14 +158,14 @@ curl -H "Authorization: Bearer eyJhbGciOi..." \
204158 -d '{"sql": "SELECT 1"}'
205159```
206160
207- Or via native protocol (e.g., with `nodedb-client`):
161+ Or via native protocol (e.g., with `nodedb-client`) on port 6433 :
208162
209163```rust
210164let auth = AuthMethod::OidcBearer {
211165 token: "eyJhbGciOi...".to_string(),
212166 provider: "auth0".to_string(),
213167};
214- let session = nodedb_client::connect("localhost:6432 ", auth).await?;
168+ let session = nodedb_client::connect("localhost:6433 ", auth).await?;
215169```
216170
217171### Step 4: Query as the Authenticated User
@@ -301,7 +255,7 @@ Regular users cannot modify providers.
301255## Troubleshooting
302256
303257**Token rejected: invalid signature**
304- - JWKS cache may be stale. Manually refresh: `ALTER OIDC PROVIDER <name> REFRESH JWKS`
258+ - JWKS cache may be stale; it will auto- refresh on next unknown key ID
305259- Check that the issuer matches exactly (including trailing `/`)
306260
307261**Token rejected: audience mismatch**
0 commit comments