@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,235 @@
|
|
|
1
|
+
# Initialize Admin and Link Tide Account
|
|
2
|
+
|
|
3
|
+
Create the realm admin user, assign `tide-realm-admin`, generate the invite link, wait for account linking, approve user change requests, configure the IdP domain, and export the adapter JSON.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- After `bootstrap-realm-from-template` — realm exists with IGA enabled, client change requests approved
|
|
10
|
+
- Admin user does not yet exist in the realm
|
|
11
|
+
|
|
12
|
+
**Do not use** if the admin already has `tideUserKey` set. Check: `curl -H "Authorization: Bearer $TOKEN" "$TIDECLOAK_URL/admin/realms/$REALM_NAME/users?username=admin" | jq -r '.[0].attributes.tideUserKey[0] // empty'`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- TideCloak running with realm created and IGA enabled (playbook `bootstrap-realm-from-template` complete)
|
|
19
|
+
- `curl`, `jq` installed
|
|
20
|
+
- A browser to open the invite link (interactive step)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
### Step 1: Create admin user
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
TIDECLOAK_URL="${TIDECLOAK_URL:-http://localhost:8080}"
|
|
30
|
+
REALM_NAME="${REALM_NAME:-myapp}"
|
|
31
|
+
CLIENT_NAME="${CLIENT_NAME:-myclient}"
|
|
32
|
+
CLIENT_APP_URL="${CLIENT_APP_URL:-http://localhost:3000}"
|
|
33
|
+
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@yourorg.com}"
|
|
34
|
+
|
|
35
|
+
get_token() {
|
|
36
|
+
curl -s -X POST "$TIDECLOAK_URL/realms/master/protocol/openid-connect/token" \
|
|
37
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
38
|
+
-d "username=admin&password=password&grant_type=password&client_id=admin-cli" \
|
|
39
|
+
| jq -r '.access_token'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
TOKEN="$(get_token)"
|
|
43
|
+
curl -s -X POST "$TIDECLOAK_URL/admin/realms/$REALM_NAME/users" \
|
|
44
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
45
|
+
-H "Content-Type: application/json" \
|
|
46
|
+
-d "{\"username\":\"admin\",\"email\":\"$ADMIN_EMAIL\",\"enabled\":true}"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 1b: Approve user creation change request (if any)
|
|
50
|
+
|
|
51
|
+
With IGA enabled, user creation usually generates a change request. Approve before proceeding. **Note**: When the master admin token creates the first user, IGA may not generate a change request (the master admin bypasses realm-level IGA). The `approve_and_commit` function handles this gracefully — if no requests exist, it skips. VERIFIED (atproto-learnings L-02).
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
sleep 2
|
|
55
|
+
approve_and_commit users
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
(Use the `approve_and_commit` function from `bootstrap-realm-from-template`.)
|
|
59
|
+
|
|
60
|
+
**Failure if skipped**: User lookup in Step 2 returns `null`. Role lookup returns `{"error":"..."}` which gets passed as the role mapping body, producing `Invalid json representation for RoleRepresentation`.
|
|
61
|
+
|
|
62
|
+
### Step 2: Assign tide-realm-admin role
|
|
63
|
+
|
|
64
|
+
`tide-realm-admin` is a **client role** on the `realm-management` client, not a realm role.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
TOKEN="$(get_token)"
|
|
68
|
+
USER_ID=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/users?username=admin" \
|
|
69
|
+
-H "Authorization: Bearer $TOKEN" | jq -r '.[0].id')
|
|
70
|
+
|
|
71
|
+
if [ -z "$USER_ID" ] || [ "$USER_ID" = "null" ]; then
|
|
72
|
+
echo "ERROR: Could not find admin user. Was the user change request approved?"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
TOKEN="$(get_token)"
|
|
77
|
+
CLIENT_UUID=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/clients?clientId=realm-management" \
|
|
78
|
+
-H "Authorization: Bearer $TOKEN" | jq -r '.[0].id')
|
|
79
|
+
|
|
80
|
+
ROLE_JSON=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/clients/$CLIENT_UUID/roles/tide-realm-admin" \
|
|
81
|
+
-H "Authorization: Bearer $TOKEN")
|
|
82
|
+
|
|
83
|
+
# Validate we got a role, not an error
|
|
84
|
+
if echo "$ROLE_JSON" | jq -e '.error' > /dev/null 2>&1; then
|
|
85
|
+
echo "ERROR: tide-realm-admin role not found: $ROLE_JSON"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
TOKEN="$(get_token)"
|
|
90
|
+
curl -s -X POST "$TIDECLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/role-mappings/clients/$CLIENT_UUID" \
|
|
91
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
92
|
+
-H "Content-Type: application/json" \
|
|
93
|
+
-d "[$ROLE_JSON]"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Step 3: Generate invite link
|
|
97
|
+
|
|
98
|
+
Use the required-action-link endpoint. **Do not use `execute-actions-email`** — it fails on the dev image without SMTP configuration (`"Invalid sender address 'null'"`). The direct link method works without SMTP. VERIFIED (LEARNINGS-batch-008 L-05).
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
TOKEN="$(get_token)"
|
|
102
|
+
INVITE_LINK=$(curl -s -X POST \
|
|
103
|
+
"$TIDECLOAK_URL/admin/realms/$REALM_NAME/tideAdminResources/get-required-action-link?userId=$USER_ID&lifespan=43200" \
|
|
104
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
105
|
+
-H "Content-Type: application/json" \
|
|
106
|
+
-d '["link-tide-account-action"]')
|
|
107
|
+
|
|
108
|
+
echo "====================================="
|
|
109
|
+
echo "Open this link in a browser to link your admin Tide account:"
|
|
110
|
+
echo "$INVITE_LINK"
|
|
111
|
+
echo "====================================="
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**This is an interactive step.** The admin must open the link in a browser and complete the Tide account linking flow. The script cannot automate this — it requires the user's browser.
|
|
115
|
+
|
|
116
|
+
### Step 4: Wait for account linking
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
echo "Waiting for admin to link Tide account..."
|
|
120
|
+
while true; do
|
|
121
|
+
TOKEN="$(get_token)"
|
|
122
|
+
KEY=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/users?username=admin" \
|
|
123
|
+
-H "Authorization: Bearer $TOKEN" | jq -r '.[0].attributes.tideUserKey[0] // empty')
|
|
124
|
+
[ -n "$KEY" ] && echo "Account linked." && break
|
|
125
|
+
sleep 5
|
|
126
|
+
done
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Step 5: Approve user change requests
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Reuse approve_and_commit from bootstrap-realm-from-template
|
|
133
|
+
approve_and_commit() {
|
|
134
|
+
local TYPE=$1
|
|
135
|
+
TOKEN="$(get_token)"
|
|
136
|
+
local requests=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/tide-admin/change-set/$TYPE/requests" \
|
|
137
|
+
-H "Authorization: Bearer $TOKEN" 2>/dev/null || echo "[]")
|
|
138
|
+
|
|
139
|
+
echo "$requests" | jq -c '.[]' | while read -r req; do
|
|
140
|
+
local id=$(echo "$req" | jq -r .draftRecordId)
|
|
141
|
+
local cst=$(echo "$req" | jq -r .changeSetType)
|
|
142
|
+
local at=$(echo "$req" | jq -r .actionType)
|
|
143
|
+
local payload="{\"changeSetId\":\"$id\",\"changeSetType\":\"$cst\",\"actionType\":\"$at\"}"
|
|
144
|
+
|
|
145
|
+
TOKEN="$(get_token)"
|
|
146
|
+
curl -s -X POST "$TIDECLOAK_URL/admin/realms/$REALM_NAME/tide-admin/change-set/sign" \
|
|
147
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
148
|
+
-H "Content-Type: application/json" -d "$payload"
|
|
149
|
+
|
|
150
|
+
curl -s -X POST "$TIDECLOAK_URL/admin/realms/$REALM_NAME/tide-admin/change-set/commit" \
|
|
151
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
152
|
+
-H "Content-Type: application/json" -d "$payload"
|
|
153
|
+
done
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
approve_and_commit users
|
|
157
|
+
approve_and_commit roles
|
|
158
|
+
approve_and_commit clients
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Sweep all types.** Account linking generates a user change request for the `tideUserKey` attribute write. The IGA toggle and setUpTideRealm may also have generated accumulated client change requests. Approve all three types here. VERIFIED (atproto-learnings L-06, L-07).
|
|
162
|
+
|
|
163
|
+
### Step 6: Update CustomAdminUIDomain
|
|
164
|
+
|
|
165
|
+
Required for enclave approval popups to work from the app origin.
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
TOKEN="$(get_token)"
|
|
169
|
+
INST=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/identity-provider/instances/tide" \
|
|
170
|
+
-H "Authorization: Bearer $TOKEN")
|
|
171
|
+
UPDATED=$(echo "$INST" | jq --arg d "$CLIENT_APP_URL" '.config.CustomAdminUIDomain=$d')
|
|
172
|
+
curl -s -X PUT "$TIDECLOAK_URL/admin/realms/$REALM_NAME/identity-provider/instances/tide" \
|
|
173
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
174
|
+
-H "Content-Type: application/json" -d "$UPDATED"
|
|
175
|
+
|
|
176
|
+
curl -s -X POST "$TIDECLOAK_URL/admin/realms/$REALM_NAME/vendorResources/sign-idp-settings" \
|
|
177
|
+
-H "Authorization: Bearer $TOKEN"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Step 7: Export adapter JSON
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
TOKEN="$(get_token)"
|
|
184
|
+
CLIENT_UUID=$(curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/clients?clientId=$CLIENT_NAME" \
|
|
185
|
+
-H "Authorization: Bearer $TOKEN" | jq -r '.[0].id')
|
|
186
|
+
|
|
187
|
+
ADAPTER_OUTPUT="${ADAPTER_OUTPUT:-./data/tidecloak.json}"
|
|
188
|
+
curl -s "$TIDECLOAK_URL/admin/realms/$REALM_NAME/vendorResources/get-installations-provider?clientId=$CLIENT_UUID&providerId=keycloak-oidc-keycloak-json" \
|
|
189
|
+
-H "Authorization: Bearer $TOKEN" > "$ADAPTER_OUTPUT"
|
|
190
|
+
|
|
191
|
+
echo "Adapter config saved to $ADAPTER_OUTPUT"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Verify the export:
|
|
195
|
+
```bash
|
|
196
|
+
node -e "const c=require('$ADAPTER_OUTPUT'); console.log('jwk:', !!c.jwk, 'vendorId:', !!c.vendorId, 'homeOrkUrl:', !!c.homeOrkUrl)"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Verification
|
|
202
|
+
|
|
203
|
+
- [ ] Admin user exists with `tideUserKey` attribute set
|
|
204
|
+
- [ ] `tide-realm-admin` assigned (client role on `realm-management`)
|
|
205
|
+
- [ ] No pending user change requests remain
|
|
206
|
+
- [ ] CustomAdminUIDomain matches app origin
|
|
207
|
+
- [ ] Adapter JSON at `$ADAPTER_OUTPUT` contains `jwk`, `vendorId`, `homeOrkUrl`
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Common Failures
|
|
212
|
+
|
|
213
|
+
| Symptom | Cause | Fix |
|
|
214
|
+
|---------|-------|-----|
|
|
215
|
+
| Invite link returns 404 | `requiredActions` missing from realm template | Use full template with `link-tide-account-action` |
|
|
216
|
+
| "Could not find configuration for Required Action" | Tide env vars missing from container | Restart container with all required env vars |
|
|
217
|
+
| `tideUserKey` never appears | Admin didn't complete the linking flow | Open invite link in browser, complete the flow |
|
|
218
|
+
| Enclave popups don't work from app | CustomAdminUIDomain not set | Run Step 6 |
|
|
219
|
+
| Adapter JSON missing `jwk` | IGA not enabled | Run `toggle-iga` from `bootstrap-realm-from-template` Step 5 |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Anti-Patterns
|
|
224
|
+
|
|
225
|
+
- **Do not** auto-approve IGA role assignments from the backend. `requiresApprovalPopup: true` means the browser enclave is required for VVK-signed UserContexts.
|
|
226
|
+
- **Do not** skip the invite link step. Account linking is interactive by design.
|
|
227
|
+
- **Do not** use `hasRealmRole("tide-realm-admin")` to check admin status. It is a client role on `realm-management`. Use `hasClientRole("tide-realm-admin", "realm-management")`.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Next Step
|
|
232
|
+
|
|
233
|
+
Bootstrap is complete. Proceed to app integration:
|
|
234
|
+
- Fresh app → playbook `add-auth-nextjs-fresh`
|
|
235
|
+
- E2EE needed → playbook `configure-e2ee-roles-and-policies`
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Migrate from Existing Auth to TideCloak
|
|
2
|
+
|
|
3
|
+
Replace your current identity provider with TideCloak while keeping standard OIDC flows intact.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- Migrating from vanilla Keycloak to TideCloak
|
|
10
|
+
- Migrating from Auth0, Okta, or any other OIDC-compliant provider
|
|
11
|
+
- Want distributed key signing, zero-knowledge passwords, or quorum governance without rewriting auth flows
|
|
12
|
+
|
|
13
|
+
**Do not use** if starting a greenfield project. See [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) instead.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## From Keycloak
|
|
18
|
+
|
|
19
|
+
Keycloak to TideCloak is the simplest path. TideCloak uses the same admin console, same OIDC endpoints, and same SDK surface.
|
|
20
|
+
|
|
21
|
+
### Steps
|
|
22
|
+
|
|
23
|
+
1. **Deploy TideCloak** in place of (or alongside) your Keycloak instance.
|
|
24
|
+
2. **Download the new adapter config** (`tidecloak.json`) from the TideCloak admin console:
|
|
25
|
+
- Clients -> {your-client} -> Installation -> Keycloak OIDC JSON
|
|
26
|
+
3. **Replace `keycloak.json` with `tidecloak.json`** in your application:
|
|
27
|
+
```bash
|
|
28
|
+
# Backup existing config
|
|
29
|
+
cp data/keycloak.json data/keycloak.json.bak
|
|
30
|
+
|
|
31
|
+
# Replace with TideCloak adapter
|
|
32
|
+
cp tidecloak.json data/keycloak.json
|
|
33
|
+
# Or rename to tidecloak.json and update your config loader path
|
|
34
|
+
```
|
|
35
|
+
4. **No code changes needed.** Same SDK, same OIDC protocol. The application does not need to know it is talking to TideCloak instead of Keycloak.
|
|
36
|
+
|
|
37
|
+
### What to verify after swap
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Confirm discovery endpoint responds
|
|
41
|
+
curl -s http://localhost:8080/realms/{realm}/.well-known/openid-configuration | jq .issuer
|
|
42
|
+
|
|
43
|
+
# Confirm JWKS endpoint responds
|
|
44
|
+
curl -s http://localhost:8080/realms/{realm}/protocol/openid-connect/certs | jq .keys[0].kty
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## From Other OIDC Providers (Auth0, Okta, etc.)
|
|
50
|
+
|
|
51
|
+
Any application using standard OIDC can point to TideCloak by updating configuration values. No TideCloak-specific SDK is required for basic authentication.
|
|
52
|
+
|
|
53
|
+
### Steps
|
|
54
|
+
|
|
55
|
+
1. **Deploy TideCloak.**
|
|
56
|
+
2. **Create a realm and client** in TideCloak matching your existing client configuration (redirect URIs, scopes, grant types).
|
|
57
|
+
3. **Update your application's OIDC configuration:**
|
|
58
|
+
|
|
59
|
+
| Setting | Old value (example: Auth0) | New value (TideCloak) |
|
|
60
|
+
|---------|---------------------------|----------------------|
|
|
61
|
+
| Discovery endpoint | `https://tenant.auth0.com/.well-known/openid-configuration` | `http://localhost:8080/realms/{realm}/.well-known/openid-configuration` |
|
|
62
|
+
| Issuer URL | `https://tenant.auth0.com/` | `http://localhost:8080/realms/{realm}` |
|
|
63
|
+
| Client ID | Your Auth0 client ID | Your TideCloak client ID |
|
|
64
|
+
| Client secret (if confidential) | Your Auth0 client secret | Your TideCloak client secret |
|
|
65
|
+
|
|
66
|
+
4. **Standard OIDC -- no TideCloak SDK required for basic auth.** Your existing OIDC library (e.g., `openid-client`, `next-auth` with generic provider, `passport-openidconnect`) works without changes beyond the config values above.
|
|
67
|
+
5. **Add TideCloak SDK only if you need Tide-specific features:**
|
|
68
|
+
```bash
|
|
69
|
+
npm install @tidecloak/js
|
|
70
|
+
# or
|
|
71
|
+
npm install @tidecloak/react
|
|
72
|
+
```
|
|
73
|
+
The SDK is required for E2EE features (`doEncrypt()` / `doDecrypt()`) and direct enclave interactions. It is not required for login, logout, or token verification.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## What Stays the Same
|
|
78
|
+
|
|
79
|
+
These are standard OIDC behaviors. TideCloak does not change them:
|
|
80
|
+
|
|
81
|
+
- **OIDC/OAuth 2.0 flows** -- Authorization Code, PKCE, Client Credentials all work identically.
|
|
82
|
+
- **JWT format and claims structure** -- Access tokens are standard JWTs. No proprietary wrapper.
|
|
83
|
+
- **JWKS verification endpoint** -- `GET /realms/{realm}/protocol/openid-connect/certs` returns standard JWK set. Existing JWT verification code works without modification.
|
|
84
|
+
- **Role claim paths** -- `realm_access.roles` for realm roles, `resource_access.{client}.roles` for client roles. Same as Keycloak.
|
|
85
|
+
- **Redirect URI patterns** -- Same configuration, same behavior.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## What You Gain
|
|
90
|
+
|
|
91
|
+
These improvements are invisible to the application. No code changes required to benefit:
|
|
92
|
+
|
|
93
|
+
| Feature | What it means |
|
|
94
|
+
|---------|--------------|
|
|
95
|
+
| **VVK threshold signing** | JWTs are signed by a distributed Vendor Verification Key. No single signing key exists to steal. Compromise of one node does not compromise tokens. |
|
|
96
|
+
| **Zero-knowledge passwords** | User passwords are never stored as hashes. The server never sees the plaintext password. Credential database breaches yield nothing usable. |
|
|
97
|
+
| **Quorum governance** | Admin changes (role assignments, policy updates) require multiple admin approvals before taking effect. Single compromised admin cannot unilaterally escalate privileges. |
|
|
98
|
+
| **Optional E2EE** | `doEncrypt()` / `doDecrypt()` available via TideCloak SDK for end-to-end encrypted data fields. Requires `@tidecloak/js` or `@tidecloak/react`. |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Verification Checklist
|
|
103
|
+
|
|
104
|
+
### Discovery and Tokens
|
|
105
|
+
|
|
106
|
+
- [ ] `GET /realms/{realm}/.well-known/openid-configuration` returns valid JSON with correct `issuer`
|
|
107
|
+
- [ ] `GET /realms/{realm}/protocol/openid-connect/certs` returns JWKS with at least one key
|
|
108
|
+
- [ ] Application obtains access token via Authorization Code flow
|
|
109
|
+
- [ ] Access token decodes to standard JWT with expected claims (`sub`, `realm_access`, `iss`)
|
|
110
|
+
|
|
111
|
+
### Login and Logout
|
|
112
|
+
|
|
113
|
+
- [ ] Login redirects to TideCloak login page (not old provider)
|
|
114
|
+
- [ ] Successful login redirects back to application with valid tokens
|
|
115
|
+
- [ ] Logout clears session and redirects correctly
|
|
116
|
+
- [ ] Silent token refresh works (no forced re-login after token expiry)
|
|
117
|
+
|
|
118
|
+
### JWT Verification
|
|
119
|
+
|
|
120
|
+
- [ ] Existing server-side JWT verification code accepts TideCloak tokens without modification
|
|
121
|
+
- [ ] `iss` claim matches the new TideCloak issuer URL
|
|
122
|
+
- [ ] Role claims at `realm_access.roles` are populated correctly
|
|
123
|
+
|
|
124
|
+
### No Residual Old Auth
|
|
125
|
+
|
|
126
|
+
- [ ] No requests to old provider endpoints in browser network tab
|
|
127
|
+
- [ ] No old provider cookies or tokens in browser storage
|
|
128
|
+
- [ ] No old provider SDKs still loaded in the application bundle
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Common Failures
|
|
133
|
+
|
|
134
|
+
### Issuer Mismatch
|
|
135
|
+
|
|
136
|
+
**Symptom**: JWT verification fails. Error message mentions issuer validation.
|
|
137
|
+
|
|
138
|
+
**Cause**: Application still expects the old provider's issuer URL (e.g., `https://tenant.auth0.com/`) but receives TideCloak's issuer (`http://localhost:8080/realms/myrealm`).
|
|
139
|
+
|
|
140
|
+
**Fix**: Update the expected issuer in your JWT verification configuration to match TideCloak's issuer URL exactly. Check trailing slashes.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### CORS Errors After Switch
|
|
145
|
+
|
|
146
|
+
**Symptom**: Browser console shows CORS errors on token or JWKS requests.
|
|
147
|
+
|
|
148
|
+
**Cause**: TideCloak's Web Origins configuration does not include your application's origin.
|
|
149
|
+
|
|
150
|
+
**Fix**: In TideCloak admin console: Clients -> {your-client} -> Settings -> Web Origins. Add your application origin (e.g., `http://localhost:3000`).
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Redirect URI Mismatch
|
|
155
|
+
|
|
156
|
+
**Symptom**: Login fails with "Invalid redirect_uri" error on TideCloak login page.
|
|
157
|
+
|
|
158
|
+
**Cause**: The redirect URI your application sends does not match any URI registered in TideCloak.
|
|
159
|
+
|
|
160
|
+
**Fix**: In TideCloak admin console: Clients -> {your-client} -> Settings -> Valid Redirect URIs. Add all URIs your application uses (including `http://localhost:*` for development).
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### Old Provider Tokens Cached
|
|
165
|
+
|
|
166
|
+
**Symptom**: Application appears logged in but API calls fail with 401. Or infinite redirect loop.
|
|
167
|
+
|
|
168
|
+
**Cause**: Browser still holds tokens or cookies from the old provider.
|
|
169
|
+
|
|
170
|
+
**Fix**: Clear site data in browser DevTools (Application -> Storage -> Clear site data). Test in incognito window for a clean session.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### Client Secret Not Configured (Confidential Clients)
|
|
175
|
+
|
|
176
|
+
**Symptom**: Token exchange fails with 401 from TideCloak token endpoint.
|
|
177
|
+
|
|
178
|
+
**Cause**: Confidential client in TideCloak does not have the client secret configured, or the application is sending the old provider's secret.
|
|
179
|
+
|
|
180
|
+
**Fix**: In TideCloak admin console: Clients -> {your-client} -> Credentials. Copy the secret and update your application's configuration.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### Role Claims Missing or Different Path
|
|
185
|
+
|
|
186
|
+
**Symptom**: Application cannot find user roles after migration.
|
|
187
|
+
|
|
188
|
+
**Cause**: Old provider used a custom claim path (e.g., Auth0 namespaced claims like `https://myapp.com/roles`). TideCloak uses standard Keycloak paths.
|
|
189
|
+
|
|
190
|
+
**Fix**: Update role extraction code to read from `realm_access.roles` (realm roles) or `resource_access.{client}.roles` (client roles). If your application hardcodes a custom claim namespace, replace it.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## References
|
|
195
|
+
|
|
196
|
+
- Source: SDK documentation, operational exemplars
|
|
197
|
+
- Keycloak migration: same admin console, same OIDC endpoints, config swap only
|
|
198
|
+
- Generic OIDC migration: config-only change, no SDK required for basic auth
|