Rayfin

@microsoft/rayfin-auth

The Auth client surface — signOut, session management, and the OpaqueSession shape — with exact signatures from the SDK.

@microsoft/rayfin-auth implements Rayfin's authentication client: session lifecycle management, token refresh, and sign-out. You normally reach it through client.auth on a RayfinClient rather than constructing it yourself. Signing in happens through @microsoft/rayfin-auth-provider-fabric, which operates on this same Auth instance — Fabric SSO (Entra ID) is the only supported sign-in method.

Installation

npm install @microsoft/rayfin-auth

The Auth class

class Auth {
  constructor(apiClient: ApiClient, options?: { storage?: AuthStorage | boolean; storageKeyPrefix?: string });
}

interface AuthStorage {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
  clear(): void;
}

Rayfin's own SDK auto-detects Node.js, React Native, and Electron, skipping browser-only APIs (like localStorage) when window is undefined — the isomorphic design means the same Auth code runs in any of these environments without crashing.

Signing out

MethodSignatureDescription
signOut() => Promise<void>Revokes the current access token and clears the local session.
signOutAll() => Promise<SignOutAllResponse>Revokes every active session for the user (all devices). Returns { count }.
await auth.signOut();

Session management

MethodSignatureDescription
getSession() => OpaqueSessionReturns the current session synchronously — not a Promise.
onSessionChange(callback: (session: OpaqueSession | null) => void) => () => voidSubscribes to session changes; returns an unsubscribe function.
hasRefreshToken() => booleanWhether a refresh token is available for refreshSession().
refreshSession() => Promise<TokenResponse>Refreshes using the stored refresh token. Concurrent calls share one in-flight request.
const session = auth.getSession(); // no await — synchronous
if (session.isAuthenticated) {
  console.log(session.user?.email);
}

const unsubscribe = auth.onSessionChange((session) => {
  setCurrentSession(session);
});
// later: unsubscribe();

Warning

The session-change callback is onSessionChange. onAuthStateChange does not exist on the Rayfin auth client — see Known limitations.

Session shape

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;
}

Verifying tokens

MethodSignatureDescription
getJwks() => Promise<JwksResponse>Public keys for verifying Rayfin-issued JWTs, for services that validate tokens themselves.

Events

on(event, handler) subscribes to a specific named AuthEvent (in addition to the general onSessionChange), returning an unsubscribe function. Events relevant to session lifecycle — independent of how the user signed in — include 'AUTH_LOGIN', 'AUTH_LOGOUT', 'AUTH_REFRESH', and 'AUTH_SESSION_EXPIRED':

function on(event: AuthEvent, handler: (session: OpaqueSession) => void): () => void;

auth.on('AUTH_SESSION_EXPIRED', () => redirectToLogin());

React usage

import { useState, useEffect } from 'react';
import { auth } from './lib/rayfin';
import type { OpaqueSession } from '@microsoft/rayfin-auth';

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 up sign-in separately with ensureSignedInWithFabric, which takes this same auth instance.

Configuration and restart behavior

Auth is configured in rayfin.yml under services.auth (enabled, allowedRedirectUris, fabric.enabled). After changing any of these values, restart the backend (npx rayfin up) so the updated endpoints are exposed — the running server does not pick up rayfin.yml changes on its own. See Known limitations.

Something wrong on this page?Report an issueEdit this page

On this page