Skip to Content
View .md

Alien SSO React API Reference: AlienSsoProvider and useAuth

React bindings for Alien SSO. For the guided flow, see the React Integration guide; shared client types live in the Core API Reference.

AlienSsoProvider

Context provider that wraps your application, owns the AlienSsoClient instance and exposes authentication state to the hooks and components below.

function AlienSsoProvider(props: { config: AlienSsoProviderConfig; children: React.ReactNode; }): JSX.Element;
OptionTypeDefaultDescription
ssoBaseUrlstring— (required)Base URL of the SSO service
providerAddressstring— (required)Your provider address
pollingIntervalnumber5000Polling interval in ms
agentIdobjectAgent ID configuration (see Agent Mode)
agentId.enabledbooleanfalseEnable the Agent tab in the sign-in modal
agentId.skillUrlstring/ALIEN-SKILL.mdURL to your service’s ALIEN-SKILL.md
dpopobjectOpt into RFC 9449 DPoP sender-constrained tokens — see the Core API Reference

The config object is passed through to AlienSsoClient, so all core config fields (redirectUri, tokenStorage, allowInsecureSsoBaseUrl, …) are accepted here as well.

import { AlienSsoProvider } from '@alien-id/sso-react'; function App() { return ( <AlienSsoProvider config={{ ssoBaseUrl: 'https://sso.alien-api.com', providerAddress: 'your-provider-address', }} > <YourApp /> </AlienSsoProvider> ); }

useAuth

Hook that provides access to authentication state and methods. Must be used within AlienSsoProvider.

The hook returns the provider’s context value with the following shape. The context type itself is not exported — the package’s exported symbols are AlienSsoProvider, useAuth, AgentIdConfig, AlienSsoProviderConfig, SignInButton, SignInButtonProps and SignInModal:

