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;| Option | Type | Default | Description |
|---|---|---|---|
ssoBaseUrl | string | — (required) | Base URL of the SSO service |
providerAddress | string | — (required) | Your provider address |
pollingInterval | number | 5000 | Polling interval in ms |
agentId | object | — | Agent ID configuration (see Agent Mode) |
agentId.enabled | boolean | false | Enable the Agent tab in the sign-in modal |
agentId.skillUrl | string | /ALIEN-SKILL.md | URL to your service’s ALIEN-SKILL.md |
dpop | object | — | Opt 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'] });generateDeeplink()
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
PollResponse —
authorization_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(): voidopenModal() / closeModal()
Control the built-in sign-in modal. This is the supported way to show
and hide SignInModal.
openModal(): void
closeModal(): voidconst { 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 | nullpollingInterval
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';
}| Prop | Type | Default | Description |
|---|---|---|---|
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 AlienSsoProvider — do not render it yourself.
Deprecated export — do not render manually.
SignInModaltakes no props and is controlled entirely through theuseAuth()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 — useuseAuth().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.enabledistrue, 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 modalTypes
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:
- An install command (
npx skills add alien-id/agent-id) with a copy button - 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.enabledistrue, 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. SignInButtonalways carries adata-agent-idattribute regardless ofagentId.enabled. When a skill URL is configured it readsIf you're an AI Agent, read {skillUrl} and follow the instructions to authenticate; otherwise it falls back toAgent 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
- Core API Reference — every client method and type
- React Integration guide — add sign-in to a React app
- Service Integration — add Agent ID verification to your backend
- Demo App — agent guestbook example