@tidecloak/js 0.13.1 → 0.13.5

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.
Files changed (48) hide show
  1. package/README.md +170 -5
  2. package/dist/cjs/lib/tidecloak.js +1759 -1629
  3. package/dist/cjs/lib/tidecloak.js.map +1 -1
  4. package/dist/cjs/src/IAMService.js +526 -32
  5. package/dist/cjs/src/IAMService.js.map +1 -1
  6. package/dist/cjs/src/index.js +4 -21
  7. package/dist/cjs/src/index.js.map +1 -1
  8. package/dist/cjs/src/policy-react.js +3 -0
  9. package/dist/cjs/src/policy-react.js.map +1 -0
  10. package/dist/cjs/src/policy.css +1 -0
  11. package/dist/cjs/src/utils/fetch.js +36 -0
  12. package/dist/cjs/src/utils/fetch.js.map +1 -0
  13. package/dist/cjs/src/utils/index.js +3 -0
  14. package/dist/cjs/src/utils/index.js.map +1 -0
  15. package/dist/cjs/src/utils/pkce.js +43 -0
  16. package/dist/cjs/src/utils/pkce.js.map +1 -0
  17. package/dist/esm/lib/tidecloak.js +1760 -1619
  18. package/dist/esm/lib/tidecloak.js.map +1 -1
  19. package/dist/esm/src/IAMService.js +523 -23
  20. package/dist/esm/src/IAMService.js.map +1 -1
  21. package/dist/esm/src/index.js +2 -6
  22. package/dist/esm/src/index.js.map +1 -1
  23. package/dist/esm/src/policy-react.js +3 -0
  24. package/dist/esm/src/policy-react.js.map +1 -0
  25. package/dist/esm/src/policy.css +1 -0
  26. package/dist/esm/src/utils/fetch.js +36 -0
  27. package/dist/esm/src/utils/fetch.js.map +1 -0
  28. package/dist/esm/src/utils/index.js +3 -0
  29. package/dist/esm/src/utils/index.js.map +1 -0
  30. package/dist/esm/src/utils/pkce.js +43 -0
  31. package/dist/esm/src/utils/pkce.js.map +1 -0
  32. package/dist/types/IAMService.d.ts +328 -0
  33. package/dist/types/index.d.ts +3 -0
  34. package/dist/types/lib/tidecloak.d.ts +325 -31
  35. package/dist/types/policy-react.d.ts +1 -0
  36. package/dist/types/src/IAMService.d.ts +245 -23
  37. package/dist/types/src/index.d.ts +2 -2
  38. package/dist/types/src/policy-react.d.ts +1 -0
  39. package/dist/types/src/utils/fetch.d.ts +11 -0
  40. package/dist/types/src/utils/index.d.ts +2 -0
  41. package/dist/types/src/utils/pkce.d.ts +24 -0
  42. package/dist/types/utils/fetch.d.ts +11 -0
  43. package/dist/types/utils/index.d.ts +2 -0
  44. package/dist/types/utils/pkce.d.ts +24 -0
  45. package/package.json +18 -29
  46. package/scripts/postinstall.cjs +36 -0
  47. package/silent-check-sso.html +1 -0
  48. package/scripts/postinstall.js +0 -43
package/README.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Lightweight browser SDK for integrating TideCloak SSO into any JavaScript application-vanilla, SPA, or framework-agnostic.
4
4
 
5
+ ## Authentication Modes
6
+
7
+ The SDK supports two authentication modes:
8
+
9
+ | Mode | Description | Use Case |
10
+ |------|-------------|----------|
11
+ | **Front-channel** | Browser handles all token operations (standard OIDC) | SPAs, simple apps |
12
+ | **Hybrid/BFF** | Browser handles PKCE, backend exchanges code for tokens | Secure apps, server-side sessions |
13
+
5
14
  ---
6
15
 
7
16
  ## 1. Prerequisites
@@ -171,7 +180,163 @@ If you override the `redirectUri` in `initIAM`, make sure to **update the corres
171
180
 