{ client: AlienSsoClient; // from @alien-id/sso auth: { isAuthenticated: boolean; token?: string | null; tokenInfo?: TokenInfo | null; }; queryClient: QueryClient; generateDeeplink: () => Promise<AuthorizeResponse>; pollAuth: (pollingCode: string) => Promise<PollResponse>; exchangeToken: (authCode: string) => Promise<TokenResponse>; verifyAuth: () => Promise<boolean>; refreshToken: () => Promise<string | null>; logout: () => void; getAccessToken: () => string | null; openModal: () => void; closeModal: () => void; isModalOpen: boolean; pollingInterval: number; agentIdEnabled: boolean; agentIdSkillUrl?: string; }

The context also carries internal modal-slot members (modalSlotHolder, claimModalSlot, releaseModalSlot) used to deduplicate SignInModal instances — these are @internal and not part of the public API.

client

Direct access to the underlying AlienSsoClient instance.

const { client } = useAuth(); const token = client.getAccessToken();

auth

Current authentication state. The type is internal (not exported):

{ isAuthenticated: boolean; token?: string | null; tokenInfo?: TokenInfo | null; }

tokenInfo holds the verified OIDC claims — see TokenInfo in the core reference for the full claim list.

const { auth } = useAuth(); if (auth.isAuthenticated) { console.log('User ID:', auth.tokenInfo?.sub); console.log('Token:', auth.token); console.log('Expires:', new Date(auth.tokenInfo!.exp * 1000)); }

queryClient

React Query client instance for advanced usage.

const { queryClient } = useAuth(); queryClient.invalidateQueries({ queryKey: ['some-key'] });

Generates the authentication deep link and polling code. Resolves to an AuthorizeResponse (deep_link, polling_code, expired_at).

async generateDeeplink(): Promise<AuthorizeResponse>

pollAuth()

Polls for the authorization status. Resolves to a PollResponseauthorization_code is only present when status is 'authorized'.

async pollAuth(pollingCode: string): Promise<PollResponse>

exchangeToken()

Exchanges the authorization code for tokens and updates the auth state on success. Tokens are persisted via the configured token storage (localStorage by default in browsers). Resolves to a TokenResponse.

async exchangeToken(authCode: string): Promise<TokenResponse>

verifyAuth()

Verifies the current access token by calling /oauth/userinfo and updates the auth state with the result. Resolves to true when the token is valid, false otherwise. The underlying client refreshes the token automatically on a 401. Unlike the core client’s verifyAuth(), which resolves to the userinfo payload or null, the hook resolves to a boolean.

async verifyAuth(): Promise<boolean>

refreshToken()

Refreshes the access token using the stored refresh token. Resolves to the refreshed access token, or null when the refresh failed — in that case the auth state is cleared and the user is logged out.

async refreshToken(): Promise<string | null>
const { refreshToken, auth } = useAuth(); // Proactive refresh before the token expires if (auth.tokenInfo && auth.tokenInfo.exp * 1000 < Date.now() + 60000) { const accessToken = await refreshToken(); if (!accessToken) { // Redirect to login } }

logout()

Sets the auth state to unauthenticated and clears all stored authentication data: tokens from the configured token storage and the PKCE/state/nonce values from sessionStorage.

logout(): void

openModal() / closeModal()

Control the built-in sign-in modal. This is the supported way to show and hide SignInModal.

openModal(): void closeModal(): void
const { openModal, closeModal, isModalOpen } = useAuth(); <button onClick={openModal}>Sign In</button>; { isModalOpen && <button onClick={closeModal}>Cancel</button>; }

isModalOpen

Boolean indicating whether the sign-in modal is currently open.

getAccessToken()

Pulls the current access token from storage at call time. Returns null when no session exists. Equivalent to auth.token, but reads on demand instead of from render state.

getAccessToken(): string | null

pollingInterval

Polling interval (ms) used by the modal’s authorization wait loop. Same value as client.pollingInterval.

agentIdEnabled / agentIdSkillUrl

Resolved Agent ID settings from the provider config: whether the Agent tab is enabled (default false) and the skill URL (default /ALIEN-SKILL.md). See Agent Mode.

Components

SignInButton

Pre-styled button component that opens the sign-in modal. The SignInButtonProps interface is exported.

function SignInButton(props: SignInButtonProps): JSX.Element; interface SignInButtonProps { variant?: 'default' | 'short'; color?: 'dark' | 'light'; }
PropTypeDefaultDescription
variant'default' | 'short''default''short' renders a compact icon-only button
color'dark' | 'light''light'Color scheme
import { SignInButton } from '@alien-id/sso-react'; function LoginPage() { return ( <div> <h1>Welcome</h1> <SignInButton variant="default" color="light" /> </div> ); }

SignInModal

Modal component for the authentication flow. Automatically rendered by AlienSsoProviderdo not render it yourself.

Deprecated export — do not render manually. SignInModal takes no props and is controlled entirely through the useAuth() context. The provider already renders one instance, and an internal slot mechanism guarantees only one instance renders — the first to claim the slot — while the rest render nothing. The export is kept for backward compatibility and may become internal in a future major version — use useAuth().openModal() / closeModal() instead.

The modal:

  • Displays a QR code with the deep link for human authentication
  • Handles polling automatically
  • Shows loading and error states
  • Exchanges the token on successful authentication
  • Updates auth state when complete
  • When agentId.enabled is true, shows a Human/Agent tab switcher with a sliding indicator
  • The Agent tab displays the skill install command with a copy button and setup instructions
const { openModal, closeModal } = useAuth(); openModal(); // Open modal closeModal(); // Close modal

Types

Shared client types are defined once in the core reference — see AuthorizeResponse, PollResponse, TokenResponse, UserInfoResponse and TokenInfo. The React package adds:

AlienSsoProviderConfig

The provider’s config prop type — the core client config plus the React-only agentId block. Both AlienSsoProviderConfig and AgentIdConfig are exported:

type AlienSsoProviderConfig = AlienSsoClientConfig & { agentId?: AgentIdConfig; }; type AgentIdConfig = { enabled: boolean; skillUrl?: string; };

See the Core API Reference for the AlienSsoClientConfig fields (redirectUri, tokenStorage, allowInsecureSsoBaseUrl, dpop, …). The auth-state and context types are internal (not exported) — their shapes are documented under useAuth.

Usage Examples

Basic Authentication

import { AlienSsoProvider, useAuth, SignInButton } from '@alien-id/sso-react'; function App() { return ( <AlienSsoProvider config={{ ssoBaseUrl: 'https://sso.alien-api.com', providerAddress: 'your-provider-address', }} > <Dashboard /> </AlienSsoProvider> ); } function Dashboard() { const { auth, logout } = useAuth(); if (!auth.isAuthenticated) { return <SignInButton />; } return ( <div> <p>Welcome! User ID: {auth.tokenInfo?.sub}</p> <button onClick={logout}>Logout</button> </div> ); }

Protected Route

import { useAuth } from '@alien-id/sso-react'; import { Navigate } from 'react-router-dom'; function ProtectedRoute({ children }: { children: React.ReactNode }) { const { auth } = useAuth(); if (!auth.isAuthenticated) { return <Navigate to="/login" replace />; } return <>{children}</>; }

Token Refresh on API Calls

import { useAuth } from '@alien-id/sso-react'; function useApi() { const { auth, refreshToken, logout } = useAuth(); async function fetchWithAuth(url: string) { // Check if token is expiring within 1 minute if (auth.tokenInfo && auth.tokenInfo.exp * 1000 < Date.now() + 60000) { const accessToken = await refreshToken(); if (!accessToken) { logout(); throw new Error('Session expired'); } } return fetch(url, { headers: { Authorization: `Bearer ${auth.token}`, }, }); } return { fetchWithAuth }; }

Custom Sign-In Flow

import { useAuth } from '@alien-id/sso-react'; import { useState, useEffect } from 'react'; import { QRCodeSVG } from 'qrcode.react'; function CustomSignIn() { const { generateDeeplink, pollAuth, exchangeToken, auth } = useAuth(); const [deepLink, setDeepLink] = useState<string | null>(null); const [pollingCode, setPollingCode] = useState<string | null>(null); const handleSignIn = async () => { const response = await generateDeeplink(); setDeepLink(response.deep_link); setPollingCode(response.polling_code); }; useEffect(() => { if (!pollingCode) return; const interval = setInterval(async () => { const response = await pollAuth(pollingCode); if (response.status === 'authorized') { clearInterval(interval); await exchangeToken(response.authorization_code!); setDeepLink(null); setPollingCode(null); } else if ( response.status === 'rejected' || response.status === 'expired' ) { clearInterval(interval); setDeepLink(null); setPollingCode(null); } }, 5000); return () => clearInterval(interval); }, [pollingCode]); if (deepLink) { return <QRCodeSVG value={deepLink} />; } return <button onClick={handleSignIn}>Sign In</button>; }

Token Verification on Mount

import { useAuth } from '@alien-id/sso-react'; import { useEffect } from 'react'; function App() { const { verifyAuth, auth } = useAuth(); useEffect(() => { if (auth.token) { verifyAuth(); } }, []); // Rest of your app }

Agent Mode

When agentId.enabled is set in the config, the sign-in modal shows a Human/Agent tab switcher. The Agent tab guides users to install the Agent ID skill and authenticate their AI agent.

<AlienSsoProvider config={{ ssoBaseUrl: 'https://sso.alien-api.com', providerAddress: 'your-provider-address', agentId: { enabled: true, skillUrl: '/ALIEN-SKILL.md', // optional, this is the default }, }} > <App /> </AlienSsoProvider>

The Agent tab displays:

  1. An install command (npx skills add alien-id/agent-id) with a copy button
  2. Steps: install Agent ID, paste the service URL to the agent, authenticate

Two discovery hooks surface for AI agents browsing your app, with distinct text and gating:

  • When agentId.enabled is true, the provider injects a <meta name="alien-agent-id" content="FOR AI AGENTS: This service supports Alien Agent ID authentication. Read the skill at: {skillUrl} for instructions"> tag.
  • SignInButton always carries a data-agent-id attribute regardless of agentId.enabled. When a skill URL is configured it reads If you're an AI Agent, read {skillUrl} and follow the instructions to authenticate; otherwise it falls back to Agent ID isn't set up.

On the server side, verify agent requests using @alien-id/sso-agent-id. See the Service Integration Guide for verification setup and discovery manifest hosting.

For a working example, see the Agent ID Demo App.

Error Handling

All async methods can throw errors. Handle them appropriately:

const { generateDeeplink, exchangeToken, refreshToken } = useAuth(); try { const { deep_link, polling_code } = await generateDeeplink(); } catch (error) { console.error('Failed to generate deep link:', error); } try { await exchangeToken(authCode); } catch (error) { console.error('Token exchange failed:', error); } try { const accessToken = await refreshToken(); if (!accessToken) { // Handle refresh failure (user logged out automatically) } } catch (error) { console.error('Refresh error:', error); }

Next Steps

Last updated on