@microsoft/rayfin-auth
Auth client reference for sessions, storage options, refresh, sign-out, events, and provider integration points in Rayfin apps.
@microsoft/rayfin-auth manages Rayfin session lifecycle, token refresh, event listeners, and sign-out.
Most apps access it as client.auth on a RayfinClient rather than constructing it directly.
Microsoft Entra sign-in is provided by @microsoft/rayfin-auth-provider-fabric, which installs sessions on this same Auth instance.
Installation
npm install @microsoft/rayfin-auth @microsoft/rayfin-libAuth constructor
class Auth {
constructor(apiClient: ApiClient, options?: AuthOptions);
}Rayfin's auth SDK detects browser and non-browser runtimes.
When window is unavailable, it skips browser-only APIs such as localStorage unless you supply custom storage.
Use { storage: false } for Node.js scripts or server code where no browser storage should be touched.
import { Auth } from '@microsoft/rayfin-auth';
import { ApiClient } from '@microsoft/rayfin-lib';
const apiClient = new ApiClient({
baseUrl: 'https://<workload-api-base-url>',
publishableKey: '<publishable-key>',
});
const auth = new Auth(apiClient, { storage: false });
auth.attachToClient(apiClient);AuthOptions
interface AuthOptions {
storage?: AuthStorage | boolean;
storageKeyPrefix?: string;
persistSession?: boolean;
autoRefreshToken?: boolean;
multiTabSync?: boolean;
}
interface AuthStorage {
getItem(key: string): string | null | Promise<string | null>;
setItem(key: string, value: string): void | Promise<void>;
removeItem(key: string): void | Promise<void>;
clear?(): void | Promise<void>;
keys?(prefix: string): string[] | Promise<string[]>;
}| Option | Type | Default | Description |
|---|---|---|---|
storage | AuthStorage | boolean | Browser localStorage when available | Storage implementation, true for default storage, or false for memory-only sessions. |
storageKeyPrefix | string | Package default | Prefix for stored auth keys. |
persistSession | boolean | true | When false, skips all storage I/O and keeps sessions in memory. |
autoRefreshToken | boolean | true | When false, disables refresh timers and automatic refresh on 401. |
multiTabSync | boolean | Auto-detected in browsers | When false, disables StorageEvent cross-tab session sync. |
Session management
| Method | Signature | Description |
|---|---|---|
getSession | () => OpaqueSession | Returns the current public session synchronously. |
onSessionChange | (callback: (session: OpaqueSession | null) => void) => () => void | Subscribes to session changes and returns an unsubscribe function. |
hasRefreshToken | () => boolean | Returns whether a refresh token is available. |
refreshSession | () => Promise<TokenResponse> | Refreshes the session; concurrent refreshes share one in-flight request. |
attachToClient | (client: ApiClient) => void | Adds authorization injection and refresh handling to another ApiClient. |
destroy | () => void | Removes timers and listeners used by the Auth instance. |
startAutoRefresh | () => Promise<void> | Restarts scheduled refresh when autoRefreshToken: false is used. |
stopAutoRefresh | () => void | Stops scheduled refresh when autoRefreshToken: false is used. |
const session = auth.getSession();
const unsubscribe = auth.onSessionChange((nextSession) => {
console.log(nextSession?.isAuthenticated ?? false);
});
unsubscribe();Warning
The session-change callback is onSessionChange.
onAuthStateChange is not part of this SDK.
OpaqueSession
Session objects are opaque by design.
Gate UI logic on isAuthenticated or the presence of user, not on internal fields.
interface OpaqueSession {
user: User | null;
role?: string;
expiresAt?: Date;
isAuthenticated: boolean;
isAnonymous: boolean;
}
interface User {
id: string;
email: string;
role?: string;
emailVerified?: boolean;
emailVerifiedAt?: string | null;
}TokenResponse
interface TokenResponse {
accessToken: string;
tokenType: string;
expiresIn: number;
refreshToken?: string | null;
scope?: string | null;
}Provider packages consume TokenResponse internally to install a public OpaqueSession.
Application code should not copy Rayfin tokens between clients.
Sign-out methods
| Method | Signature | Description |
|---|---|---|
signOut | () => Promise<void> | Revokes the current access token and clears the local session. |
signOutAll | () => Promise<SignOutAllResponse> | Revokes every active session for the user and returns { count }. |
await auth.signOut();
const result = await auth.signOutAll();
console.log(`Revoked ${result.count} sessions`);Verification and settings methods
| Method | Signature | Description |
|---|---|---|
getJwks | () => Promise<JwksResponse> | Fetches public signing keys for services that validate Rayfin-issued JWTs themselves. |
getAuthSettings | () => Promise<AuthSettingsConfig> | Fetches public auth settings from the backend. |
Events
Use onSessionChange for UI state.
For narrower lifecycle handling, subscribe to session events with on(event, handler).
The signature uses the exported AuthEvent union:
import type { AuthEvent, OpaqueSession } from '@microsoft/rayfin-auth';
function on(event: AuthEvent, handler: (session: OpaqueSession) => void): () => void;The exported union contains every auth event emitted by the SDK. Fabric apps usually care about these session lifecycle events:
| Event | Fires when |
|---|---|
AUTH_LOGIN | A session is established. |
AUTH_LOGOUT | The user signs out. |
AUTH_REFRESH | The session refreshes. |
AUTH_SESSION_EXPIRED | The access token expires and no refresh token can recover the session. |
auth.on('AUTH_SESSION_EXPIRED', () => redirectToSignIn());React usage
import { useEffect, useState } from 'react';
import type { OpaqueSession } from '@microsoft/rayfin-auth';
import { auth } from './lib/rayfin';
export function useAuth() {
const [session, setSession] = useState<OpaqueSession | null>(null);
useEffect(() => {
setSession(auth.getSession());
return auth.onSessionChange(setSession);
}, []);
return {
session,
isAuthenticated: session?.isAuthenticated ?? false,
signOut: auth.signOut.bind(auth),
};
}Wire sign-in separately with ensureSignedInWithFabric, signInWithEntraToken, or the local development helper that installs a brokered token.
AuthApi provider integration
auth.getAuthApi() returns the lower-level AuthApi used by companion provider packages.
Rayfin 1.36 adds getBrokeredAuthorizeExternalUrl() so the external embed flow can tell the parent host which endpoint to call. New in 1.36
class AuthApi {
getBrokeredAuthorizeExternalUrl(): string;
exchangeVerificationCode(request: VerificationCodeExchangeRequest): Promise<TokenResponse>;
getAuthSettings(): Promise<AuthSettingsConfig>;
}Builders using ensureSignedInWithFabric() or createEmbedHost() do not call getBrokeredAuthorizeExternalUrl() directly.
The provider SDK includes it in the external-embed handshake.
Internal provider exports
The package also exposes @microsoft/rayfin-auth/_internal for first-party provider packages.
Do not use these helpers in application code:
function getAuthProviderClient(auth: Auth): ApiClient;
function runProviderSignIn<T>(auth: Auth, operation: () => Promise<T>): Promise<T>;
function createSessionFromTokenResponse(
auth: Auth,
tokenResponse: TokenResponse,
options?: { persistBeforeCommit?: boolean }
): Promise<OpaqueSession>;PKCE helper exports
The root package exports PKCE utilities used by auth providers:
function generateCodeVerifier(): string;
function generateCodeChallenge(verifier: string): Promise<string>;
function generateState(): string;Configuration and restart behavior
Auth is configured in rayfin.yml under services.auth.
After changing values such as enabled, allowedRedirectUris, fabric.enabled, or fabric.externalEntraExchange, apply the updated runtime settings with npm run dev or npx rayfin up.
A running backend does not infer local config changes until they are applied.
@microsoft/rayfin-data
The fluent GraphQL query and mutation API behind client.data — select, where, orderBy, pagination, and CRUD methods with exact signatures.
@microsoft/rayfin-auth-provider-fabric
Fabric auth provider reference for Fabric SSO, direct Entra token exchange, embedded handoff, and external embed support.