172
181
  ---
173
182
 
174
- ## 6. Encrypting & Decrypting Data
183
+ ## 6. Hybrid/BFF Mode (Backend-For-Frontend)
184
+
185
+ In hybrid mode, the browser generates PKCE and redirects to the IdP, but the **backend exchanges the authorization code for tokens**. This keeps tokens server-side for improved security—ideal for applications with server-rendered pages or strict security requirements.
186
+
187
+ ### How It Works
188
+
189
+ 1. **Login Page**: User clicks login → `doLogin()` generates PKCE, stores verifier in sessionStorage, redirects to IdP
190
+ 2. **IdP**: User authenticates
191
+ 3. **Callback Page**: IdP redirects back with `?code=...` → `initIAM()` sends code + verifier to your backend
192
+ 4. **Backend**: Exchanges code for tokens, creates session cookie
193
+ 5. **Success**: User is redirected to their original destination
194
+
195
+ ### Configuration
196
+
197
+ ```js
198
+ const hybridConfig = {
199
+ authMode: "hybrid",
200
+ oidc: {
201
+ authorizationEndpoint: "https://auth.example.com/realms/myrealm/protocol/openid-connect/auth",
202
+ clientId: "my-client",
203
+ redirectUri: "https://app.example.com/auth/callback",
204
+ scope: "openid profile email", // optional, defaults to "openid profile email"
205
+ prompt: "login" // optional
206
+ },
207
+ tokenExchange: {
208
+ endpoint: "/api/authenticate", // Your backend endpoint
209
+ provider: "tidecloak-auth", // optional, sent to backend
210
+ headers: () => ({ // optional, custom headers (e.g., CSRF token)
211
+ "anti-csrf-token": document.querySelector('meta[name="csrf-token"]')?.content
212
+ })
213
+ }
214
+ };
215
+ ```
216
+
217
+ ### Login Page Example
218
+
219
+ ```js
220
+ import { IAMService } from "@tidecloak/js";
221
+
222
+ // Define config (or import from shared file)
223
+ const hybridConfig = { /* ... */ };
224
+
225
+ // Load config on page load
226
+ await IAMService.loadConfig(hybridConfig);
227
+
228
+ // Trigger login when user clicks button
229
+ document.getElementById("login-btn").onclick = () => {
230
+ const returnUrl = new URLSearchParams(window.location.search).get("return") || "/";
231
+ IAMService.doLogin(returnUrl); // returnUrl is where user goes after successful auth
232
+ };
233
+ ```
234
+
235
+ ### Callback Page Example
236
+
237
+ ```js
238
+ import { IAMService } from "@tidecloak/js";
239
+
240
+ const hybridConfig = { /* same config as login page */ };
241
+
242
+ // initIAM automatically detects the callback (code in URL) and handles token exchange
243
+ const authenticated = await IAMService.initIAM(hybridConfig);
244
+
245
+ if (authenticated) {
246
+ // Success - redirect to original destination
247
+ const returnUrl = IAMService.getReturnUrl() || "/";
248
+ window.location.assign(returnUrl);
249
+ } else {
250
+ // Failed - show error or redirect to login
251
+ document.getElementById("error").textContent = "Login failed. Please try again.";
252
+ }
253
+ ```
254
+
255
+ ### Backend Token Exchange
256
+
257
+ Your backend receives a POST request to the configured `tokenExchange.endpoint`:
258
+
259
+ ```json
260
+ {
261
+ "accessToken": "{\"code\":\"AUTH_CODE\",\"code_verifier\":\"PKCE_VERIFIER\",\"redirect_uri\":\"https://app.example.com/auth/callback\"}",
262
+ "provider": "tidecloak-auth"
263
+ }
264
+ ```
265
+
266
+ Your backend should:
267
+ 1. Parse the `accessToken` JSON string
268
+ 2. Exchange the code with the IdP's token endpoint
269
+ 3. Create a session (e.g., set HTTP-only cookies)
270
+ 4. Return a success response
271
+
272
+ ### React Example
273
+
274
+ **LoginPage.tsx**
275
+ ```tsx
276
+ import { useEffect, useState } from "react";
277
+ import { IAMService } from "@tidecloak/js";
278
+ import { useLocation } from "react-router-dom";
279
+
280
+ const hybridConfig = { /* ... */ };
281
+
282
+ export function LoginPage() {
283
+ const [ready, setReady] = useState(false);
284
+ const location = useLocation();
285
+ const returnUrl = new URLSearchParams(location.search).get("return") || "/";
286
+
287
+ useEffect(() => {
288
+ IAMService.loadConfig(hybridConfig).then(() => setReady(true));
289
+ }, []);
290
+
291
+ return (
292
+ <button disabled={!ready} onClick={() => IAMService.doLogin(returnUrl)}>
293
+ Login with TideCloak
294
+ </button>
295
+ );
296
+ }
297
+ ```
298
+
299
+ **CallbackPage.tsx**
300
+ ```tsx
301
+ import { useEffect, useState } from "react";
302
+ import { IAMService } from "@tidecloak/js";
303
+
304
+ const hybridConfig = { /* same config */ };
305
+
306
+ export function CallbackPage() {
307
+ const [error, setError] = useState<string | null>(null);
308
+
309
+ useEffect(() => {
310
+ IAMService.initIAM(hybridConfig)
311
+ .then(authenticated => {
312
+ if (authenticated) {
313
+ window.location.assign(IAMService.getReturnUrl() || "/");
314
+ } else {
315
+ setError("Login failed");
316
+ }
317
+ })
318
+ .catch(err => setError(err.message));
319
+ }, []);
320
+
321
+ if (error) return <div>Error: {error}</div>;
322
+ return <div>Logging in...</div>;
323
+ }
324
+ ```
325
+
326
+ ### Hybrid Mode Limitations
327
+
328
+ In hybrid mode, tokens are server-side, so these methods will throw:
329
+ - `getToken()`, `getIDToken()`, `getTokenExp()`
330
+ - `getName()`, `hasRealmRole()`, `hasClientRole()`
331
+ - `getValueFromToken()`, `getValueFromIDToken()`
332
+ - `updateIAMToken()`, `forceUpdateToken()`
333
+ - `doEncrypt()`, `doDecrypt()`
334
+
335
+ Use `isLoggedIn()` and `getReturnUrl()` instead.
336
+
337
+ ---
338
+
339
+ ## 7. Encrypting & Decrypting Data (Front-channel Only)
175
340
 
