The User Object
Coming in oidc-spa v10.3. This feature has not been released yet.
Access the User in Your App
Once configured, your custom user model is available throughout your frontend code.
import { prOidc } from "./oidc";
export async function getGreeting() {
const oidc = await prOidc;
if (!oidc.isUserLoggedIn) {
return "Hello!";
}
const { user } = await oidc.getUser();
return `Hello ${user.displayName}!`;
}In a component where login is already enforced:
import { useOidc } from "../oidc";
export function Greeting() {
const { user } = useOidc({ assert: "user logged in" });
return <p>Hello {user.displayName}!</p>;
}In browser code outside a React component:
import { getOidc } from "./oidc";
export async function getGreeting() {
const oidc = await getOidc({ assert: "user logged in" });
const { user } = await oidc.getUser();
return `Hello ${user.displayName}!`;
}The user object is your application's model of the signed-in person. Shape it around what the frontend needs to render.
Implement createUser
Keep src/oidc.user.ts focused on translating identity data into the model consumed by your UI:
Define a
Usertype containing exactly the information your UI needs.Implement
createUserto gather that information and return aUser.
Here are some example of the sources you can use to construct the user object.
The decoded payload of the ID token is the simplest source when it already contains everything your UI needs.
A dedicated endpoint is often the best option when the model depends on your application's database.
The backend validates the access token, identifies the caller, loads the corresponding record, and returns an application-specific object.
Some providers expose roles or groups only in a JWT access token. This Keycloak-shaped example turns those roles into UI-friendly fields.
OAuth clients should normally treat access tokens as opaque. Use this pattern only when your provider documents that the access token is a JWT with a stable claim shape. decodeJwt() decodes the payload; it does not validate the token. Never use this client-side result to protect backend data.
fetchUserInfo() calls the standard OIDC UserInfo endpoint discovered from your provider's metadata and attaches the current access token.
No UserInfo request is made unless you call fetchUserInfo(). The available claims still depend on your requested scopes and provider configuration.
Provider-specific APIs can expose information that is not available through standard OIDC claims. For Keycloak, oidc-spa includes a typed helper for the account profile.
The endpoint must be enabled and accessible to your client. Keep this provider-specific code inside createUser so the rest of the UI remains provider-agnostic.
Connect It to Your Adapter
createUser is framework-independent. Register it when configuring oidc-spa. If your project supports mock mode, register user_mock alongside it.
When bootstrapOidc() receives { implementation: "mock", ... }, it uses this user_mock by default. You can override it by passing a different user_mock to that bootstrap call.
When bootstrapOidc() receives { implementation: "mock", ... }, it uses this user_mock by default. You can override it by passing a different user_mock to that bootstrap call.
Keep the User Up to Date
oidc-spa runs createUser when it first builds the signed-in user's model. It runs createUser again when it detects meaningful changes in the decoded ID token or the decoded payload of a JWT access token. Routine rotation-only changes, such as new iat or exp values, do not rebuild the user.
When createUser reads from an external source, such as your API, UserInfo, or a provider-specific profile endpoint, oidc-spa cannot detect changes to that source. After an update succeeds, call refreshUser() to rebuild the user.
With the real implementation, refreshUser() renews the tokens, forces createUser to run again, notifies user subscribers, and resolves to the refreshed User. In mock mode, it simply resolves to the configured user_mock.
Call refreshCurrentUser() after the external update has completed.
Components that read user through useOidc() re-render with the refreshed value.
Was this helpful?