SPA Frontend
Installing keycloak-js
Section titled “Installing keycloak-js”keycloak-js is the official browser-side adapter for Keycloak. It handles the Authorization Code + PKCE flow, token storage, silent refresh, and logout — all without you managing redirect URLs or token exchanges by hand.
Install it from npm:
npm install keycloak-jsThe package ships its own TypeScript types, so no separate @types package is needed.
Creating the Keycloak instance
Section titled “Creating the Keycloak instance”Pass your realm’s URL, your realm name, and your client ID. These three values are the minimum required to identify your application to Keycloak:
import Keycloak from 'keycloak-js';
const keycloak = new Keycloak({
url: 'http://localhost:8080',
realm: 'my-app',
clientId: 'my-app-frontend',
});
keycloak
.init({ onLoad: 'login-required', pkceMethod: 'S256' })
.then((authenticated) => {
if (authenticated) {
console.log('Logged in as', keycloak.tokenParsed?.preferred_username);
startApp();
}
});
function startApp() {
// Your app bootstrap goes here.
// keycloak.token is available from this point on.
}Key points:
onLoad: 'login-required'redirects the user to Keycloak immediately if they are not yet authenticated. Use'check-sso'if you want the page to be accessible without login and only show a login button.pkceMethod: 'S256'enables PKCE (Proof Key for Code Exchange). This is mandatory for public clients (SPAs) because they cannot store a client secret securely. PKCE replaces the secret with a per-request code challenge.
Calling a protected API
Section titled “Calling a protected API”After init resolves with authenticated: true, keycloak.token holds the raw JWT string. Attach it as a Bearer token in every API request:
async function fetchProfile() {
await keycloak.updateToken(30); // refresh if expiring in < 30 seconds
const response = await fetch('https://api.example.com/profile', {
headers: {
Authorization: `Bearer ${keycloak.token}`,
},
});
return response.json();
}updateToken(minValidity) checks whether the current token will expire within minValidity seconds and, if so, uses the refresh token to silently obtain a new one. Always call it before attaching keycloak.token to a request so you never send an expired JWT.
Reading token claims
Section titled “Reading token claims”The decoded payload is available in keycloak.tokenParsed. Common claims you will use:
keycloak.tokenParsed?.preferred_username // usernamekeycloak.tokenParsed?.email // email addresskeycloak.tokenParsed?.realm_access?.roles // array of realm roleskeycloak.tokenParsed?.resource_access?.['my-app-frontend']?.roles // client roles