Basic Usage
Let's get your App authenticated!
In this section we assume that you have access to an OIDC Server, that you have created and configured an OIDC client for your application and that you have a hold on your issuer uri and client id.
import { createOidc } from "oidc-spa";
const oidc = await createOidc({
issuerUri: "https://auth.your-domain.net/realms/myrealm",
clientId: "myclient",
/**
* Vite: `publicUrl: import.meta.env.BASE_URL`
* CRA: `publicUrl: process.env.PUBLIC_URL`
* Other: `publicUrl: "/"` (Usually)
*/
BASE_URL: import.meta.env.BASE_URL
});
if (!oidc.isUserLoggedIn) {
// The user is not logged in.
// We can call login() to redirect the user to the login/register page.
// This return a promise that never resolve.
oidc.login({
/**
* If you are calling login() in the callback of a click event
* set this to false.
*/
doesCurrentHrefRequiresAuth: false
/**
* Optionally, you can add some extra parameter
* to be added on the login url.
* (Can also be a parameter of createOidc `extraQueryParams: ()=> ({ ui_locales: "fr" })`)
*/
//extraQueryParams: { kc_idp_hint: "google", ui_locales: "fr" }
/**
* You can allso set where to redirect the user after
* successful login
*/
// redirectUrl: "/dashboard"
/**
* Keycloak: You can also send the users directly to the register page
* see: https://github.com/keycloakify/oidc-spa/blob/14a3777601c50fa69d1221495d77668e97443119/examples/tanstack-router-file-based/src/components/Header.tsx#L54-L66
*/
});
} else {
// The user is logged in.
const {
// The accessToken is what you'll use as a Bearer token to
// authenticate to your APIs
accessToken,
decodedIdToken
} = oidc.getTokens();
fetch("https://api.your-domain.net/orders", {
headers: {
Authorization: `Bearer ${accessToken}`
}
})
.then(response => response.json())
.then(orders => console.log(orders));
// To call when the user click on logout.
// You can also redirect to a custom url with
// { redirectTo: "specific url", url: "/bye" }
oidc.logout({ redirectTo: "home" });
// If you are wondering why ther's a decodedIdToken and no
// decodedAccessToken read this: https://docs.oidc-spa.dev/resources/jwt-of-the-access-token
console.log(`Hello ${decodedIdToken.preferred_username}`);
// Note that in this example the decodedIdToken is not typed.
// What is inside the idToken is defined by the OIDC server you are using.
// If you want to specify the type of the decodedIdToken you can do:
//
// import { z } from "zod";
// export const { useOidc } = createUseOidc({
// ...
// decodedIdTokenSchema: z.object({
// sub: z.string(),
// preferred_username: z.string(),
// // ... other properties
// })
// })
}
This piece of code should give you the necessary information to understand how oidc-spa can be used inside your react components. To go further you can refer to the examples setup to see how to integrate oidc-spa with your routing library:
import { createReactOidc } from "oidc-spa/react";
export const { OidcProvider, useOidc, getOidc } = createReactOidc({
// NOTE: If you don't have the params right away see note below.
issuerUri: "https://auth.your-domain.net/realms/myrealm",
clientId: "myclient",
/**
* Vite: `publicUrl: import.meta.env.BASE_URL`
* CRA: `publicUrl: process.env.PUBLIC_URL`
* Other: `publicUrl: "/"` (Usually)
*/
BASE_URL: import.meta.env.BASE_URL
});
ReactDOM.createRoot(document.getElementById("root")!).render(
<OidcProvider
// Optional, it's usually so fast that a fallback is really not required.
fallback={<>Checking authentication ⌛️</>}
>
<App />
</OidcProvider>
);
function App() {
const { isUserLoggedIn, login, logout, oidcTokens } = useOidc();
return (
isUserLoggedIn ? (
<>
{/*
Note: The decodedIdToken can be typed and validated with zod See: https://github.com/keycloakify/oidc-spa/blob/fddac99d2b49669a376f9a0b998a8954174d195e/examples/tanstack-router/src/oidc.tsx#L17-L43
If you are wondering why ther's a decodedIdToken and no
decodedAccessToken read this: https://docs.oidc-spa.dev/resources/jwt-of-the-access-token
*/}
<span>Hello {oidcTokens.decodedIdToken.preferred_username}</span>
<button onClick={() => logout({ redirectTo: "home" })}>
Logout
</button>
</>
) : (
<button onClick={() => login({
/**
* If you are calling login() in the callback of a button click
* (like here) set this to false.
*/
doesCurrentHrefRequiresAuth: false
/**
* Optionally, you can add some extra parameter
* to be added on the login url.
* (Can also be a parameter of createReactOidc `extraQueryParams: ()=> ({ ui_locales: "fr" })`)
*/
//extraQueryParams: { kc_idp_hint: "google", ui_locales: "fr" }
/**
* You can allso set where to redirect the user after
* successful login
*/
// redirectUrl: "/dashboard"
/**
* Keycloak: You can also send the user direcly to the register page
* See: https://github.com/keycloakify/oidc-spa/blob/14a3777601c50fa69d1221495d77668e97443119/examples/tanstack-router-file-based/src/components/Header.tsx#L54-L66
*/
})} >
Login
</button>
)
);
}
import { useEffect, useState } from "react";
type Order = {
id: number;
name: string;
};
function OrderHistory(){
const { oidcTokens } = useOidc({ assert: "user logged in" });
const [orders, setOrders] = useState<Order[] | undefined>(undefined);
useEffect(
()=> {
fetch("https://api.your-domain.net/orders", {
headers: {
Authorization: `Bearer ${oidcTokens.accessToken}`
}
})
.then(response => response.json())
.then(orders => setOrders(orders));
},
[]
);
if(orders === undefined){
return <>Loading orders ⌛️</>
}
return (
<ul>
{orders.map(order => (
<li key={order.id}>{order.name}</li>
))}
</ul>
);
}
If you get your OIDC parameters from an API you can passes an assync function that returns the oidc parameters. This function gets called when <OidcProvider />
is first mounted or when getOidc()
is first called.
export const {
OidcProvide,
useOidc,
getOidc
} = createReactOidc(async ()=> {
const {
issuerUri,
clientId
} = await axios.get("/oidc-params").then(r => r.data);
return {
issuerUri,
clientId,
publicUrl: import.meta.env.BASE_URL
};
});
xx
Last updated
Was this helpful?