### Start TanStack Router Example with oidc-spa Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/tanstack-router-start/tanstack-start.md Clones the TanStack Start example from GitHub, installs dependencies, and runs the development server. This command initializes a project configured for oidc-spa. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/tanstack-start start-oidc cd start-oidc npm install npm run dev # By default, the example runs against Keycloak. # You can edit the .env file to test other providers. ``` -------------------------------- ### Clone and Run Basic Angular oidc-spa Example Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Clones the basic oidc-spa Angular example using gitpick, installs dependencies, and starts the development server. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/angular oidc-spa-angular cd oidc-spa-angular npm install npm run start ``` -------------------------------- ### Project Setup with npx gitpick Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/next.js.md Initializes a new Next.js project with oidc-spa example code using npx gitpick. This command clones the example repository, sets up the project directory, copies environment variables, installs dependencies, and starts the development server. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/next oidc-spa-next cd oidc-spa-next cp .env.local.sample .env.local npm install npm run dev ``` -------------------------------- ### Setup React Router Framework OIDC Example (Bash) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/react-router.md This command-line snippet demonstrates how to clone and set up the 'rr-framework-oidc' example project from keycloakify/oidc-spa. It includes steps for installing dependencies, configuring environment variables, and running the development server. The example utilizes preconfigured test accounts for Keycloak, Auth0, or Google OAuth. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/react-router-framework rr-framework-oidc cd rr-framework-oidc # You can use our preconfigured Keycloak, Auth0, or Google OAuth test accounts cp .env.local.sample .env.local npm install npm run dev # Start exploring with: src/oidc.ts ``` -------------------------------- ### Clone and Run Advanced Angular oidc-spa Example Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Clones the advanced oidc-spa Angular kitchensink example using gitpick, installs dependencies, and starts the development server. This example demonstrates features like token validation and role-based access control. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/angular-kitchensink oidc-spa-angular-kitchensink cd oidc-spa-angular-kitchensink npm install npm run start ``` -------------------------------- ### Clone and Run TanStack Router Example with oidc-spa Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/tanstack-router-start/react-router.md This command sequence clones a TanStack Router example project that is preconfigured with oidc-spa. It then navigates into the project directory, copies environment variables, installs dependencies, and starts the development server. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/tanstack-router-file-router tr-oidc cd tr-oidc # You can use our preconfigured Keycloak, Auth0, or Google OAuth test accounts cp .env.local.sample .env.local npm install npm run dev # Start exploring with: src/oidc.ts ``` -------------------------------- ### Clone and Run React Router Declarative Example Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/react-router.md This command clones a React Router declarative mode example using `gitpick`. It guides you through setting up environment variables, installing dependencies, and running the development server, starting exploration from `src/oidc.ts`. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/react-router-declarative rr-declarative-oidc cd rr-declarative-oidc # You can use our preconfigured Keycloak, Auth0, or Google OAuth test accounts cp .env.local.sample .env.local npm install npm run dev # Start exploring with: src/oidc.ts ``` -------------------------------- ### Test oidc-spa Google Integration Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/providers-configuration/google-oauth.md This bash script demonstrates how to set up and run a project to test the oidc-spa integration with Google OAuth. It involves cloning an example project, configuring environment variables, installing dependencies, and starting the development server. ```bash npx degit https://github.com/keycloakify/oidc-spa/examples/tanstack-router-file-based oidc-spa-tanstack-router cd oidc-spa-tanstack-router cp .env.local.sample .env.local # Edit .env.local, uncomment the Google section and comment the Keycloak section # replace the values by your own. yarn yarn dev ``` -------------------------------- ### Clone and Run React Router Data Mode Example Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/react-router.md This command clones a React Router data mode example using `gitpick`. It provides instructions for setting up environment variables, installing dependencies, and starting the development server, with guidance to begin exploring in `src/oidc.ts`. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/react-router-data rr-data-oidc cd rr-data-oidc # You can use our preconfigured Keycloak, Auth0, or Google OAuth test accounts cp .env.local.sample .env.local npm install npm run dev # Start exploring with: src/oidc.ts ``` -------------------------------- ### Install oidc-spa and zod in Angular (bun) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Installs the oidc-spa and zod libraries using bun. Zod is optional but recommended for input validation. ```bash bun add oidc-spa zod ``` -------------------------------- ### Manual Setup for Security Features (Easy) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/resources/migrating-from-keycloak-js.md This is a simplified manual setup for projects not using Vite and where modifying the entry file is not feasible. It involves calling `oidcEarlyInit` within the same module as the `Keycloak` initialization. Note that this approach offers a reduced security posture compared to the other methods and might conflict with certain routing libraries. It requires importing modules from 'oidc-spa/entrypoint', 'oidc-spa/browser-runtime-freeze', and 'oidc-spa/DPoP'. ```typescript import { Keycloak } from "oidc-spa/keycloak-js"; import { oidcEarlyInit } from "oidc-spa/entrypoint"; import { browserRuntimeFreeze } from 'oidc-spa/browser-runtime-freeze'; import { DPoP } from 'oidc-spa/DPoP'; // Should run as early as possible. oidcEarlyInit({ BASE_URL: "/" // The path where your app is hosted // If applicable you should use `process.env.PUBLIC_URL` // or `import.meta.env.BASE_URL`. // This is not an option. There's only one good answer. securityDefenses: { // See: https://docs.oidc-spa.dev/v/v10/security-features/browser-runtime-freeze ...browserRuntimeFreeze({ //excludes: [ "fetch", "XMLHttpRequest" ] }), // See: https://docs.oidc-spa.dev/v/v10/security-features/dpop ...DPoP({ mode: 'auto' }) } }); const keycloak = new Keycloak({ /* ... */ }); ``` -------------------------------- ### Initialize oidc-spa project with Nuxt Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/nuxt.md Commands to scaffold a new Nuxt SPA project using the oidc-spa example template and install necessary dependencies. ```bash npx gitpick keycloakify/oidc-spa/tree/main/examples/nuxt-spa oidc-spa-nuxt-spa cd oidc-spa-nuxt-spa cp .env.local.sample .env.local yarn install yarn dev ``` -------------------------------- ### Install oidc-spa dependencies Source: https://context7.com/keycloakify/docs.oidc-spa.dev/llms.txt Command to install the oidc-spa library and the required zod dependency for schema validation. ```bash npm install oidc-spa zod ``` -------------------------------- ### Install oidc-spa and zod in Angular (npm) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Installs the oidc-spa and zod libraries using npm. Zod is optional but recommended for input validation. ```bash npm install oidc-spa zod ``` -------------------------------- ### Display OIDC Initialization Errors in TanStack Start Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/error-management/error-handling-with-autologin.md This example demonstrates integrating OIDC error handling within a TanStack Start application. It utilizes the `useOidc` hook to access `oidcInitializationError` and conditionally renders an `OidcErrorComponent` to inform the user about authentication issues. ```tsx import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"; import Header from "@/components/Header"; import { AutoLogoutWarningOverlay } from "@/components/AutoLogoutWarningOverlay"; import { useOidc } from "@/oidc"; import type { OidcInitializationError } from "oidc-spa/core"; export const Route = createRootRoute({ // ... shellComponent: RootDocument }); function RootDocument({ children }: { children: React.ReactNode }) { const { oidcInitializationError } = useOidc(); return (
{oidcInitializationError ? ( ) : ( children )}
); } function OidcErrorComponent(props: { oidcInitializationError: OidcInitializationError; }){ const { oidcInitializationError } = props; // Distinguish misconfiguration vs. temporary auth-server outage. console.log(oidcInitializationError.isAuthServerLikelyDown); // Developer-only diagnostic with likely cause and fix. // Do not display this to end users. console.log(oidcInitializationError.message); return

Our auth is down, sorry

; } ``` -------------------------------- ### Install oidc-spa and zod with npm, yarn, pnpm, or bun Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/tanstack-router-start/react-router.md These commands show how to install the 'oidc-spa' and 'zod' packages using different package managers. 'zod' is optional but recommended for data validation. ```bash npm install oidc-spa zod ``` ```bash yarn add oidc-spa zod ``` ```bash pnpm add oidc-spa zod ``` ```bash bun add oidc-spa zod ``` -------------------------------- ### Install oidc-spa and zod in Angular (pnpm) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Installs the oidc-spa and zod libraries using pnpm. Zod is optional but recommended for input validation. ```bash pnpm add oidc-spa zod ``` -------------------------------- ### Deno.serve API Handler with Authentication (TypeScript) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/backend-token-validation/deno.serve.md This snippet demonstrates a Deno.serve API handler in TypeScript. It sets up authentication using bootstrapAuth, retrieves user details with getUser, and handles GET requests for '/api/todos' and '/api/todos/:userId'. It includes error handling for invalid requests and unauthorized access. ```typescript import { bootstrapAuth, getUser } from "./auth.ts"; // See below bootstrapAuth({ implementation: "real", // or "mock", see: https://docs.oidc-spa.dev/v/v8/integration-guides/backend-token-validation/mock-modes issuerUri: Deno.env.get("OIDC_ISSUER_URI")!, expectedAudience: Deno.env.get("OIDC_AUDIENCE") ?? undefined }); Deno.serve(async (request: Request) => { const url = new URL(request.url); if (request.method === "GET" && url.pathname === "/api/todos") { const user = await getUser({ req: request }); // We got an exception, validation failed if (user instanceof Response) { const response = user; return response; } const json = await Deno.readTextFile( `todos_${user.id}.json` ); return new Response(json, { status: 200, headers: { "content-type": "application/json" } }); } /** * Support staff endpoint. * Example: GET /api/todos/1234 */ if (request.method === "GET" && url.pathname.startsWith("/api/todos/")) { let userId: string; try { userId = decodeURIComponent(url.pathname.replace("/api/todos/", "")); } catch { return new Response("bad request", { status: 400 }); } if (!userId || userId.includes("/")) { return new Response("bad request", { status: 400 }); } { // Will reject the request if user making the request // doesn't have "support-staff" role const user = await getUser({ req: request, requiredRole: "support-staff" }); // We got an exception, validation failed if (user instanceof Response) { const response = user; return response; } } const json = await Deno.readTextFile(`todos_${userId}.json`); return new Response(json, { status: 200, headers: { "content-type": "application/json" } }); } return new Response("not found", { status: 404 }); }); ``` -------------------------------- ### Simplifying OIDC Ready Checks in TanStack Start Components Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/non-blocking-rendering.md This code demonstrates how to simplify checks for OIDC readiness within TanStack Start components using the `assert: "ready"` option. This approach removes the need for explicit `isOidcReady` checks, making the code cleaner and more declarative by ensuring the hook only returns values when OIDC is ready. ```tsx function AuthButtons(props: { className?: string }) { const { className } = props; const { isUserLoggedIn } = useOidc({ assert: "ready" }); return (
{isUserLoggedIn ? : }
); } function Greeting() { const { isUserLoggedIn, decodedIdToken } = useOidc({ assert: "ready" }); return ( {isUserLoggedIn ? `Welcome back ${decodedIdToken.name}` : `Hello anonymous visitor!`} ); } ``` -------------------------------- ### Install oidc-spa and zod in Angular (yarn) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Installs the oidc-spa and zod libraries using yarn. Zod is optional but recommended for input validation. ```bash yarn add oidc-spa zod ``` -------------------------------- ### Install oidc-spa dependencies Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/nuxt.md Installation commands for oidc-spa and Zod validation library across different package managers. ```npm npm install oidc-spa zod ``` ```yarn yarn add oidc-spa zod ``` ```pnpm pnpm add oidc-spa zod ``` ```bun bun add oidc-spa zod ``` -------------------------------- ### Hono API Handler Setup with OIDC SPA Authentication Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/backend-token-validation/hono.md This snippet shows a typical Hono API handler setup. It initializes the OIDC SPA authentication module with configuration, defines routes for fetching todos, and demonstrates how to retrieve user information using `getUser` which includes role validation. ```typescript import { Hono } from "hono"; import * as fs from "node:fs/promises"; import { bootstrapAuth, getUser } from "./auth"; // See below function startHonoServer() { bootstrapAuth({ implementation: "real", // or "mock", see: https://docs.oidc-spa.dev/v/v8/integration-guides/backend-token-validation/mock-modes issuerUri: process.env.OIDC_ISSUER_URI!, expectedAudience: process.env.OIDC_AUDIENCE }); const app = new Hono(); app.get("/api/todos", async c => { const user = await getUser({ req: c.req }); const json = await fs.readFile(`todos_${user.id}.json`, "utf8"); return c.text(json); }); app.get("/api/todos-for-support/:userId", async c => { // Will reject the request if user making the request // doesn't have "support-staff" role await getUser({ req: c.req, requiredRole: "support-staff" }); const userId = c.req.param("userId"); const json = await fs.readFile(`todos_${userId}.json`, "utf8"); return c.text(json); }); // ... } ``` -------------------------------- ### Integrate OIDC with React Source: https://context7.com/keycloakify/docs.oidc-spa.dev/llms.txt Demonstrates setting up OIDC in a React application using bootstrapOidc and the useOidc hook. It includes examples for protected components and accessing user information. ```typescript import { oidcSpa } from "oidc-spa/react-spa"; import { z } from "zod"; export const { bootstrapOidc, useOidc, withLoginEnforced } = oidcSpa .withExpectedDecodedIdTokenShape({ decodedIdTokenSchema: z.object({ sub: z.string(), preferred_username: z.string(), email: z.string().optional() }) }) .createUtils(); bootstrapOidc({ issuerUri: import.meta.env.VITE_OIDC_ISSUER, clientId: import.meta.env.VITE_OIDC_CLIENT_ID, debugLogs: true }); function UserProfile() { const { isUserLoggedIn, login, logout } = useOidc(); if (!isUserLoggedIn) return ; const { getDecodedIdToken } = useOidc({ assert: "user logged in" }); return

