Skip to main content

How-to Guide: Common Tasks with TideCloak in Vanilla JS

Quick, copy-paste snippets for everyday tasks using @tidecloak/js.


Install​

npm install @tidecloak/js

Ensure public/silent-check-sso.html exists (see tutorial) and place your adapter at ./tidecloak.json.


Initialize IAM​

import { IAMService } from "@tidecloak/js";
import config from "./tidecloak.json";
await IAMService.initIAM(config);
// or override redirect:
await IAMService.initIAM({ ...config, redirectUri: "https://your.app/auth/callback" });

Default redirect: ${window.location.origin}/auth/redirect → ensure that path exists.


DPoP (opt-in)​

DPoP binds the access token to a key held by this browser, so a copied token stops working. It is off unless you ask for it:

await IAMService.initIAM({ ...config, useDPoP: { mode: "strict" } });

Turning it on changes the token. The realm issues one with typ: "DPoP" and cnf.jkt, and that token is rejected with a bare 401 if it is later sent as a plain Authorization: Bearer .... Use IAMService.secureFetch, which attaches the proof for you, and make sure your resource server validates it.

Your app also has to serve the DPoP verification page, which is how TideCloak confirms the browser holds the key. It has to come from your origin, because the key lives in your app's IndexedDB and nothing on another origin can read it.

The setup is the same as for React: fetch the page into public/, then serve it from a small Vite middleware in dev and from your host's header config in production. See serve the DPoP verification page for both, and DPoP and sender-constrained tokens for what the page actually does.

If the page is missing, logins still work but stall for about four seconds and fall back to a popup. That stall is the usual sign this is not set up.


Login / Logout​

IAMService.doLogin(); // redirect to SSO
IAMService.doLogout(); // clear and redirect

Tokens & Claims​

const isLogged = IAMService.isLoggedIn(); // boolean
const token = await IAMService.getToken(); // access token (string)
const idToken = IAMService.getIDToken(); // ID token (string)
const exp = IAMService.getTokenExp(); // seconds since epoch
const username = IAMService.getName(); // preferred_username
const email = IAMService.getValueFromToken("email");
const sub = IAMService.getValueFromIDToken("sub");

Role Checks​

IAMService.hasRealmRole("admin"); // boolean
IAMService.hasClientRole("editor"); // boolean (defaults to your app client)

Token Refresh​

await IAMService.updateIAMToken(); // try to refresh if needed
await IAMService.forceUpdateToken(); // force refresh attempt

Events​

const onReady = (auth) => console.log("Ready, logged in:", auth);
IAMService.on("ready", onReady);
// Later (SPA cleanup):
IAMService.off("ready", onReady);

Common events:

EventWhen it fires
readyInitial silent SSO finished (true/false)
authSuccessInteractive login success
authErrorInteractive login failed
authRefreshSuccessSilent token refresh succeeded
authRefreshErrorSilent token refresh failed
logoutUser logged out
tokenExpiredToken expired before refresh

Encrypt / Decrypt (E2EE)​

Requires roles per tag: _tide_<tag>.selfencrypt / _tide_<tag>.selfdecrypt

// Encrypt string values:
const [encDob] = await IAMService.doEncrypt([
{ data: "2005-03-04", tags: ["dob"] }
]);
// Decrypt back:
const [dob] = await IAMService.doDecrypt([
{ encrypted: encDob, tags: ["dob"] }
]);
// Multi-field example:
const encrypted = await IAMService.doEncrypt([
{ data: "10 Smith Street", tags: ["street"] },
{ data: "Southport", tags: ["suburb"] },
{ data: "20 James Street - Burleigh Heads", tags: ["street", "suburb"] }
]);
const decrypted = await IAMService.doDecrypt([
{ encrypted: encrypted[0], tags: ["street"] },
{ encrypted: encrypted[1], tags: ["suburb"] },
{ encrypted: encrypted[2], tags: ["street", "suburb"] }
]);

data must be string or Uint8Array. Output order matches input order.


Protecting Backend APIs​

Send the access token as a bearer:

const token = await IAMService.getToken();
const res = await fetch("/api/secure", {
headers: { Authorization: `Bearer ${token}` }
});

Verify the JWT in your backend (Node, Go, etc.) using your realm's JWKS.