176
341
  TideCloak lets you protect sensitive fields with **tag-based** encryption. You pass in an array of `{ data, tags }` objects and receive an array of encrypted strings (or vice versa for decryption).
177
342
 
@@ -280,7 +445,7 @@ async function decryptExamples(encryptedFields) {
280
445
 
281
446
  ---
282
447
 
283
- ## 7. Events & Lifecycle
448
+ ## 8. Events & Lifecycle
284
449
 
285
450
  Register handlers via `.on(event, handler)` or remove with `.off(event, handler)`:
286
451
 
@@ -303,9 +468,9 @@ IAMService
303
468
 
304
469
  ---
305
470
 
306
- ## 8. Core Methods
471
+ ## 9. Core Methods (Front-channel Only)
307
472
 
308
- After initialization, you can call these methods anywhere:
473
+ After initialization, you can call these methods anywhere (note: most are only available in front-channel mode):
309
474
 
310
475
  ```js
311
476
  // Check login state
@@ -342,7 +507,7 @@ await IAMService.doDecrypt([{ encrypted: "...", tags: ["tag1"] }]);
342
507
 
343
508
  ---
344
509
 
345
- ## 9. Tips & Best Practices
510
+ ## 10. Tips & Best Practices
346
511
 
347
512
  * **Single Init**: Call `initIAM` only once on page load or app bootstrap.
348
513
  * **Token Cookie**: `kcToken` is set automatically; ensure server-side middleware reads this cookie.