React library for **authentication and authorization** based on **OpenID Connect (OIDC)**. It supports multiple providers (Google, Keycloak, Microsoft, etc.), **Authorization Code** flow with **PKCE**, in-memory token storage, and automatic token refresh.
npm install @iad-os/react-ghost-authReact library for authentication and authorization based on OpenID Connect (OIDC). It supports multiple providers (Google, Keycloak, Microsoft, etc.), Authorization Code flow with PKCE, in-memory token storage, and automatic token refresh.
---
``bash`
npm install @iad-os/react-ghost-auth react
Peer dependency: react >= 16.14.0
---
Each provider is a ProviderOptions object:
| Field | Type | Description |
|-------|------|-------------|
| issuer | string | OIDC issuer URL (e.g. https://auth.example.com/realms/my-realm) |name
| | string | Provider name (e.g. "Keycloak") |client_id
| | string | Application client ID |client_secret
| | string | (optional) Client secret (for confidential clients) |redirect_uri
| | string | Redirect URI after login |redirect_logout_uri
| | string | Redirect URI after logout |requested_scopes
| | string | Requested scopes (e.g. openid profile email) |pkce
| | boolean | (optional) Use PKCE (recommended for SPAs) |defualt
| | boolean | (optional) Default provider when issuer is not passed |access_type
| | string | (optional) e.g. offline for refresh token |kc_idp_hint
| | string | (optional) Keycloak identity provider hint |
`ts
import type { AuthenticationConfig } from '@iad-os/react-ghost-auth';
const config: AuthenticationConfig = {
providers: [
{
issuer: 'https://keycloak.example.com/realms/my-realm',
name: 'Keycloak',
client_id: 'my-app',
redirect_uri: 'https://my-app.example.com/callback',
redirect_logout_uri: 'https://my-app.example.com',
requested_scopes: 'openid profile email',
pkce: true,
defualt: true,
},
],
};
`
---
Wrap your app (or the part that uses auth) with the provider and pass the config and callbacks.
`tsx
import AuthenticationProvider from '@iad-os/react-ghost-auth';
function App() {
const config = { providers: [/ ... /] };
return (
onRoute={(route, overrided) => {
// Called after login/logout with the URL to use (e.g. for the router)
window.history.replaceState({}, '', route);
}}
onError={(message) => console.error(message)}
refreshTokenBeforeExp={60}
overrideRedirectUri={(loc) => ${loc.origin}${loc.pathname}}`
enableLog={process.env.NODE_ENV === 'development'}
>
);
}
AuthenticationProvider props:
| Prop | Type | Default | Description |
|------|------|--------|-------------|
| config | AuthenticationConfig | required | Config with the list of providers |children
| | ReactNode | required | App content |onRoute
| | (route, overrided) => void | required | Callback with the route to use after login/logout |onError
| | (message: string) => void | optional | Callback for errors (e.g. from provider) |refreshTokenBeforeExp
| | number | 0 | Seconds before token expiry to trigger automatic refresh (0 = disabled) |overrideRedirectUri
| | (location) => string | optional | Override for redirect_uri (e.g. for hash-based SPA) |enableLog
| | boolean | false | Enable debug logging in console |
---
#### RequireAuth
Renders children only when the user is authenticated; otherwise renders loggedOut. Optionally triggers autologin.
`tsx
import { RequireAuth } from '@iad-os/react-ghost-auth';
| Prop | Type | Default | Description |
|------|------|--------|-------------|
|
children | ReactNode | required | Content when logged in |
| loggedOut | ReactNode | optional | Content when not logged in |
| autologin | boolean | false | If true, in LOGGED-OUT state calls autologin() (starts login flow) |---
####
LoggedRenders one content when logged in and another when not (no redirect, UI only).
`tsx
import { Logged } from '@iad-os/react-ghost-auth'; in={
Welcome
}
out={Not authenticated
}
/>
`| Prop | Type | Description |
|------|------|-------------|
|
in | ReactNode | Content when logged in |
| out | ReactNode | optional – Content when not logged in |---
####
LoggingRenders content only during the “logging” phase (return from provider with
code, token exchange in progress).`tsx
import { Logging } from '@iad-os/react-ghost-auth'; } />
`| Prop | Type | Description |
|------|------|-------------|
|
in | ReactNode | Content shown during token exchange |---
####
AutoLoginWhen in LOGGED-OUT state and a “current” provider exists (e.g. from a previous session), calls
login(issuer); when status is LOGIN, can render children (e.g. “Redirecting to login…” screen).`tsx
import { AutoLogin } from '@iad-os/react-ghost-auth';
Redirecting to login...
`| Prop | Type | Description |
|------|------|-------------|
|
children | ReactNode | optional – Content shown when in LOGIN phase (e.g. redirect message) |---
$3
####
useAuthentication()Exposes auth state and actions.
`tsx
import { useAuthentication } from '@iad-os/react-ghost-auth';function MyComponent() {
const {
login, // (issuer?: string) => Promise
logout, // () => Promise
autologin, // () => void – sets status to LOGIN
isAuthenticated, // () => boolean
status, // 'INIT' | 'LOGIN' | 'LOGGING' | 'LOGGED-IN' | 'LOGGED-OUT' | 'LOGOUT'
refreshToken, // () => Promise
token, // TokenResponse | undefined
getCurrentProvider, // () => ProviderOptions | undefined
providers, // ProviderOptions[]
} = useAuthentication();
return (
{status === 'LOGGED-IN' ? (
) : (
)}
);
}
`---
####
useToken()Returns
token and refreshToken only when the user is authenticated; otherwise throws.`tsx
import { useToken } from '@iad-os/react-ghost-auth';function ProtectedApi() {
const { token, refreshToken } = useToken();
// token: TokenResponse, refreshToken: () => Promise
return Access token: {token.access_token.slice(0, 20)}…;
}
`Use it only inside a protected tree (e.g. under
RequireAuth or after checking isAuthenticated()).---
####
useUserInfoDecodes the
id_token (JWT) payload and returns it typed. Throws if not authenticated or no id_token.`tsx
import { useUserInfo } from '@iad-os/react-ghost-auth';type MyClaims = { sub: string; email?: string; name?: string };
function Profile() {
const user = useUserInfo();
return {user.name ?? user.sub};
}
`---
$3
Use when you need to handle login/logout/refresh outside React components (e.g. from services or after mount):
`ts
import { tokenService } from '@iad-os/react-ghost-auth';// Login (redirects to provider)
await tokenService.login({ issuer: 'https://...' });
await tokenService.login(); // uses default provider
// Logout (redirects to provider end session)
await tokenService.logout();
// Refresh token
const newToken = await tokenService.refreshToken();
// Current token (from store)
const token = tokenService.getToken();
`-
login({ issuer?, overrideRedirectUri? }) – starts the OIDC flow.
- logout() – clears state and redirects to provider logout.
- refreshToken() – refreshes the token using the refresh token.
- getToken() – returns the current TokenResponse or undefined.The
code-to-token exchange (after redirect) is handled internally by AuthenticationProvider via tokenService.retriveToken; you typically do not need to call it yourself.---
Exported types
-
AuthenticationConfig – { providers: ProviderOptions[] }
- TokenResponse – access_token, refresh_token, id_token, expires_in, etc.
- ProviderOptions – see table above.---
Flow overview
1. User clicks “Login” →
login() (or tokenService.login()) is called.
2. The app stores in session state, code_verifier, redirect_uri, current_provider_issuer and redirects to the provider’s authorization endpoint.
3. User authenticates at the provider and is redirected back to your redirect_uri with ?code=...&state=....
4. AuthenticationProvider detects code and state, calls tokenService.retriveToken({ code, code_verifier }), stores the token in the store, and calls onRoute.
5. If refreshTokenBeforeExp > 0, an automatic refresh is scheduled before token expiry after login.
6. To sign out: logout() clears state and redirects to the provider’s end session.---
Build
`bash
npm run build
`Output in
dist/` (CommonJS and ESM).