Auto Login
Enforce authentication everywhere in your app.
Auto Login is a mode in oidc-spa designed for applications where every page requires authentication.
This is typically the case for admin dashboards or any internal tool that do not need "marketing" pages.
When Auto Login is enabled, visiting your application automatically redirects the user to the IdP’s login page if no active session is detected.
import { createOidc } from "oidc-spa/core";
const oidc = await createOidc({
// ...
autoLogin: true
}); import { oidcSpa } from "oidc-spa/react-tanstack-start";
export const {
bootstrapOidc,
useOidc,
getOidc,
oidcFnMiddleware,
oidcRequestMiddleware,
- enforceLogin
} = oidcSpa
.withExpectedDecodedIdTokenShape({ /* ... */ })
.withAccessTokenValidation({ /* ... */ })
+ .withAutoLogin()
.createUtils();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 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>
);
}You can remove all the assertin your oidc component, the components specifically for the not logged in state can be removed.
import { useOidc } from "@/oidc";
-function AuthButtons() {
- const { hasInitCompleted, isUserLoggedIn } = useOidc();
-
- if (!hasInitCompleted) {
- return null;
- }
-
- return isUserLoggedIn ? <LoggedInAuthButton /> : <NotLoggedInAuthButton />;
-}
-
-function LoggedInAuthButton() {
- const { logout } = useOidc({ assert: "user logged in" });
-
- return (
- <button
- onClick={() => logout({ redirectTo: "home" })}
- >
- Logout
- </button>
- );
-}
-
-function NotLoggedInAuthButton() {
- const { login, issuerUri } = useOidc({ assert: "user not logged in" });
-
- return (
- <div className="flex items-center gap-2">
- <button
- onClick={() => login()}
- >
- Login
- </button>
- </div>
- );
-}
+function AuthButtons() {
+
+ const { isOidcReady, logout } = useOidc();
+
+ if (!isOidcReady) {
+ return null;
+ }
+
+ return (
+ <button
+ onClick={() => logout({ redirectTo: "home" })}
+ >
+ Logout
+ </button>
+ );
+}You can remove the assert: "user logged in" from oidcFnMiddleware and oidcRequestMiddleware:
-oidcFnMiddleware({ assert: "user logged in" })
+oidcFnMiddleware()
-oidcRequestMiddleware({ assert: "user logged in" })
+oidcRequestMiddleware()You can remove all the beforeLoad: enforceLogin:
export const Route = createFileRoute("/demo/start/api-request")({
- beforeLoad: enforceLogin,
loader: async () => { },
pendingComponent: () => <Spinner />,
component: Home
});For all the components that are within the <OidcInitializationGate /> you know that hasInitCompleted will be true so you can assert it to narrow down the type:
-const { ... } = useOidc({ assert: "user logged in" });
+const { ... } = useOidc({ assert: "ready" }); export const {
bootstrapOidc,
useOidc,
getOidc,
OidcInitializationGate
- withLoginEnforced,
- enforceLogin
} = oidcSpa
.withExpectedDecodedIdTokenShape({ /* ... */ })
+ .withAutoLogin()
.createUtils();You can then proceed to remove all the usage of withLoginEnforced and enforceLogin throughout your codebase.
You can also remove all the assetion of the login state of the user:
- useOidc({ assert: "user logged in" });
+ useOidc();All the components with useOidc({ assert: "user not logged in" }); can be removed.
@Injectable({ providedIn: 'root' })
export class Oidc extends AbstractOidcService<DecodedIdToken> {
// ...
override autoLogin = true;
}All the handling for the user not logged in state can be removed.
-@if (oidc.isUserLoggedIn) {
<div>
<span>Hello {{ oidc.$decodedIdToken().name }}</span>
<button (click)="oidc.logout({ redirectTo: 'home' })">Logout</button>
</div>
-} @else {
-<div>
- <button (click)="oidc.login()">Login</button>
-</div>
-}You can remove the usage of Oidc.enforceLoginGuard:
-canActivate: [Oidc.enforceLoginGuard],
//...
canActivate: [
async (route) => {
const oidc = inject(Oidc);
const router = inject(Router);
- await Oidc.enforceLoginGuard(route);
//...
},
],Last updated
Was this helpful?