Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Gracefully handle authentication issues
What happens if the OIDC server is down, or if your OIDC server isn't properly configured?
By default, , when there is an error with the OIDC initialization your website will load with the user unauthenticated.
This allows the user to at least access parts of the application that do not require authentication. When the user clicks on the login button (triggering the login()
function), a browser alert is displayed, indicating that authentication is currently unavailable, and no further action is taken.
You can customize this behavior. An initializationError
object is present on the oidc
object if an error occurred.
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.
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:
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.
xx
You probably don't need to do it. The token refresh is handled automatically for you, however you can manually trigger a token refresh:
You can also track when the token are being refreshed:
Or directly in your component:
In some cases, you might want to perform some operation to initialize the user's session. This could involve calling a special API endpoint or clearing some cached values in the local storage.
What you don't want, however, is to run this every time the user refreshes the page.
To help you determine if the session should be initialized, you can leverage the isNewBrowserSession
property that is available when the user is logged in.
You can also do this in your React component (although it's maybe not the best approach)
The primary usecase for a library like oidc-spa is to use it to authenticate a REST, tRPC, or Websocket API.
Let's see a very basic REST API example:
Initialize oidc-spa and expose the oidc instance as a promise:
Create a REST API Client that adds the OIDC Access Token as Autorization header to every HTTP request:
Initialize the React adapter of oidc-spa and expose the prOidc object, a promise of the vanilla OIDC API:
Create a REST API Client that adds the OIDC Access Token as Autorization header to every HTTP request:
Using your REST API client in your REACT components:
This example is purposefully very basic to minimize noise but in your App you might want to consider using solutions like tRPC (if you have JS backend) and TanStack Query.
If you're implementing a JavaScript Backend (Node/Deno/webworker) oidc-spa also exposes an utility to help you validate and decode the access token that your client sends in the authorization header. Granted, this is fully optional feel free to use anything else. Let's assume we have a Node.js REST API build with Express or Hono. You can create an oidc file as such:
Then you can enforce that some endpoints of your API requires the user to be authenticated, in this example we use Hono:
If you're looking for a comprehensive Backend+Frontend example you can refer to Insee's project
The app is live here:
The frontend (Vite project):
The backend (Node TODO App REST API):
There are known issues with the v6 of oidc-spa. I'm actively working on it.
Before starting be aware that oidc-spa is not suited for Next.js or any other framwork that involves server side rendering.
If you are using Next the closer alternative is to use (with if you are using Keycloak). See .
If you're having issues don't hesitate to !
Let's install in your project:
Create the oidc-callback. file in your public/ directory:
On your OIDC Server, in your client configuration, define Valid Redirect URIs: https://oidc-callback.htm, http://localhost:/oidc-callback.htm. .
In this section we assume you are using Keycloak. If you are using another authentication server you'll have to addapt the queryParameter
provided.
When your user is logged in, you can provide a link to redirect to Keycloak so they can manage their account.
There is thee main actions:
UPDATE_PASSWORD: Enables the user to change their password.
UPDATE_PROFILE: Enable the user to edit teir account information such as first name, last name, email, and any additional user profile attribute that you might have configured on your Keycloak server.
delete_account: (In lower case): This enables the user to delete he's account. You must enable it manually on your Keycloak server Admin console. See .
Let's, as an example, how you would implement an update password button:
For certain use cases, you may want a mock adapter to simulate user authentication without involving an actual authentication server.
This approach is useful when building an app where user authentication is a feature but not a requirement. It also proves beneficial for running tests or in Storybook environments.
Vite + TypeScript + React + Tanstack Router
The example setup is live here:
Run it locally with:
Automatically logging out your user after a set period of inactivity on your app (they dont move the mouse or press any key on the keyboard for a while)
Important to understand: This is a policy that is enforced on the identity server. Not on in the application code!
The auto logout is defined by the lifespan of the refresh token.
For example, if you're using Keycloak and you want an auto disconnect after 5 minutes of inactivity you would set the SSO Session Idle to 5 minutes. See .
If you can't configure your OIDC server you can still enforce auto logout like so:
Note that this parameter is marked as unsafe because what happens if the user closes the tab? He will be able to return a while back and still be logged in. oidc-spa can't enforce a security policy when it's not running. Only the identity server can.
TODO
TODO
Enforce authentiaction everywhere on your app
If there is no part of your app that can be browsed without being logged which is typically the case for application like dashboard or administration pannel, you can make oidc-spa automatically redirect users to the login pages when they are not authenticated.
In this mode you don't have to:
Check isUserLoggedIn
, it will always be true.
(React) Use useOidc({ assert: "user logged in" })
you know that's the case.
Under construction
issuerUri
and clientId
Oidc-spa need to two parameter to connect with your Keycloak instance, the issuerUri and the clientId.
issuerUri
In Keycloak, the OIDC issuer uri is formatted as such:
https://<KC_DOMAIN><KC_RELATIVE_PATH>/realms/<REALM_NAME>
<KC_DOMAIN>: The domain of your Keycloak server, example: auth.my-company.com.
<KC_RELATIVE_PATH>: The sub path under your which your Keycloak is hosted. By default, in recent version of keycloak it's "" (empty string). On older Keycloak version it used to be "/auth" by default. Check how you Keycloak server is configured. This parrameter is usualy set by an environement variable. Example -e KC_HTTP_RELATIVE_PATH=/auth
.
<REALM_NAME>: The name of your realm. Example: myrealm. One important note is that you should always create create a realm for your organization and never use the master realm. To create a realm navigate to https://<DOMAIN><KC_RELATIVE_PATH>/admin/master/console login as an administrator, click on the select at the top left corner of the page, click on "Create a new Realm", give it a name, save.
clientId
The client it is usualy something like 'myapp'. Let's see how to create a client suitable for your SPA.
Connect to your Keycloak Admin Console: https://<KC_DOMAIN><KC_RELATIVE_PATH>/admin/master/console
Login as an admin
Using the select input in the top left corner, navigate to your realm.
In the left pannel click on Clients.
Click on Create Client.
Fill in the Client ID, for example myapp, click on next.
Make sure Client authentication is off and that Standard Flow is checked in, click next.
Set two Valid Redirect URIs: https://<APP_DOMAIN><BASE_URL>oidc-callback.htm and http://localhost:<DEV_PORT>/oidc-callback.htm.
<APP_DOMAIN>: Examples: https://my-company.com or https://app.my-company.com. Note that in order to avoid issues related to the end of third party cookies it's important that <APP_DOMAIN> and <KC_DOMAIN> be hosted under the same root domain (my-company.com).
<BASE_URL>: Examples: "/" or "/dashboard/".
<DEV_PORT>: Example: 5173 (Default port of the Vite dev server)
If you are not using using the oidc-callbak.htm file, remove the /oidc-callback.htm portion of the urls, there should be no trailing slashes at the end.
Feel free to fill in the other field but they are not required. Click Save, you're done!
One important policy you want to define is how often you want your user to have to authenticate again when they visite your site. Note that the parameter that we will configure here do not affect the lifespawn of the access token that remains 5 minuts by default. What we are tweaking here is for how long Keycloak will keep the session active and that is reflected in the livespawn of the reflesh token, this how oidc-spa is able to learn about it.
Let's see the good defaults for the two more common scenario:
For thoses kind of web applications, you want the user to have to login again each time they visit your app. You also want them to be automatically loged out after .
To enforce this policy you want to:
Disable the "Remeber Me" checkbox when logging in:
Select your realm
In the left menu navigate to realm settings
Go to the Login tab
Set "Remember Me" to Off
Set the session Idle time:
In the Realm settings go to the Session Tab
Set Session idle: 5min
Session idle MAX: 14 days, if your user is actively using your app for days, there's no reason to desconect them.
You can display a coundown timer before auto logout with:
For thoses kind of app you don't want your user to have to authenticate every other day. Take YouTube for example, each time you reach the site your logged in already, we want this type of behaviour.
To enable it
Enable the possibility for your user to check a "Remeber Me" checkbox when logging in:
Select your realm
In the left menu navigate to realm settings
Go to the Login tab
Set "Remember Me" to On
Set the session idle: You want the users that haven't checked "Remember Me" to have to re authenticate once every 2 week.
In the Realm settings go to the Session Tab
Set Session idle and Session Idle Max to 14 days
Set the session idle Remember Me: You want the users that have explicitely checked "Remeber Me" when logging in to only have to authenticate again once every year.
In the Session tab of the Realm settings, set Session idle Remeber Me and Session Idle Max Remember me to 356 days.
By default on Keycloak, users are not allowed to delete their accout.
If you try to implement a delete account button, when clicking on it, your users will be granted with an "action non permited" screen.
To enable it:
In the left bar navigate to Autentication -> Required Action -> "Delete Account" Enabled: On
In the left bar navigate to Realm Setting -> User Registration -> Default Roles -> Assign Role -> Filter by client -> select Delete Account and click on assign.
We have specific configuration instructions for the following Auth Software:
If you are using another OIDC Provider, no problem keep reading.
Here are the key takeways for configuring.
Create a OpenID Connect client with Standard Flow AKA Authorization code flow. It's the default setting.
Disable client authentication (public client). We don't want to rely on client secret, it would be instantaneously leaked by your SPA.
In the configuration of the client, you only need a single valid redirect URIs. Let's assume that the home of your page is https://my-app.com you would set https://my-app.com/oidc-callback.htm, if your app is hosted under a sub path like https://my-app.com/dashboard, use https://my-app.com/dashboard/oidc-callback.htm. You may also want to add http://localhost:/oidc-callback.htm for local developement.
Valid post logout redirect: Same as the Valid Redirec URIs
Web Ogigins: http://my-app.com, http://localhost:5173
TL;DR; It's mostly inconsequential.
Google is ending third-party cookies for all Chrome users in 2024 and are already disabled by default in Safari.
Let's see how it might affect you.
First of all, if your identity server and your app shares the same root domain you are not affected.
Example, if you are in the case:
Your app is hosted at www.example.com or dashboard.example.com
Your identity server, for example Keycloak, is hosted at: auth.example.com
You are not affected ✅. Indeed Both www.example.com, dashboard.example.com and auth.example.com shares the same root domain: example.com. On the other end, if you are in the folowing case:
You app is hosted at www.examples.com or dashboard.example.com
Your identity server is hosted at: auth.sowhere-else.com
Let's see how third party cookies phase out will affect you:
You will see a console warning "Third-party cookie will be blocked" in the console in production.
If a user that is authenticated close the tab of your app or close the browser and open your site again a while later. With third party cookies enabled and assuming he's session haven't expired yet he will be automaticall logged in. With third party cookies disabled your website will load in unautenticated mode. If he clicks on the login button this will trigger a full reload and he will be authenticated without having to enter he's credential again.
Conex resources:
reCaptcha is not directly related to oidc-spa since the cookie it sets is on the thegister page (so outside of your app). Anyway, since it's a connex concern:
And why it's not supposed to be read on the client side.
You might be surprised or even frustrated by the fact that oidc-spa only provides the decoded id token but not the decoded access token.
Infact the access token is supposed to be opaque for the client application is to be used only as an authentication key such as a Bearer token for an API.
As per the OIDC standard the access token is not even required to be a JWT!
But worry not, everything that you need is probably in the id token, if there is something missing in your id token that is present in your access token there is an explicit policy on your identity server in place that strips this information out. Zod is stripping out all the claims that are not specified in the schema. This might have led you to believe that there is less information in the id token than what actually is.
If, however, you still want to access the informations in the access token you can do it with:
Feeling a bit lost? Have a question? A feature request? Reach out on Discrord!
Backers of the project
Very little change in the API.
The public/silent-sso.html -> to public/silent-sso.htm ()
Use getOidc()
instead or prOidc
(React API)
If you are using the mock with the vanilla API (not React)