npx degit https://github.com/keycloakify/oidc-spa/examples/react-router oidc-spa-react-router
cd oidc-spa-react-router
cp .env.local.sample .env.local
yarn
yarn dev
Enabling SPA mode
react-router.config.ts
import type { Config } from "@react-router/dev/config";
export default {
// Config options...
// Server-side render by default, to enable SPA mode set this to `false`
ssr: false
} satisfies Config;
oidc.client.ts
Make sure you create a app/oidc.client.ts file, (instead of app/oidc.ts).
Setting up the entrypoint
Create thoses two files:
Working with loaders
The default approach when you want to enforce that the user be logged in when accesing a given route is to wrap the component into withLoginEnforced(), example:
This approach is framwork agnostic and always works however, you might want to use the loaders to doload the data, for that you would use enforceLogin() istead of withLoginEnforced:
pages/invoices.tsx
import { enforceLogin, fetchWithAuth } from "../oidc.client";
import type { Route } from "./+types/invoices";
import { useLoaderData } from "react-router";
export async function clientLoader(params: Route.ClientLoaderArgs) {
await enforceLogin(params);
// If we are here, the user is logged in.
const invoices = await fetchWithAuth("/api/invoices").then(r => r.json());
return invoices;
}
export function HydrateFallback() {
return <div>Loading invoices...</div>;
}
export default function Invoices() {
const invoices = useLoaderData<typeof clientLoader>();
return (
<div>
{invoices.map(invoice => (
<div key={invoice.id}>{invoice.amount}</div>
))}
</div>
);
}
Running the example
Run it locally with:
npx degit https://github.com/keycloakify/oidc-spa/examples/react-router-framework oidc-spa-react-router
cd oidc-spa-react-router
cp .env.local.sample .env.local
yarn
yarn dev
This is for setting for integrating oidc-spa with react-router in .
As of today, to use oidc-spa you need to .
If your whole app requires user to be authenticated () you can skip this section.