@tideorg/mcp 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GAP_REGISTER.md +117 -0
- package/README.md +38 -0
- package/adapters/AGENTS.md +241 -0
- package/adapters/CLAUDE.md +146 -0
- package/adapters/replit.md +224 -0
- package/canon/anti-patterns.md +2133 -0
- package/canon/concepts.md +816 -0
- package/canon/custom-contracts.md +533 -0
- package/canon/delegation.md +195 -0
- package/canon/feature-mapping.md +637 -0
- package/canon/framework-matrix.md +1125 -0
- package/canon/invariants.md +851 -0
- package/canon/redirect-handler.md +254 -0
- package/canon/tidecloak-bootstrap.md +287 -0
- package/canon/tidecloak-endpoints.md +294 -0
- package/canon/troubleshooting.md +1494 -0
- package/canon/version-policy.md +89 -0
- package/mcp-server/dist/index.d.ts +2 -0
- package/mcp-server/dist/index.js +605 -0
- package/package.json +45 -0
- package/playbooks/add-auth-nextjs-existing.md +799 -0
- package/playbooks/add-auth-nextjs-fresh.md +654 -0
- package/playbooks/add-rbac-nextjs.md +190 -0
- package/playbooks/bootstrap-realm-from-template.md +170 -0
- package/playbooks/configure-e2ee-roles-and-policies.md +196 -0
- package/playbooks/deploy-tidecloak-docker.md +792 -0
- package/playbooks/diagnose-broken-login.md +234 -0
- package/playbooks/diagnose-missing-roles-or-claims.md +253 -0
- package/playbooks/initialize-admin-and-link-account.md +235 -0
- package/playbooks/migrate-from-existing-auth.md +198 -0
- package/playbooks/protect-api-nextjs.md +451 -0
- package/playbooks/protect-routes-nextjs.md +544 -0
- package/playbooks/setup-forseti-e2ee.md +756 -0
- package/playbooks/setup-iga-admin-panel.md +344 -0
- package/playbooks/setup-server-delegation.md +142 -0
- package/playbooks/start-tidecloak-dev.md +130 -0
- package/playbooks/verify-jwt-server-side.md +439 -0
- package/prompts/add-admin-approval-flow.md +50 -0
- package/prompts/build-private-customer-portal.md +85 -0
- package/prompts/migrate-generic-auth-to-tide.md +67 -0
- package/prompts/secure-existing-app.md +80 -0
- package/reference-apps/INDEX.md +87 -0
- package/reference-apps/encrypted-communication/anti-patterns.md +123 -0
- package/reference-apps/encrypted-communication/bootstrap-sequence.md +152 -0
- package/reference-apps/encrypted-communication/manifest.yaml +100 -0
- package/reference-apps/encrypted-communication/role-policy-matrix.md +80 -0
- package/reference-apps/encrypted-communication/scenario.md +134 -0
- package/reference-apps/git-pr-signing-service/anti-patterns.md +61 -0
- package/reference-apps/git-pr-signing-service/bootstrap-sequence.md +157 -0
- package/reference-apps/git-pr-signing-service/manifest.yaml +80 -0
- package/reference-apps/git-pr-signing-service/role-policy-matrix.md +99 -0
- package/reference-apps/git-pr-signing-service/scenario.md +169 -0
- package/reference-apps/iga-admin-governance/anti-patterns.md +133 -0
- package/reference-apps/iga-admin-governance/bootstrap-sequence.md +153 -0
- package/reference-apps/iga-admin-governance/manifest.yaml +87 -0
- package/reference-apps/iga-admin-governance/role-policy-matrix.md +67 -0
- package/reference-apps/iga-admin-governance/scenario.md +126 -0
- package/reference-apps/organisation-password-manager/anti-patterns.md +71 -0
- package/reference-apps/organisation-password-manager/bootstrap-sequence.md +127 -0
- package/reference-apps/organisation-password-manager/manifest.yaml +86 -0
- package/reference-apps/organisation-password-manager/role-policy-matrix.md +59 -0
- package/reference-apps/organisation-password-manager/scenario.md +107 -0
- package/reference-apps/policy-governed-signing/anti-patterns.md +67 -0
- package/reference-apps/policy-governed-signing/bootstrap-sequence.md +128 -0
- package/reference-apps/policy-governed-signing/manifest.yaml +78 -0
- package/reference-apps/policy-governed-signing/role-policy-matrix.md +62 -0
- package/reference-apps/policy-governed-signing/scenario.md +113 -0
- package/skills/tide-diagnostics/SKILL.md +99 -0
- package/skills/tide-integration/SKILL.md +136 -0
- package/skills/tide-learning-capture/SKILL.md +174 -0
- package/skills/tide-rbac-and-e2ee/SKILL.md +214 -0
- package/skills/tide-reviewer/SKILL.md +133 -0
- package/skills/tide-route-and-api-protection/SKILL.md +201 -0
- package/skills/tide-scenario-resolver/SKILL.md +81 -0
- package/skills/tide-setup/SKILL.md +218 -0
- package/skills/tide-solutions-architect/SKILL.md +130 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Diagnose Broken Login
|
|
2
|
+
|
|
3
|
+
Symptom-led troubleshooting for login failures.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Pre-Flight: Is Tide Actually Installed?
|
|
8
|
+
|
|
9
|
+
Before diagnosing specific symptoms, verify a real Tide integration exists:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 1. SDK installed?
|
|
13
|
+
grep '@tidecloak/nextjs' package.json
|
|
14
|
+
# If missing: npm install @tidecloak/nextjs
|
|
15
|
+
|
|
16
|
+
# 2. Provider in layout?
|
|
17
|
+
grep 'TideCloakProvider\|Providers' app/layout.tsx
|
|
18
|
+
# If missing: no Tide provider wrapping the app
|
|
19
|
+
|
|
20
|
+
# 3. Config file present?
|
|
21
|
+
test -f data/tidecloak.json && echo "Found" || echo "Missing"
|
|
22
|
+
# If missing: export adapter JSON from TideCloak Admin Console
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**If check 1 or 2 fails**, stop. The app does not have a Tide integration. Complete [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) (or [add-auth-nextjs-existing.md](add-auth-nextjs-existing.md) for existing apps) first, then return here.
|
|
26
|
+
|
|
27
|
+
**If only check 3 fails**, export the adapter JSON from TideCloak Admin Console and place it at `data/tidecloak.json`. DPoP is configured per-client in TideCloak Admin, not in the provider props. See [add-auth-nextjs-fresh.md Step 2](add-auth-nextjs-fresh.md#step-2-export-adapter-json-from-tidecloak).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Pre-Flight: Is Adapter Config Present and Correctly Located?
|
|
32
|
+
|
|
33
|
+
Before symptom-specific debugging, verify the adapter config file:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Filename must be tidecloak.json (not adapter.json, not keycloak.json)
|
|
37
|
+
|
|
38
|
+
# Next.js (server-side):
|
|
39
|
+
test -f data/tidecloak.json && echo "Found data/tidecloak.json" || echo "Missing"
|
|
40
|
+
|
|
41
|
+
# React/Vite or Vanilla JS (client-side):
|
|
42
|
+
test -f public/tidecloak.json && echo "Found public/tidecloak.json" || echo "Missing"
|
|
43
|
+
|
|
44
|
+
# Wrong filename?
|
|
45
|
+
ls data/adapter.json data/keycloak.json public/adapter.json public/keycloak.json 2>/dev/null && echo "WRONG FILENAME — rename to tidecloak.json"
|
|
46
|
+
|
|
47
|
+
# Does code point to the right path?
|
|
48
|
+
grep -r 'configUrl\|tidecloak\.json\|adapter\.json' app/providers.tsx src/main.tsx public/auth.js 2>/dev/null
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**If file is missing**: Export from TideCloak admin console. See [add-auth-nextjs-fresh.md Step 2](add-auth-nextjs-fresh.md#step-2-export-adapter-json-from-tidecloak).
|
|
52
|
+
|
|
53
|
+
**If wrong filename**: Rename to `tidecloak.json`. The SDK does not look for `adapter.json` or `keycloak.json`.
|
|
54
|
+
|
|
55
|
+
**If wrong location**: Next.js server-side code reads from `data/tidecloak.json`. React/Vite/Vanilla JS client-side SDK fetches from `public/tidecloak.json` via `configUrl`. See [canon/invariants.md I-05](../canon/invariants.md#i-05-adapter-json-configuration-required).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Symptom: Login Hangs Indefinitely
|
|
60
|
+
|
|
61
|
+
**What you see**: Click login, redirect to TideCloak, enter credentials, spinner forever.
|
|
62
|
+
|
|
63
|
+
**Diagnostic steps**:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 1. Check browser console
|
|
67
|
+
# Look for: "Refused to frame" CSP error
|
|
68
|
+
|
|
69
|
+
# 2. Check CSP headers
|
|
70
|
+
curl -I http://localhost:3000 | grep -i content-security-policy
|
|
71
|
+
|
|
72
|
+
# 3. Check silent SSO file
|
|
73
|
+
curl http://localhost:3000/silent-check-sso.html
|
|
74
|
+
# Should return HTML
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Fix**: Add Tide domains to CSP. See [add-auth-nextjs-fresh.md Step 6](add-auth-nextjs-fresh.md#step-6-configure-csp-for-swe-iframe).
|
|
78
|
+
|
|
79
|
+
**Full guide**: [canon/troubleshooting.md T-01](../canon/troubleshooting.md#t-01-login-hangs-indefinitely).
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Symptom: Login Succeeds but User Lands on 404
|
|
84
|
+
|
|
85
|
+
**What you see**: Credentials accepted at TideCloak, but browser shows 404 or blank page after redirect.
|
|
86
|
+
|
|
87
|
+
**Diagnostic**:
|
|
88
|
+
```bash
|
|
89
|
+
# Check redirect URI in adapter config
|
|
90
|
+
jq '.["auth-server-url"], .resource' data/tidecloak.json 2>/dev/null
|
|
91
|
+
|
|
92
|
+
# Check redirect handler exists
|
|
93
|
+
# App Router:
|
|
94
|
+
test -f app/auth/redirect/page.tsx && echo "Found" || echo "Missing"
|
|
95
|
+
# Pages Router:
|
|
96
|
+
test -f pages/auth/redirect.tsx && echo "Found" || echo "Missing"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Fix**: Create the redirect handler at the configured redirect path. See [canon/redirect-handler.md](../canon/redirect-handler.md) for framework-specific examples and [add-auth-nextjs-fresh.md Step 6](add-auth-nextjs-fresh.md#step-6-create-post-auth-redirect-handler).
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Symptom: Redirect URI Mismatch
|
|
104
|
+
|
|
105
|
+
**What you see**: TideCloak error page: "Invalid redirect_uri".
|
|
106
|
+
|
|
107
|
+
**Diagnostic**:
|
|
108
|
+
```bash
|
|
109
|
+
# Check client config
|
|
110
|
+
# TideCloak Admin → Clients → {client} → Settings → Valid Redirect URIs
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Fix**: Add app URL to valid redirect URIs:
|
|
114
|
+
- `http://localhost:3000/*` (dev)
|
|
115
|
+
- `https://app.example.com/*` (prod)
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Symptom: Cannot Find Module @tidecloak/nextjs
|
|
120
|
+
|
|
121
|
+
**What you see**: Import error on SDK package.
|
|
122
|
+
|
|
123
|
+
**Diagnostic**:
|
|
124
|
+
```bash
|
|
125
|
+
cat package.json | grep tidecloak
|
|
126
|
+
# Should show: "@tidecloak/nextjs": "..."
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Fix**:
|
|
130
|
+
```bash
|
|
131
|
+
npm install @tidecloak/nextjs
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
All `@tidecloak` packages are available on public npm registry.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Symptom: Config Not Loading
|
|
139
|
+
|
|
140
|
+
**What you see**: Provider fails to initialize, or auth-server-url / realm / clientId are undefined.
|
|
141
|
+
|
|
142
|
+
**Diagnostic**:
|
|
143
|
+
```bash
|
|
144
|
+
# Check tidecloak.json exists at the correct path
|
|
145
|
+
test -f data/tidecloak.json && echo "Found" || echo "MISSING — export from TideCloak admin"
|
|
146
|
+
|
|
147
|
+
# Check it has required Tide fields
|
|
148
|
+
node -e "const c=require('./data/tidecloak.json'); console.log('realm:', c.realm, 'url:', c['auth-server-url'], 'jwk:', !!c.jwk)"
|
|
149
|
+
|
|
150
|
+
# Check provider imports it
|
|
151
|
+
grep "tidecloak.json" app/providers.tsx src/app/providers.tsx 2>/dev/null
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Fix**: The app should load config from `data/tidecloak.json`, not from `NEXT_PUBLIC_TIDECLOAK_*` env vars. If `providers.tsx` uses env vars instead of importing the JSON file, replace with:
|
|
155
|
+
```typescript
|
|
156
|
+
import tcConfig from '../../data/tidecloak.json';
|
|
157
|
+
// ...
|
|
158
|
+
<TideCloakProvider config={tcConfig}>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Do not create `NEXT_PUBLIC_TIDECLOAK_URL`, `NEXT_PUBLIC_TIDECLOAK_REALM`, `NEXT_PUBLIC_TIDECLOAK_CLIENT_ID`, or `NEXT_PUBLIC_TIDECLOAK_REDIRECT_URI` env vars. These values are in `tidecloak.json`.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Symptom: Silent Refresh Fails
|
|
166
|
+
|
|
167
|
+
**What you see**: User logged out after 10 minutes.
|
|
168
|
+
|
|
169
|
+
**Diagnostic**:
|
|
170
|
+
```bash
|
|
171
|
+
# Check silent SSO file
|
|
172
|
+
curl http://localhost:3000/silent-check-sso.html
|
|
173
|
+
# Should return HTML
|
|
174
|
+
|
|
175
|
+
# Check browser console for 404
|
|
176
|
+
# DevTools → Console → Filter: silent-check-sso
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Fix**: Create `public/silent-check-sso.html`. See [add-auth-nextjs-fresh.md Step 5](add-auth-nextjs-fresh.md#step-5-create-silent-sso-file).
|
|
180
|
+
|
|
181
|
+
**Full guide**: [canon/troubleshooting.md T-04](../canon/troubleshooting.md#t-04-silent-token-refresh-fails).
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Symptom: Infinite Redirect Loop
|
|
186
|
+
|
|
187
|
+
**What you see**: Page redirects to login, login redirects to page, repeat forever.
|
|
188
|
+
|
|
189
|
+
**Diagnostic**: Check if login page has auth guard.
|
|
190
|
+
|
|
191
|
+
**Fix**: Remove auth guard from login/public pages:
|
|
192
|
+
```typescript
|
|
193
|
+
// app/login/page.tsx
|
|
194
|
+
export default function LoginPage() {
|
|
195
|
+
// NO AuthGuard here
|
|
196
|
+
return <div>Login</div>;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Symptom: CORS Errors
|
|
203
|
+
|
|
204
|
+
**What you see**: Browser console: "CORS policy: No 'Access-Control-Allow-Origin'".
|
|
205
|
+
|
|
206
|
+
**Diagnostic**: Check TideCloak client Web Origins.
|
|
207
|
+
|
|
208
|
+
**Fix**:
|
|
209
|
+
1. TideCloak Admin → Clients → {client} → Settings
|
|
210
|
+
2. Web Origins: Add `http://localhost:3000` and `https://app.example.com`
|
|
211
|
+
3. Save
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Quick Diagnostic Checklist
|
|
216
|
+
|
|
217
|
+
Run these in order:
|
|
218
|
+
|
|
219
|
+
- [ ] TideCloak reachable: `curl ${TIDECLOAK_URL}/.well-known/openid-configuration`
|
|
220
|
+
- [ ] Adapter config filename is `tidecloak.json` (not `adapter.json` or `keycloak.json`)
|
|
221
|
+
- [ ] Adapter config at correct location: `data/tidecloak.json` (Next.js) or `public/tidecloak.json` (React/Vite/Vanilla)
|
|
222
|
+
- [ ] Adapter JSON valid: `jq 'has("jwk") and has("vendorId") and has("homeOrkUrl")' data/tidecloak.json`
|
|
223
|
+
- [ ] Env vars set: `cat .env.local | grep NEXT_PUBLIC`
|
|
224
|
+
- [ ] CSP configured: `curl -I http://localhost:3000 | grep CSP`
|
|
225
|
+
- [ ] Silent SSO file: `curl http://localhost:3000/silent-check-sso.html`
|
|
226
|
+
- [ ] Redirect handler exists at configured redirectUri path
|
|
227
|
+
- [ ] Browser console clean (no errors)
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## References
|
|
232
|
+
|
|
233
|
+
- [canon/troubleshooting.md](../canon/troubleshooting.md) - Complete troubleshooting
|
|
234
|
+
- [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) - Setup checklist
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Diagnose Missing Roles or Claims
|
|
2
|
+
|
|
3
|
+
Troubleshoot missing or incorrect JWT claims.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Pre-Check: Is There a Real JWT?
|
|
8
|
+
|
|
9
|
+
Before inspecting claims, confirm the app is using real Tide JWTs, not fake auth:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Check for fake/hardcoded tokens
|
|
13
|
+
grep -r "auth_token\|fake.*token\|hardcoded\|FAKE_USERS" lib/ app/ --include="*.ts" --include="*.tsx"
|
|
14
|
+
# If matches: the app is using fake auth, not Tide. Fix the auth system first.
|
|
15
|
+
|
|
16
|
+
# Check for cookie-based auth instead of JWT
|
|
17
|
+
grep -r "cookies.*auth\|cookie.*token" app/api/ --include="*.ts"
|
|
18
|
+
# If matches: API reads auth from cookies, not Authorization header. See protect-api-nextjs.md.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If the app has no real Tide integration (no `@tidecloak/nextjs` in package.json, no `TideCloakProvider` in layout), stop. Complete [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) first. Role diagnostics only apply to apps with working Tide auth.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Symptom: Role Check Always Fails
|
|
26
|
+
|
|
27
|
+
**What you see**: `hasRealmRole('admin')` returns false even for admin users.
|
|
28
|
+
|
|
29
|
+
**Diagnostic steps**:
|
|
30
|
+
|
|
31
|
+
### Step 1: Check JWT Contents
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Client-side
|
|
35
|
+
const { getValueFromToken, getValueFromIdToken } = useTideCloak();
|
|
36
|
+
console.log('User sub:', getValueFromToken("sub"));
|
|
37
|
+
console.log('Realm roles:', getValueFromToken("realm_access")?.roles);
|
|
38
|
+
console.log('Resource access:', getValueFromToken("resource_access"));
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or decode JWT manually:
|
|
42
|
+
```bash
|
|
43
|
+
# Get token from browser DevTools → Application → Local Storage
|
|
44
|
+
# Paste at jwt.io to decode
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 2: Verify Role Name
|
|
48
|
+
|
|
49
|
+
Common mismatches:
|
|
50
|
+
- Looking for `'admin'` but role is `'realm-admin'`
|
|
51
|
+
- Case sensitivity: `'Admin'` vs `'admin'`
|
|
52
|
+
- Client role vs realm role
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// Check both realm and client roles
|
|
56
|
+
function hasAnyRole(user: any, role: string): boolean {
|
|
57
|
+
// Realm roles
|
|
58
|
+
const realmRoles = user?.realm_access?.roles || [];
|
|
59
|
+
if (realmRoles.includes(role)) return true;
|
|
60
|
+
|
|
61
|
+
// Client roles
|
|
62
|
+
const resourceAccess = user?.resource_access || {};
|
|
63
|
+
for (const client of Object.values(resourceAccess)) {
|
|
64
|
+
const clientRoles = (client as any)?.roles || [];
|
|
65
|
+
if (clientRoles.includes(role)) return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Symptom: User Has No Roles
|
|
75
|
+
|
|
76
|
+
**What you see**: `getValueFromToken("realm_access")?.roles` is empty array or undefined.
|
|
77
|
+
|
|
78
|
+
**Diagnostic**:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Check user in TideCloak Admin
|
|
82
|
+
# Admin Console → Users → {user} → Role Mappings
|
|
83
|
+
# Should show assigned roles
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Causes**:
|
|
87
|
+
|
|
88
|
+
1. **Roles not assigned**: Assign in TideCloak Admin
|
|
89
|
+
2. **IGA pending**: If IGA enabled, role assignment needs quorum approval
|
|
90
|
+
3. **Default roles missing**: Realm missing default composite role
|
|
91
|
+
|
|
92
|
+
**Fix (assign role)**:
|
|
93
|
+
|
|
94
|
+
1. TideCloak Admin → Users → {user} → Role Mappings
|
|
95
|
+
2. Assign role → {role-name}
|
|
96
|
+
3. If IGA enabled: Approve change-set (requires quorum)
|
|
97
|
+
4. User logout/login to get new token
|
|
98
|
+
|
|
99
|
+
**Fix (default roles)**:
|
|
100
|
+
|
|
101
|
+
1. TideCloak Admin → Realm Settings → User Registration → Default Roles
|
|
102
|
+
2. Add a `_tide_*` role (e.g., `_tide_enabled`) and application default role
|
|
103
|
+
3. New users auto-receive these roles
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Symptom: Custom Claim Missing
|
|
108
|
+
|
|
109
|
+
**What you see**: `getValueFromToken("custom_field")` returns undefined.
|
|
110
|
+
|
|
111
|
+
**Diagnostic**:
|
|
112
|
+
|
|
113
|
+
Check if protocol mapper exists:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# TideCloak Admin → Client Scopes → roles → Mappers
|
|
117
|
+
# Or: Clients → {client} → Client Scopes → roles → Mappers
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Fix (add protocol mapper)**:
|
|
121
|
+
|
|
122
|
+
1. Client Scopes → roles → Mappers → Create
|
|
123
|
+
2. Mapper Type: "User Attribute"
|
|
124
|
+
3. User Attribute: `customField` (user attribute name)
|
|
125
|
+
4. Token Claim Name: `custom_field` (claim name in JWT)
|
|
126
|
+
5. Claim JSON Type: String
|
|
127
|
+
6. Add to ID token: ON
|
|
128
|
+
7. Add to access token: ON
|
|
129
|
+
8. Save
|
|
130
|
+
|
|
131
|
+
**Fix (set user attribute)**:
|
|
132
|
+
|
|
133
|
+
1. Users → {user} → Attributes
|
|
134
|
+
2. Key: `customField`, Value: `some-value`
|
|
135
|
+
3. Save
|
|
136
|
+
|
|
137
|
+
User must logout/login to get updated token.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Symptom: `tideuserkey` or `vuid` Missing
|
|
142
|
+
|
|
143
|
+
**What you see**: Tide-specific claims missing.
|
|
144
|
+
|
|
145
|
+
**Cause**: Protocol mappers not configured or account not linked.
|
|
146
|
+
|
|
147
|
+
**Diagnostic**:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Check user attributes
|
|
151
|
+
curl "${TIDECLOAK_URL}/admin/realms/${REALM}/users/${USER_ID}" | \
|
|
152
|
+
jq '.attributes | {tideUserKey, vuid}'
|
|
153
|
+
# Should show values
|
|
154
|
+
|
|
155
|
+
# Check protocol mappers
|
|
156
|
+
curl "${TIDECLOAK_URL}/admin/realms/${REALM}/clients/${CLIENT_ID}/protocol-mappers/models" | \
|
|
157
|
+
jq '.[] | select(.name | contains("tide"))'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Fix**: See [canon/troubleshooting.md T-07](../canon/troubleshooting.md#t-07-account-linking-stuck) for account linking.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Symptom: Roles Change But Token Doesn't Update
|
|
165
|
+
|
|
166
|
+
**What you see**: Assigned new role in TideCloak, but `getValueFromToken("realm_access")?.roles` still shows old values.
|
|
167
|
+
|
|
168
|
+
**Cause**: Token cached. JWT claims frozen at issue time.
|
|
169
|
+
|
|
170
|
+
**Fix**:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# User must logout/login to get fresh token
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Or force refresh:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Client-side
|
|
180
|
+
const { logout, login } = useTideCloak();
|
|
181
|
+
|
|
182
|
+
async function forceTokenRefresh() {
|
|
183
|
+
await logout();
|
|
184
|
+
await login();
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Symptom: E2EE Role Not Working
|
|
191
|
+
|
|
192
|
+
**What you see**: `doEncrypt('tag', data)` fails even though user has role.
|
|
193
|
+
|
|
194
|
+
**Diagnostic**:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Check exact role name
|
|
198
|
+
# Should be: _tide_{tag}.selfencrypt
|
|
199
|
+
# Not: _tide_encrypt or tide_{tag}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Fix**:
|
|
203
|
+
|
|
204
|
+
1. TideCloak Admin → Roles → Create Role
|
|
205
|
+
2. Name: `_tide_ssn.selfencrypt` (exact pattern)
|
|
206
|
+
3. Assign to user
|
|
207
|
+
4. Create matching decrypt role: `_tide_ssn.selfdecrypt`
|
|
208
|
+
5. User logout/login
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Quick Diagnostic Script
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Add to app for debugging
|
|
216
|
+
function debugAuth() {
|
|
217
|
+
const { authenticated, getValueFromToken, getValueFromIdToken } = useTideCloak();
|
|
218
|
+
|
|
219
|
+
console.log('=== Auth Debug ===');
|
|
220
|
+
console.log('Authenticated:', authenticated);
|
|
221
|
+
console.log('User sub:', getValueFromToken("sub"));
|
|
222
|
+
console.log('User name:', getValueFromIdToken("preferred_username"));
|
|
223
|
+
console.log('Realm roles:', getValueFromToken("realm_access")?.roles);
|
|
224
|
+
console.log('Resource access:', getValueFromToken("resource_access"));
|
|
225
|
+
console.log('Tide claims:', {
|
|
226
|
+
tideuserkey: getValueFromToken("tideuserkey"),
|
|
227
|
+
vuid: getValueFromToken("vuid")
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Call from browser console
|
|
232
|
+
debugAuth();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Known Issues
|
|
238
|
+
|
|
239
|
+
### `_tide_*` Role Required
|
|
240
|
+
|
|
241
|
+
**Required for all Tide operations**: Every user must have at least one role starting with `_tide_` (e.g., `_tide_enabled`). This role assignment enables the Tide Voucher system to fund user operations.
|
|
242
|
+
|
|
243
|
+
**Why**: The Vendor uses the `_tide_*` role to verify the user is Tide-enabled before assigning Vouchers. Without this role, Tide-related requests (including authorization) will be rejected.
|
|
244
|
+
|
|
245
|
+
**Fix**: Add a `_tide_*` role to realm default roles. Common convention: `_tide_enabled`.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## References
|
|
250
|
+
|
|
251
|
+
- [add-rbac-nextjs.md](add-rbac-nextjs.md) - RBAC implementation
|
|
252
|
+
- [canon/troubleshooting.md T-07](../canon/troubleshooting.md#t-07-account-linking-stuck) - Account linking
|
|
253
|
+
- [canon/concepts.md#tag-based-e2ee-roles](../canon/concepts.md#tag-based-e2ee-roles) - E2EE roles
|