Lightweight React authentication UI components with bearer token support and Smartlinks SDK integration
npm install @proveanything/smartlinks-auth-uibash
npm install @smartlinks/auth-ui @proveanything/smartlinks
`
Note: This package requires the Smartlinks SDK (@proveanything/smartlinks) as a peer dependency.
Quick Start
$3
Initialize the Smartlinks SDK at the top level of your application:
`tsx
// src/App.tsx or src/main.tsx
import * as smartlinks from '@proveanything/smartlinks';
// Initialize the SDK before your app renders
smartlinks.initializeApi({
baseUrl: 'https://smartlinks.app/api/v1',
proxyMode: false, // Set to true if running in iframe
});
`
$3
Add this import to your app's entry point:
`tsx
import '@smartlinks/auth-ui/dist/index.css';
`
Important: Without this CSS import, the authentication UI will not be styled correctly.
$3
`tsx
import { AuthProvider } from '@smartlinks/auth-ui';
import '@smartlinks/auth-ui/dist/index.css';
function App() {
return (
clientId="your-client-123"
clientName="Acme Corp"
>
);
}
`
$3
`tsx
import { SmartlinksAuthUI, useAuth } from '@smartlinks/auth-ui';
function YourApp() {
const { user, isAuthenticated, logout } = useAuth();
if (isAuthenticated) {
return (
Welcome, {user?.displayName || user?.email}!
);
}
return (
clientId="your-client-123"
onAuthSuccess={(response) => {
console.log('Authenticated!', response.user);
// Optional: redirect or update UI
}}
/>
);
}
`
Components
$3
Main authentication component with login, registration, password reset, and provider authentication.
#### Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| clientId | string | Yes | Client identifier for your application |
| clientName | string | No | Client name for branded emails |
| accountData | Record | No | Custom metadata to store on registration |
| onAuthSuccess | (response: AuthResponse) => void | No | Callback when authentication succeeds |
| onAuthError | (error: Error) => void | No | Callback when authentication fails |
| onRedirect | (url: string, reason: RedirectReason) => void | No | Callback for navigation after deep-link auth. When provided, disables automatic redirects. |
| redirectUrl | string | No | URL to redirect after auth (default: current page) |
| initialMode | 'login' \| 'register' | No | Initial view (default: 'login', or 'register' if signupProminence is 'emphasized') |
| signupProminence | 'minimal' \| 'balanced' \| 'emphasized' | No | How prominently to feature signup vs login (default: 'minimal') |
| customization | AuthUIConfig | No | UI customization (colors, fonts, logo) |
#### Example
`tsx
clientId="your-client-123"
clientName="Acme Corp"
accountData={{
companyName: "Acme Corp",
plan: "enterprise"
}}
onAuthSuccess={(response) => {
console.log('User:', response.user);
console.log('Token:', response.token);
console.log('Account Data:', response.accountData);
}}
onAuthError={(error) => {
console.error('Auth error:', error);
}}
initialMode="register"
/>
`
$3
By default, after deep-link authentication (email verification, magic link, phone auth), the component performs a direct window.location.href redirect. This can cause issues in iframe environments or when you want custom navigation.
The onRedirect callback gives the parent app full control over navigation:
`tsx
// React Router integration
clientId="your-client-123"
onAuthSuccess={(token, user) => {
console.log('Logged in:', user);
}}
onRedirect={(url, reason) => {
console.log(Auth complete (${reason}), navigating to:, url);
navigate(url); // React Router navigation
}}
/>
// Iframe with postMessage to parent
clientId="your-client-123"
onAuthSuccess={(token, user) => {
window.parent.postMessage({
type: 'auth-success',
payload: { token, user }
}, '*');
}}
onRedirect={(url, reason) => {
window.parent.postMessage({
type: 'auth-redirect',
payload: { url, reason }
}, '*');
}}
/>
// Close modal instead of redirect
clientId="your-client-123"
onAuthSuccess={(token, user) => {
setUser(user);
}}
onRedirect={(url, reason) => {
// Ignore the URL, just close the auth modal
setShowAuthModal(false);
}}
/>
`
RedirectReason values:
- 'email-verified' - User clicked email verification link
- 'magic-link' - User clicked magic link to log in
- 'phone-verified' - User completed phone verification
$3
Control how prominently signup is featured vs login using the signupProminence prop. This is useful for different user journey contexts:
| Mode | Use Case | Behavior |
|------|----------|----------|
| minimal (default) | Returning user access | Login form with small "Sign up" link at bottom |
| balanced | General purpose | Equal-weight toggle for "Sign In" / "Create Account" |
| emphasized | Product claiming, new users | Signup form with small "Sign in" link at bottom |
#### Examples
Product Claiming (new users expected):
`tsx
clientId="your-client-123"
signupProminence="emphasized"
onAuthSuccess={handleAuth}
/>
`
Accessing Protected Content (existing users):
`tsx
clientId="your-client-123"
signupProminence="minimal"
onAuthSuccess={handleAuth}
/>
`
General Purpose Portal:
`tsx
clientId="your-client-123"
signupProminence="balanced"
onAuthSuccess={handleAuth}
/>
`
$3
Account management component for authenticated users to update their profile, change passwords, update contact info, and delete their account.
#### Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| clientId | string | Yes | Client identifier for your application |
| showHeader | boolean | No | Show component header (default: false) |
| onProfileUpdate | () => void | No | Callback after profile update |
| onAccountDelete | () => void | No | Callback after account deletion |
#### Example
`tsx
import { AccountManagement } from '@smartlinks/auth-ui';
clientId="your-client-123"
onProfileUpdate={() => {
console.log('Profile updated!');
}}
onAccountDelete={() => {
console.log('Account deleted');
// Redirect to home or login
}}
/>
`
Session Management
$3
The AuthProvider component manages authentication state across your application. It handles token persistence, cross-tab synchronization, and automatic token refresh.
#### Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| clientId | string | Yes | Client identifier for your application |
| clientName | string | No | Client name for branded communications |
| accountCacheTTL | number | No | Account cache TTL in ms (default: 300000 / 5 min) |
| preloadAccountInfo | boolean | No | Fetch account info on login (default: false) |
#### Example
`tsx
clientId="your-client-123"
clientName="Acme Corp"
accountCacheTTL={600000} // 10 minutes
preloadAccountInfo={true}
>
`
$3
Access authentication state and methods anywhere in your app:
`tsx
import { useAuth } from '@smartlinks/auth-ui';
function MyComponent() {
const {
user, // Current user object (email, displayName, uid)
token, // Current JWT bearer token
accountData, // Custom account metadata
accountInfo, // Cached account information
isAuthenticated, // Boolean auth status
isLoading, // Loading state
login, // Manual login function
logout, // Logout function
getToken, // Get current token
getAccount, // Fetch account info (uses cache)
refreshAccount, // Force refresh account info
} = useAuth();
return (
{isAuthenticated ? (
Welcome, {user.displayName}!
) : (
Please log in
)}
);
}
`
$3
Protect routes that require authentication:
`tsx
import { ProtectedRoute } from '@smartlinks/auth-ui';
fallback={ }
redirectTo="/login"
>
`
$3
Subscribe to authentication events:
`tsx
import { onAuthStateChange } from '@smartlinks/auth-ui';
useEffect(() => {
const unsubscribe = onAuthStateChange((event, session) => {
switch (event) {
case 'LOGIN':
console.log('User logged in:', session.user);
navigate('/dashboard');
break;
case 'LOGOUT':
console.log('User logged out');
navigate('/');
break;
case 'CROSS_TAB_SYNC':
console.log('Auth state synced from another tab');
break;
case 'TOKEN_REFRESH':
console.log('Token refreshed');
break;
case 'ACCOUNT_REFRESH':
console.log('Account info refreshed');
break;
}
});
return () => unsubscribe();
}, []);
`
Account Caching
The auth module includes intelligent account info caching to reduce API calls:
`tsx
const { getAccount, refreshAccount, accountInfo } = useAuth();
// Get account (uses cache if fresh)
const account = await getAccount();
// Force refresh
const freshAccount = await getAccount(true);
// or
const freshAccount = await refreshAccount();
// Access cached data synchronously
const cachedAccount = accountInfo;
`
Configuration:
- Default cache TTL: 5 minutes
- Configure via accountCacheTTL prop on AuthProvider
- Enable automatic preload with preloadAccountInfo={true}
See ACCOUNT_CACHING.md for detailed documentation.
Authentication Methods
$3
Standard email and password authentication with registration, login, password reset, and email verification.
`tsx
clientId="your-client-123"
launchMode="signup"
/>
`
$3
One-click Google authentication with automatic account creation.
`tsx
clientId="your-client-123"
// Google Auth is enabled by default
/>
`
$3
Phone number authentication with SMS verification codes.
`tsx
clientId="your-client-123"
// Phone auth is enabled by default
/>
`
$3
Passwordless authentication via email magic links.
`tsx
clientId="your-client-123"
// Magic links are enabled by default
/>
`
Customization
$3
Customize colors, fonts, and logo via the admin interface or programmatically:
`tsx
clientId="your-client-123"
customization={{
branding: {
logoUrl: "https://yourdomain.com/logo.png",
title: "Welcome to Acme",
subtitle: "Sign in to your account",
primaryColor: "#6366f1",
secondaryColor: "#4f46e5",
backgroundColor: "#f0f9ff",
fontFamily: "Inter, sans-serif"
}
}}
/>
`
$3
Configure which authentication providers are available and their display order through the Smartlinks admin interface.
$3
Customize email templates for password reset, email verification, and magic links through the admin interface with support for:
- Custom logos and hero images
- Branded colors and fonts
- Custom intro text and CTAs
- Footer links and company information
See CUSTOMIZATION_GUIDE.md for detailed customization options.
Advanced Features
$3
The clientId parameter enables multi-tenant authentication, allowing different applications or customers to use the same auth infrastructure with isolated configurations:
`tsx
// App 1
// App 2
`
$3
Store custom metadata per user account during registration:
`tsx
clientId="your-client-123"
accountData={{
companyName: "Acme Corp",
plan: "enterprise",
seats: 50,
customFields: {
industry: "Technology",
region: "North America"
}
}}
/>
`
$3
The component automatically handles URL-based authentication flows:
- Email Verification: ?mode=verifyEmail&token=xxx
- Password Reset: ?mode=resetPassword&token=xxx
- Magic Links: ?mode=magicLink&token=xxx
$3
Authentication state automatically syncs across browser tabs using BroadcastChannel API and IndexedDB. When a user logs in or out in one tab, all other tabs update immediately.
TypeScript Support
Full TypeScript definitions included:
`tsx
import type {
AuthUser,
AuthToken,
AuthResponse,
AuthProvider,
AuthUIConfig,
SmartlinksAuthUIProps,
AccountManagementProps,
ClaimField,
ClaimResult
} from '@smartlinks/auth-ui';
`
Documentation
- AUTH_STATE_MANAGEMENT.md - Complete guide to authentication state, callbacks, and cross-tab sync
- ACCOUNT_CACHING.md - Account information caching strategies and configuration
- CUSTOMIZATION_GUIDE.md - Detailed customization and theming guide
- SMARTLINKS_INTEGRATION.md - Smartlinks SDK integration details
Troubleshooting
$3
Problem: The authentication UI appears unstyled or has no layout.
Solution: Make sure you've imported the CSS file:
`tsx
import '@smartlinks/auth-ui/dist/index.css';
`
This import should be at the top of your app's entry point (before your component imports).
$3
Problem: Cannot read property 'authKit' of undefined or similar SDK errors.
Solution: Initialize the Smartlinks SDK before rendering components:
`tsx
import * as smartlinks from '@proveanything/smartlinks';
smartlinks.initializeApi({
baseUrl: 'https://smartlinks.app/api/v1',
proxyMode: false,
});
`
$3
Problem: Users get logged out on page refresh.
Solution:
1. Ensure AuthProvider wraps your entire app
2. Check that IndexedDB is enabled in the browser
3. Verify that third-party cookies aren't blocked (affects cross-tab sync)
$3
Problem: Type errors when using the components.
Solution: The package includes TypeScript definitions. Make sure:
`tsx
import type { AuthUser, AuthResponse } from '@smartlinks/auth-ui';
``