Welcome, {getDecodedIdToken().preferred_username}

; } ``` -------------------------------- ### Initialize oidc-spa with Keycloak Credentials Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/providers-configuration/keycloak.md Demonstrates how to initialize the oidc-spa library with Keycloak's issuerUri and clientId. This snippet is framework-agnostic and shows the basic setup required for authentication. ```typescript createOidc({ issuerUri: "https://auth.my-company.com/realms/myeralm", clientId! "myclient", // ... }); ``` -------------------------------- ### Manual Setup for Security Features (Recommended) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/resources/migrating-from-keycloak-js.md This configuration is for non-Vite projects or when more control is needed. It involves renaming the main entry point and creating a new one to call `oidcEarlyInit`. This method ensures security features are initialized early in the application lifecycle. It requires importing modules from 'oidc-spa/entrypoint', 'oidc-spa/browser-runtime-freeze', and 'oidc-spa/DPoP'. ```typescript import { oidcEarlyInit } from "oidc-spa/entrypoint"; import { browserRuntimeFreeze } from 'oidc-spa/browser-runtime-freeze'; import { DPoP } from 'oidc-spa/DPoP'; const { shouldLoadApp } = oidcEarlyInit({ BASE_URL: "/" // The path where your app is hosted // If applicable you should use `process.env.PUBLIC_URL` // or `import.meta.env.BASE_URL`. // This is not an option. There's only one good answer. securityDefenses: { // See: https://docs.oidc-spa.dev/v/v10/security-features/browser-runtime-freeze ...browserRuntimeFreeze({ //excludes: [ "fetch", "XMLHttpRequest" ] }), // See: https://docs.oidc-spa.dev/v/v10/security-features/dpop ...DPoP({ mode: 'auto' }) } }); if( shouldLoadApp ){ import("./main.lazy"); } ``` -------------------------------- ### Configure oidc-spa with Parameters (Framework Agnostic, TypeScript) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/providers-configuration/auth0.md Demonstrates how to initialize oidc-spa using the `createOidc` function with essential parameters like `issuerUri`, `clientId`, and `extraQueryParams`. It also highlights the optional `idleSessionLifetimeInSeconds` for auto-logout synchronization. ```typescript createOidc({ issuerUri: "auth.my-company.com", clientId: "DzXSmwQS7oSTQGLbafhrPXYLT0mOMyZD" extraQueryParams: { audience: "https://app.my-company.com/api" } // (Optional) This must be kept in sync with the Idle Session Lifetime value // configured in the Auth0 dashboard. To ensure correct autoLogout behavior. idleSessionLifetimeInSeconds: 1800, // ... }); ``` -------------------------------- ### Manual oidc-spa Initialization (Recommended) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/react-router.md This method is recommended for non-Vite projects with a single client entry point. It involves renaming the main entry file and creating a new one to call `oidcEarlyInit` before deferring the main app import, optimizing authentication speed. ```bash mv src/main.ts src/main.lazy.ts ``` ```typescript import { oidcEarlyInit } from "oidc-spa/entrypoint"; const { shouldLoadApp } = oidcEarlyInit({ BASE_URL: "/" // The path where your app is hosted. You can also pass it later to createOidc(). }); if (shouldLoadApp) { // Note: Deferring the main app import adds a few milliseconds to cold start, // but dramatically speeds up auth. Overall, it's a net win. import("./main.lazy"); } ``` -------------------------------- ### Fastify Server Setup with OIDC SPA Authentication Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/backend-token-validation/fastify.md This snippet demonstrates setting up a Fastify server, bootstrapping OIDC SPA authentication, and defining API endpoints that require user authentication. It includes reading user-specific data and handling requests with role-based access control. ```typescript import Fastify from "fastify"; import * as fs from "node:fs/promises"; import { bootstrapAuth, getUser } from "./auth"; // See below async function startFastifyServer() { bootstrapAuth({ implementation: "real", // or "mock", see: https://docs.oidc-spa.dev/v/v8/integration-guides/backend-token-validation/mock-modes issuerUri: process.env.OIDC_ISSUER_URI!, expectedAudience: process.env.OIDC_AUDIENCE }); const fastify = Fastify({ // If you run behind a reverse proxy, you almost always want this enabled. // It affects things like the computed request origin. trustProxy: true }); fastify.get("/api/todos", async (req, reply) => { const user = await getUser({ req, reply }); const json = await fs.readFile( `todos_${user.id}.json`, "utf8" ); reply.code(200).type("application/json").send(json); }); fastify.get("/api/todos-for-support/:userId", async (req, reply) => { // Will reject the request if user making the request // doesn't have "support-staff" role await getUser({ req, reply, requiredRole: "support-staff" }); const { userId } = req.params as { userId: string }; const json = await fs.readFile( `todos_${userId}.json`, "utf8" ); reply.code(200).type("application/json").send(json); }); // ... await fastify.listen({ port: parseInt(process.env.PORT ?? "3000"), host: "0.0.0.0" }); } ``` -------------------------------- ### Rename Angular Entrypoint Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/angular.md Renames the main TypeScript entry point file from `main.tsx` to `main.lazy.tsx` as part of the oidc-spa setup. ```bash mv src/main.tsx src/main.lazy.tsx ``` -------------------------------- ### Authentication Utilities for Server-Side (TypeScript) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/backend-token-validation/deno.serve.md This snippet defines utility functions for server-side authentication using the 'oidc-spa' library. It includes 'bootstrapAuth' for initializing the authentication process and 'getUser' for validating access tokens and extracting user information, with support for role-based authorization. ```typescript import { oidcSpa, extractRequestAuthContext } from "npm:oidc-spa@latest/server"; import { z } from "npm:zod@latest"; const { bootstrapAuth, validateAndDecodeAccessToken } = oidcSpa .withExpectedDecodedAccessTokenShape({ // This is purely declarative. Here you'll specify // the claim that you expect to be present in the access token payload. decodedAccessTokenSchema: z.object({ sub: z.string(), name: z.string(), email: z.string().optional(), // Keycloak specific, convention to manage authorization. realm_access: z.object({ roles: z.array(z.string()) }).optional() }) }) .createUtils(); export { bootstrapAuth }; // Your local representation of a user. export type User = { id: string; name: string; email: string | undefined; }; export async function getUser(params: { req: Request; requiredRole?: "realm-admin" | "support-staff"; }): Promise { const { req, requiredRole } = params; const requestAuthContext = extractRequestAuthContext({ request: req, // Set this to false only if you don't have a reverse HTTP proxy in front of your // server. (Almost never the case in modern deployments). trustProxy: true }); if (!requestAuthContext) { // Demo shortcut: we return 401 on missing Authorization, but a mixed // public/private endpoint could instead return undefined here and let // the caller decide whether to process an anonymous request. console.warn("Anonymous request"); return new Response("unauthorized", { status: 401 }); } if (!requestAuthContext.isWellFormed) { console.warn(requestAuthContext.debugErrorMessage); return new Response("bad request", { status: 400 }); } const { isSuccess, debugErrorMessage, decodedAccessToken } = await validateAndDecodeAccessToken( requestAuthContext.accessTokenAndMetadata ); if (!isSuccess) { console.warn(debugErrorMessage); return new Response("unauthorized", { status: 401 }); } // Your custom Authorization logic: Grant per request access depending // on the access token claim. // ... (rest of the implementation) return { id: decodedAccessToken.sub, name: decodedAccessToken.name, email: decodedAccessToken.email }; } ``` -------------------------------- ### TanStack Start Auto Login Integration Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/auto-login.md Integrate Auto Login into your TanStack Start application by adding the `.withAutoLogin()` configuration. This simplifies authentication logic by removing the need for explicit login enforcement and session checks. ```diff import { oidcSpa } from "oidc-spa/react-tanstack-start"; export const { bootstrapOidc, useOidc, getOidc, oidcFnMiddleware, oidcRequestMiddleware, - enforceLogin } = oidcSpa .withExpectedDecodedIdTokenShape({ /* ... */ }) .withAccessTokenValidation({ /* ... */ }) + .withAutoLogin() .createUtils(); ``` ```tsx import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"; import Header from "@/components/Header"; import { AutoLogoutWarningOverlay } from "@/components/AutoLogoutWarningOverlay"; import { useOidc } from "@/oidc"; export const Route = createRootRoute({ // ... shellComponent: ShellComponent, // NOTE: Even with SSR disabled here, the ShellComponent is still SSR'd. // Only page components lose SSR. // You *can* disable SSR per-page for routes that don't load authed data, // but if your app isn’t public, it’s simpler to SSR only the shell. ssr: false }); function ShellComponent({ children }: { children: React.ReactNode }) { const { isOidcReady } = useOidc(); return ( <html lang="en"> <head> <HeadContent /> </head> <body> <div className="min-h-screen flex flex-col"> <Header /> <main className="flex flex-1 flex-col"> {isOidcReady && children } </main> </div> <AutoLogoutWarningOverlay /> <Scripts /> </body> </html> ); } ``` ```diff import { useOidc } from "@/oidc"; -function AuthButtons() { - const { hasInitCompleted, isUserLoggedIn } = useOidc(); - - if (!hasInitCompleted) { - return null; - } - - return isUserLoggedIn ? : ; -} - -function LoggedInAuthButton() { - const { logout } = useOidc({ assert: "user logged in" }); - - return ( - - ); -} - -function NotLoggedInAuthButton() { - const { login, issuerUri } = useOidc({ assert: "user not logged in" }); - - return ( -
- -
- ); -} +function AuthButtons() { + + const { isOidcReady, logout } = useOidc(); + + if (!isOidcReady) { + return null; + } + + return ( + + ); +} ``` ```diff -oidcFnMiddleware({ assert: "user logged in" }) +oidcFnMiddleware() -oidcRequestMiddleware({ assert: "user logged in" }) +oidcRequestMiddleware() ``` ```diff export const Route = createFileRoute("/demo/start/api-request")({ ``` -------------------------------- ### Manual oidc-spa Initialization for App Entrypoint Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/tanstack-router-start/react-router.md This code shows the 'Manual - Recommended' approach for initializing oidc-spa. It involves renaming the original entry point (e.g., main.ts to main.lazy.ts) and creating a new main.ts that calls 'oidcEarlyInit' and conditionally imports the lazy-loaded application. ```typescript import { oidcEarlyInit } from "oidc-spa/entrypoint"; const { shouldLoadApp } = oidcEarlyInit({ BASE_URL: "/" // The path where your app is hosted. You can also pass it later to createOidc(). }); if (shouldLoadApp) { // Note: Deferring the main app import adds a few milliseconds to cold start, // but dramatically speeds up auth. Overall, it's a net win. import("./main.lazy"); } ``` -------------------------------- ### Configure DPoP (Demonstrating Proof-of-Possession) Source: https://context7.com/keycloakify/docs.oidc-spa.dev/llms.txt Shows how to enable DPoP to bind access tokens to cryptographic keys, preventing token replay attacks. Configuration is supported via Vite plugins or manual initialization in the application entry point. ```typescript // vite.config.ts - Vite Plugin approach import { defineConfig } from "vite"; import { oidcSpa } from "oidc-spa/vite-plugin"; export default defineConfig({ plugins: [ oidcSpa({ browserRuntimeFreeze: { enabled: true }, DPoP: { enabled: true, mode: "auto" } // "auto" or "enforced" }) ] }); // Manual approach - src/main.ts import { oidcEarlyInit } from "oidc-spa/entrypoint"; import { browserRuntimeFreeze } from "oidc-spa/browser-runtime-freeze"; import { DPoP } from "oidc-spa/DPoP"; const { shouldLoadApp } = oidcEarlyInit({ BASE_URL: "/", securityDefenses: { ...browserRuntimeFreeze(), ...DPoP({ mode: "auto" }) } }); if (shouldLoadApp) { import("./main.lazy"); } // Usage remains unchanged - DPoP is transparent const { accessToken } = await oidc.getTokens(); fetch("/api/data", { headers: { Authorization: `Bearer ${accessToken}` } }); ``` -------------------------------- ### Example Access Token Claims Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/talking-to-multiple-apis-with-different-access-tokens.md Shows an example of claims found within an access token, highlighting the 'aud' (audience) field which specifies the intended resource server. Different APIs may require different claims. ```json { "aud": "https://api1.example.com", "sub": "xxxxxx", "groups": ["staff"] } ``` -------------------------------- ### CSP Configuration Example for Session Restoration Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/resources/csp-configuration.md This example demonstrates the necessary Content-Security-Policy directives to allow oidc-spa to perform silent session restoration using iframes. It specifically focuses on relaxing frame-src to include the IdP domain and frame-ancestors to allow the application to be framed by itself. ```nginx Content-Security-Policy: frame-src https://auth.my-domain.com; frame-ancestors 'self'; ...other CSP directives... ``` -------------------------------- ### Manual oidc-spa Initialization in src/oidc.ts Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/tanstack-router-start/react-router.md This snippet illustrates the 'Manual - Easy' approach for oidc-spa initialization, suitable for projects not using Vite or when the entry file cannot be edited. It involves calling 'oidcEarlyInit' early in 'src/oidc.ts'. This method may have security implications and potential conflicts with client-side routing. ```typescript import { oidcEarlyInit, } from "oidc-spa/entrypoint"; import { oidcSpa } from "oidc-spa/react-spa"; // Should run as early as possible. oidcEarlyInit({ BASE_URL: "/" // The path where your app is hosted }); export const { /* ... */ } = oidcSpa./*...*/ ``` -------------------------------- ### GET /api/admin/users Source: https://context7.com/keycloakify/docs.oidc-spa.dev/llms.txt Retrieves the list of users. Restricted to users with the 'realm-admin' role. ```APIDOC ## GET /api/admin/users ### Description Admin-only endpoint to retrieve user data. Validates both the token and the required 'realm-admin' role. ### Method GET ### Endpoint /api/admin/users ### Parameters None ### Request Example GET /api/admin/users Authorization: Bearer ### Response #### Success Response (200) - **users** (array) - List of system users #### Response Example { "users": [] } #### Error Response (403) Returned if the user does not possess the 'realm-admin' role. ``` -------------------------------- ### Conditional Rendering with TanStack Start and OIDC Initialization Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/non-blocking-rendering.md This snippet demonstrates how to conditionally render parts of a React application based on OIDC readiness in TanStack Start. It ensures that UI components dependent on OIDC are only displayed after the initialization process is complete, preventing layout shifts and ensuring a smooth user experience. ```tsx import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"; import Header from "@/components/Header"; import { AutoLogoutWarningOverlay } from "@/components/AutoLogoutWarningOverlay"; import appCss from "../styles.css?url"; import { useOidc } from "@/oidc"; export const Route = createRootRoute({ head: () => ({ /* ... */ }), shellComponent: RootDocument }); function RootDocument({ children }: { children: React.ReactNode }) { const { isOidcReady } = useOidc(); return (
{isOidcReady && ( <>
{children}
)}
); } ``` -------------------------------- ### Handle OIDC Initialization Errors in Angular Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/features/error-management/error-handling-with-autologin.md This example shows how to check for and handle OIDC initialization errors within an Angular application. It logs diagnostic information, similar to the React example, distinguishing between server outages and configuration issues. The code utilizes Angular's dependency injection to access the OIDC service. ```html @if (oidc.initializationError) {

Our Auth is down, sorry :( }@else{ } ``` ```typescript @Component({ selector: 'app-root', imports: [RouterOutlet, RouterLink, RouterLinkActive], templateUrl: './app.html', }) export class App { oidc = inject(Oidc); constructor(){ if( this.oidc.initializationError ){ const { initializationError } = this.oidc; // Distinguish a misconfiguration from a temporary auth-server outage. console.log(initializationError.isAuthServerLikelyDown); // Developer-only diagnostic with likely cause and fix. // Do not display this to end users. console.log(initializationError.message); } } } ``` -------------------------------- ### Hono Server with WebSockets (TypeScript) Source: https://github.com/keycloakify/docs.oidc-spa.dev/blob/v10/integration-guides/backend-token-validation/websocket.md Sets up a Hono server with WebSocket functionality using `@hono/node-ws`. It bootstraps authentication, defines API endpoints, and handles WebSocket upgrades, extracting user information from the 'Sec-WebSocket-Protocol' header. ```typescript import { Hono } from "hono"; import { createNodeWebSocket } from "@hono/node-ws"; import { serve } from "@hono/node-server"; import { bootstrapAuth, getUser, getUser_ws } from "./auth"; // See below function startHonoServer() { bootstrapAuth({ implementation: "real", // or "mock", see: https://docs.oidc-spa.dev/v/v8/integration-guides/backend-token-validation/mock-modes issuerUri: process.env.OIDC_ISSUER_URI!, expectedAudience: process.env.OIDC_AUDIENCE }); const app = new Hono(); app.get("/api/todos", async c => { /* ... */ }); const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app }); app.get( "/ws", upgradeWebSocket(async c => { const user = await getUser_ws({ req: c.req }); return { onOpen: (_event, ws) => { ws.send(`Hello ${user.name}`); }, onMessage(event, ws) { ws.send(`I'm not very smart, all I can do is repeat: "${event.data}"`); } }; }) ); const server = serve({ fetch: app.fetch, port }); injectWebSocket(server); } ```