Quickstart
This guide walks through adding OIDC authentication to your app using any spec-compliant OIDC provider (like Autentico, Auth0, or Keycloak).
-
Install your framework adapter
Terminal window npm install oidc-js-react # or oidc-js-vue, oidc-js-svelte, oidc-js-angular, etc. -
Add authentication
You’ll need an issuer URL, client ID, and redirect URI from your OIDC provider.
import { AuthProvider, RequireAuth, useAuth } from "oidc-js-react";const config = {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],};function App() {return (<AuthProvider config={config}><RequireAuth fallback={<p>Loading...</p>}><Dashboard /></RequireAuth></AuthProvider>);}function Dashboard() {const { user, actions } = useAuth();return (<div><p>Welcome, {user?.profile?.name}!</p><button onClick={() => actions.logout()}>Log out</button></div>);}// main.ts — register the pluginimport { oidcPlugin } from "oidc-js-vue";app.use(oidcPlugin, {config: {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],},});<!-- Dashboard.vue — protect and access auth state --><script setup lang="ts">import { RequireAuth, useAuth } from "oidc-js-vue";const { user, actions } = useAuth();</script><template><RequireAuth><template #fallback><p>Loading...</p></template><p>Welcome, {{ user?.profile?.name }}!</p><button @click="actions.logout()">Log out</button></RequireAuth></template><!-- App.svelte --><script lang="ts">import { AuthProvider, RequireAuth } from "oidc-js-svelte";const config = {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],};</script><AuthProvider {config}>{#snippet children()}<RequireAuth>{#snippet children()}<Dashboard />{/snippet}{#snippet fallback()}<p>Loading...</p>{/snippet}</RequireAuth>{/snippet}</AuthProvider><!-- Dashboard.svelte — access auth state --><script lang="ts">import { getAuthContext } from "oidc-js-svelte";const auth = getAuthContext();</script><p>Welcome, {auth.user?.profile?.name}!</p><button onclick={() => auth.actions.logout()}>Log out</button>// app.config.ts — provide auth and protect routesimport { provideAuth, authGuard } from "oidc-js-angular";export const appConfig = {providers: [provideRouter([{path: "dashboard",component: DashboardComponent,canActivate: [authGuard],},]),provideAuth({config: {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],},}),],};// dashboard.component.ts — access auth stateimport { Component, inject } from "@angular/core";import { AuthService } from "oidc-js-angular";@Component({selector: "app-dashboard",template: `<p>Welcome, {{ auth.user()?.profile?.name }}!</p><button (click)="auth.logout()">Log out</button>`,})export class DashboardComponent {readonly auth = inject(AuthService);}import { AuthProvider, RequireAuth, useAuth } from "oidc-js-solid";const config = {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],};function App() {return (<AuthProvider config={config}><RequireAuth fallback={<p>Loading...</p>}><Dashboard /></RequireAuth></AuthProvider>);}function Dashboard() {const auth = useAuth();return (<div><p>Welcome, {auth.user?.profile?.name}!</p><button onClick={() => auth.actions.logout()}>Log out</button></div>);}import { AuthProvider, RequireAuth, useAuth } from "oidc-js-preact";const config = {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],};function App() {return (<AuthProvider config={config}><RequireAuth fallback={<p>Loading...</p>}><Dashboard /></RequireAuth></AuthProvider>);}function Dashboard() {const { user, actions } = useAuth();return (<div><p>Welcome, {user?.profile?.name}!</p><button onClick={() => actions.logout()}>Log out</button></div>);}import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { AuthController, RequireAuthController } from "oidc-js-lit";@customElement("app-root")export class AppRoot extends LitElement {auth = new AuthController(this, {config: {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],},});guard = new RequireAuthController(this, { auth: this.auth });render() {if (!this.guard.authorized) return html`<p>Loading...</p>`;const { user } = this.auth;return html`<p>Welcome, ${user?.profile?.name}!</p><button @click=${() => this.auth.logout()}>Log out</button>`;}}<template><auth-provider @:config="config"><require-auth><p>Welcome, {{auth.user.value?.profile?.name}}!</p><button @on:click="auth.actions.logout()">Log out</button></require-auth></auth-provider></template><script>import { Component } from "kasper-js";import { useAuth } from "oidc-js-kasper";export class App extends Component {config = {issuer: "https://auth.example.com",clientId: "my-app",redirectUri: "http://localhost:5173/callback",scopes: ["openid", "profile", "email", "offline_access"],};auth = useAuth();}</script>
What happens under the hood
Section titled “What happens under the hood”- The auth provider fetches the OIDC discovery document from
{issuer}/.well-known/openid-configuration - When login is triggered, it generates PKCE parameters, saves auth state to
sessionStorage, and redirects to the IdP’s authorization endpoint - After the user authenticates, the IdP redirects back with an authorization code
- The provider detects the code in the URL, exchanges it for tokens, fetches the user profile, and cleans up the URL
- The auth guard (RequireAuth / authGuard) checks token expiry and automatically refreshes expired tokens using the refresh token