@tidecloak/js 0.12.47 → 0.13.2
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/README.md +170 -5
- package/dist/cjs/src/IAMService.js +522 -22
- package/dist/cjs/src/IAMService.js.map +1 -1
- package/dist/cjs/src/utils/fetch.js +36 -0
- package/dist/cjs/src/utils/fetch.js.map +1 -0
- package/dist/cjs/src/utils/index.js +3 -0
- package/dist/cjs/src/utils/index.js.map +1 -0
- package/dist/cjs/src/utils/pkce.js +43 -0
- package/dist/cjs/src/utils/pkce.js.map +1 -0
- package/dist/esm/src/IAMService.js +522 -22
- package/dist/esm/src/IAMService.js.map +1 -1
- package/dist/esm/src/utils/fetch.js +36 -0
- package/dist/esm/src/utils/fetch.js.map +1 -0
- package/dist/esm/src/utils/index.js +3 -0
- package/dist/esm/src/utils/index.js.map +1 -0
- package/dist/esm/src/utils/pkce.js +43 -0
- package/dist/esm/src/utils/pkce.js.map +1 -0
- package/dist/types/IAMService.d.ts +241 -19
- package/dist/types/src/IAMService.d.ts +246 -23
- package/dist/types/src/utils/fetch.d.ts +11 -0
- package/dist/types/src/utils/index.d.ts +2 -0
- package/dist/types/src/utils/pkce.d.ts +24 -0
- package/dist/types/utils/fetch.d.ts +11 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/pkce.d.ts +24 -0
- package/package.json +2 -2
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.
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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.
|