React Quick Reference (TideCloak)
A concise, copy‑paste friendly reference for integrating TideCloak into a React app (Vite or CRA). It combines the essentials from the Getting Started and React SDK guides.
Prerequisites
- Docker and Node.js (>= 18.17) installed
- A running TideCloak dev server (see below)
- A realm with the Tide IdP added and license activated
- A registered client in your realm
- The adapter JSON for your client (downloaded from the TideCloak Admin Console)
To spin up TideCloak quickly:
sudo docker run > -d > -v .:/opt/keycloak/data/h2 > -p 8080:8080 > -e KC_BOOTSTRAP_ADMIN_USERNAME=admin > -e KC_BOOTSTRAP_ADMIN_PASSWORD=password > tideorg/tidecloak-dev:latest
1) Activate your license (dev/free)
- Open the Admin console and navigate to your realm:
http://localhost:8080/admin/master/console/#/myrealm/identity-providers/tide/tide/settings
- Manage License → Request License and complete the flow.
This connects your host to the Tide Cybersecurity Fabric. (Free dev tier available.)
2) Create a React app & install the SDK
Vite (TypeScript)
npm create vite@latest tidecloak-react -- --template react-ts
cd tidecloak-react
npm install @tidecloak/react
CRA works too; the SDK usage is the same.
3) Export your adapter JSON
From Admin Console → Clients → your client → Actions → Download adapter configs
Save as tidecloakAdapter.json
in your React project root.
Also ensure (for local dev):
- Valid Redirect URIs:
http://localhost:5173/*
- Web Origins:
http://localhost:5173
4) Silent SSO helper (required)
Create public/silent-check-sso.html
(or confirm the SDK added it).
<html>
<body>
<script>parent.postMessage(location.href, location.origin)</script>
</body>
</html>
5) Initialize the provider
Wrap your app in TideCloakContextProvider
. Below is a minimal router‑free example; add React Router if you prefer.
src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { TideCloakContextProvider, useTideCloak, Authenticated, Unauthenticated } from '@tidecloak/react';
import adapter from '../tidecloakAdapter.json';
import './index.css';
function UserInfo() {
const { logout, getValueFromIdToken, hasRealmRole } = useTideCloak();
const username = getValueFromIdToken('preferred_username') ?? '...';
const hasDefault = hasRealmRole('default-roles-myrealm');
return (
<div>
<p>Signed in as <b>{username}</b></p>
<p>Has Default Roles? <b>{hasDefault ? 'Yes' : 'No'}</b></p>
<button onClick={logout}>Logout</button>
</div>
);
}
function Welcome() {
const { login } = useTideCloak();
return (
<div>
<h1>Hello!</h1>
<p>Please authenticate yourself.</p>
<button onClick={login}>Login</button>
</div>
);
}
createRoot(document.getElementById('root')!).render(
<StrictMode>
<TideCloakContextProvider config={adapter}>
<Authenticated><UserInfo /></Authenticated>
<Unauthenticated><Welcome /></Unauthenticated>
</TideCloakContextProvider>
</StrictMode>,
);
6) Redirect URI (default vs custom)
By default, the SDK uses:
`${window.location.origin}/auth/redirect`
If you keep this default, create a route/page at /auth/redirect
that checks auth state and forwards the user:
// src/pages/auth/RedirectPage.tsx (example with React Router)
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTideCloak } from '@tidecloak/react';
export default function RedirectPage() {
const { authenticated, isInitializing, logout } = useTideCloak();
const navigate = useNavigate();
useEffect(() => {
const params = new URLSearchParams(window.location.search);
if (params.get('auth') === 'failed') {
sessionStorage.setItem('tokenExpired', 'true');
logout();
}
}, []);
useEffect(() => {
if (!isInitializing) {
navigate(authenticated ? '/home' : '/');
}
}, [authenticated, isInitializing, navigate]);
return <p style={{textAlign:'center'}}>Waiting for authentication...</p>;
}
Or override it:
<TideCloakContextProvider config={{ ...adapter, redirectUri: 'https://yourapp.com/auth/callback' }}>
{/* app */}
</TideCloakContextProvider>
Important: Whatever path you use for
redirectUri
must exist in your app/router.
7) Read tokens & roles
import { useTideCloak } from '@tidecloak/react';
function Header() {
const {
authenticated, login, logout,
token, tokenExp, refreshToken,
getValueFromToken, getValueFromIdToken,
hasRealmRole, hasClientRole,
} = useTideCloak();
return (
<header>
{authenticated ? (
<>
<span>Logged in</span>
<button onClick={logout}>Log Out</button>
</>
) : (
<button onClick={login}>Log In</button>
)}
{token && <small>Exp: {new Date(tokenExp * 1000).toLocaleTimeString()}</small>}
</header>
);
}
hasRealmRole('admin')
hasClientRole('editor', 'backoffice-client')
8) E2EE helpers (encrypt/decrypt)
import { useTideCloak } from '@tidecloak/react';
const { doEncrypt, doDecrypt } = useTideCloak();
// Encrypt
const encrypted = await doEncrypt([
{ data: 'Sensitive Information', tags: ['private'] }
]);
// Decrypt
const decrypted = await doDecrypt([
{ encrypted: encrypted[0], tags: ['private'] }
]);
Rules
data
must be a string or Uint8Array.- Permissions:
- Encrypt →
_tide_<tag>.selfencrypt
- Decrypt →
_tide_<tag>.selfdecrypt
The output preserves input order.
9) Guard components
import { Authenticated, Unauthenticated } from '@tidecloak/react';
export default function Dashboard() {
return (
<>
<Authenticated><h1>Dashboard</h1></Authenticated>
<Unauthenticated><p>Please log in.</p></Unauthenticated>
</>
);
}
10) Troubleshooting
- After login the app "breaks" → You're missing the redirect route (
/auth/redirect
) or you overroderedirectUri
to a non‑existent path. - Silent SSO issues → Ensure
public/silent-check-sso.html
exists with the snippet above. - E2EE errors → You passed an object to
data
instead of a string/bytes, or the token lacks the required_tide_<tag>
roles. - Tokens not refreshing → Auto‑refresh is built‑in; you can force with
await refreshToken()
.
11) Dev recap
- Deployed TideCloak Dev via Docker and activated license
- Registered a client and downloaded adapter JSON
- Wrapped your React app with TideCloak provider
- Implemented login/logout, role checks, and optional E2EE
Happy building! 🚀