React Router
Instaling
npm install oidc-spa zodyarn add oidc-spa zodpnpm add oidc-spa zodbun add oidc-spa zodNote: Zod is optional but highly recommended. Writing validators manually is error-prone, and skipping validation means losing early guarantees about what your auth server provides. You can use another validator though, it doesn't have to be Zod.
If you’re not using Vite and you can’t edit your app’s entry file, run oidcEarlyInit() in the src/oidc.ts.
import { defineConfig } from "vite";
import { oidcSpa } from "oidc-spa/vite-plugin";
export default defineConfig({
plugins: [
// ...
oidcSpa()
]
});Pick this approach if:
You're not in a Vite project and
Your app has a single client entrypoint.
Let's assume your app entrypoint is src/main.ts.
First, rename it to src/main.lazy.ts.
mv src/main.ts src/main.lazy.tsThen create a new src/main.ts file:
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");
}If you’re not using Vite and you can’t edit your app’s entry file, run oidcEarlyInit() in the same module where you call createOidc().
Note however that implementing this option dowgrades the security posture of your app compared to the two other approaches, and, in some instances, might conflict with your client side routing library.
Learning from the example
You're going to be cloning this example:
React Router v7 has three modes pick the one for you:
The security features of oidc-spa are not fully effective with React Router Framework.
The security model relies on hardening the environment before any code is evaluated. If that invariant does not hold, a supply chain attack can alter the JavaScript runtime before oidc-spa can secure it.
React Router Framework does not expose a true client entrypoint. There’s no workaround for this.
Bottom line: you can run React Router Framework in SPA mode and it will work, but oidc-spa cannot protect your tokens any more than other browser-side OIDC solutions. If security is a top priority, consider migrating to TanStack.
Enabling SPA mode
This is non optional. React Router Framework does not expose the primitives to enable solution like oidc-spa to provide a full stack story. (You may want to give TanStack Start a try)
The example
Creating an API server
Now that authentication is handled, there’s one last piece of the puzzle: your resource server, the backend your app will communicate with.
This can be any type of service: a REST API, tRPC server, or WebSocket endpoint, as long as it can validate access tokens issued by your IdP.
If you’re building it in JavaScript or TypeScript (for example, using Express), oidc-spa provides ready-to-use utilities to decode and validate access tokens on the server side.
You’ll find the full documentation here:
Backend Token ValidationLast updated
Was this helpful?