@proveanything/smartlinks-auth-ui
v0.6.4
Published
Lightweight React authentication UI components with bearer token support and Smartlinks SDK integration
Maintainers
Readme
@smartlinks/auth-ui
A complete, drop-in React authentication and account management solution built for the Smartlinks platform. Provides beautiful, customizable UI components for authentication flows, session management, and user account operations with seamless Smartlinks SDK integration.
Features
Authentication
- 🔐 Multiple Auth Methods: Email/Password, Google OAuth, Phone/SMS, Magic Links
- 🎨 Beautiful Pre-built UI: Professional, responsive authentication flows
- 🪙 JWT Bearer Tokens: Automatic Smartlinks SDK integration with bearer token management
- 🗂️ Session Management: Built-in AuthProvider, useAuth hook, ProtectedRoute, and cross-tab sync
- 🏢 Multi-Tenant Support: Client ID for identifying different systems/tenants
- 📊 Custom Account Data: Store custom metadata per user account
- 🔗 Deep Link Support: Email verification, password reset, magic link flows
- 📧 Passwordless Login: Magic link authentication via email
Account Management
- 👤 Profile Management: Update display name and contact information
- 🔑 Password Changes: Secure password update flow for authenticated users
- 📧 Email Changes: Change email with verification flow
- 📱 Phone Updates: Update phone number with SMS verification
- 🗑️ Account Deletion: Self-service account deletion
Developer Experience
- ⚡ Lightweight: Minimal dependencies, integrates with Smartlinks SDK
- 📱 Fully Responsive: Works seamlessly on mobile and desktop
- ♿ Accessible: WCAG compliant forms and interactions
- 🎨 Highly Customizable: Extensive theming and branding options
- 🔄 Real-time Sync: Cross-tab authentication state synchronization
- 💾 Smart Caching: Account info caching with configurable TTL
- 🎣 Auth State Callbacks: Subscribe to login, logout, and token refresh events
- 📘 TypeScript First: Full type definitions included
Installation
npm install @smartlinks/auth-ui @proveanything/smartlinksNote: This package requires the Smartlinks SDK (@proveanything/smartlinks) as a peer dependency.
Quick Start
1. Initialize Smartlinks SDK
Initialize the Smartlinks SDK at the top level of your application:
// 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
});2. Import the CSS (Required!)
Add this import to your app's entry point:
import '@smartlinks/auth-ui/dist/index.css';Important: Without this CSS import, the authentication UI will not be styled correctly.
3. Wrap Your App with AuthProvider
import { AuthProvider } from '@smartlinks/auth-ui';
import '@smartlinks/auth-ui/dist/index.css';
function App() {
return (
<AuthProvider
clientId="your-client-123"
clientName="Acme Corp"
>
<YourApp />
</AuthProvider>
);
}4. Use the Authentication UI
import { SmartlinksAuthUI, useAuth } from '@smartlinks/auth-ui';
function YourApp() {
const { user, isAuthenticated, logout } = useAuth();
if (isAuthenticated) {
return (
<div>
<h1>Welcome, {user?.displayName || user?.email}!</h1>
<button onClick={logout}>Logout</button>
</div>
);
}
return (
<SmartlinksAuthUI
clientId="your-client-123"
onAuthSuccess={(response) => {
console.log('Authenticated!', response.user);
// Optional: redirect or update UI
}}
/>
);
}Components
SmartlinksAuthUI
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<string, any> | No | Custom metadata to store on registration |
| prefillEmail | string | No | Pre-fill email in the email/password form |
| prefillDisplayName | string | No | Pre-fill full name in the registration form |
| 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
<SmartlinksAuthUI
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"
/>Redirect Handling (onRedirect)
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:
// React Router integration
<SmartlinksAuthUI
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
<SmartlinksAuthUI
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
<SmartlinksAuthUI
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
Signup Prominence
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):
<SmartlinksAuthUI
clientId="your-client-123"
signupProminence="emphasized"
onAuthSuccess={handleAuth}
/>Accessing Protected Content (existing users):
<SmartlinksAuthUI
clientId="your-client-123"
signupProminence="minimal"
onAuthSuccess={handleAuth}
/>General Purpose Portal:
<SmartlinksAuthUI
clientId="your-client-123"
signupProminence="balanced"
onAuthSuccess={handleAuth}
/>AccountManagement
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
import { AccountManagement } from '@smartlinks/auth-ui';
<AccountManagement
clientId="your-client-123"
onProfileUpdate={() => {
console.log('Profile updated!');
}}
onAccountDelete={() => {
console.log('Account deleted');
// Redirect to home or login
}}
/>Session Management
AuthProvider
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 | No¹ | AuthKit client identifier. Auto-resolved from collection.defaultAuthKitId when collectionId is provided. |
| collectionId | string | No¹ | SmartLinks collection id. Enables contact sync, interaction tracking, and clientId auto-resolution. |
| proxyMode | boolean | No | Delegate session to the parent window (iframe embeds). Default false. |
| accountCacheTTL | number | No | Account-info cache TTL in ms (default 300_000 = 5 min). |
| preloadAccountInfo | boolean | No | Fetch account info eagerly on login (default false). |
| enableAutoRefresh | boolean | No | Background token refresh timer (default true). |
| refreshThresholdPercent | number | No | Refresh when this % of the access-token lifetime has elapsed (default 75). |
| refreshCheckInterval | number | No | Background check interval in ms (default 60_000). |
| refreshOnResume | boolean | No | Refresh the session when the app returns to the foreground. Default true on native shells (Capacitor / window.AuthKit.isNative), false on web. Listens to App.addListener('appStateChange') via a dynamic @capacitor/app import (no web runtime dep) and to document.visibilitychange as a universal fallback. |
| enableContactSync | boolean | No | Default true when collectionId is set. |
| enableInteractionTracking | boolean | No | Default true when collectionId is set. |
| interactionAppId | string | No | App id used for interaction events. |
| interactionConfig | object | No | Custom interaction ids — see AUTH_STATE_MANAGEMENT.md. |
¹ Either clientId or collectionId is required. Most apps only need collectionId — the kit looks up the collection's defaultAuthKitId and uses it for refresh-token rotation and server-side logout. See architecture/default-authkit-collection-property.
Example
// Minimal — clientId auto-resolved from the collection's defaultAuthKitId
<AuthProvider collectionId="col_abc123">
<App />
</AuthProvider>
// Explicit clientId + long-lived native sessions
<AuthProvider
clientId="your-client-123"
collectionId="col_abc123"
refreshOnResume // explicit on (auto-on under Capacitor)
accountCacheTTL={600_000}
>
<App />
</AuthProvider>useAuth Hook
Access authentication state and methods anywhere in your app:
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 (
<div>
{isAuthenticated ? (
<p>Welcome, {user.displayName}!</p>
) : (
<p>Please log in</p>
)}
</div>
);
}ProtectedRoute
Protect routes that require authentication:
import { ProtectedRoute } from '@smartlinks/auth-ui';
<ProtectedRoute
fallback={<LoginPage />}
redirectTo="/login"
>
<DashboardPage />
</ProtectedRoute>Auth State Change Callbacks
Subscribe to authentication events:
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:
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
accountCacheTTLprop on AuthProvider - Enable automatic preload with
preloadAccountInfo={true}
See ACCOUNT_CACHING.md for detailed documentation.
Authentication Methods
Email/Password
Standard email and password authentication with registration, login, password reset, and email verification.
<SmartlinksAuthUI
clientId="your-client-123"
launchMode="signup"
/>Google OAuth
One-click Google authentication with automatic account creation.
<SmartlinksAuthUI
clientId="your-client-123"
// Google Auth is enabled by default
/>Phone/SMS
Phone number authentication with SMS verification codes.
<SmartlinksAuthUI
clientId="your-client-123"
// Phone auth is enabled by default
/>Magic Links
Passwordless authentication via email magic links.
<SmartlinksAuthUI
clientId="your-client-123"
// Magic links are enabled by default
/>Customization
Branding & Theming
Customize colors, fonts, and logo via the admin interface or programmatically:
<SmartlinksAuthUI
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"
}
}}
/>Provider Configuration
Configure which authentication providers are available and their display order through the Smartlinks admin interface.
Email Templates
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
Multi-Tenant Support
The clientId parameter enables multi-tenant authentication, allowing different applications or customers to use the same auth infrastructure with isolated configurations:
// App 1
<SmartlinksAuthUI clientId="app-1-prod" />
// App 2
<SmartlinksAuthUI clientId="app-2-prod" />Custom Account Data
Store custom metadata per user account during registration:
<SmartlinksAuthUI
clientId="your-client-123"
accountData={{
companyName: "Acme Corp",
plan: "enterprise",
seats: 50,
customFields: {
industry: "Technology",
region: "North America"
}
}}
/>Deep Link Handling
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
Cross-Tab Synchronization
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.
Native / Mobile (Capacitor)
The kit ships first-class support for native shells — Capacitor, Capgo, and Ionic WebView. When a native host is detected (window.Capacitor.isNativePlatform() or window.AuthKit.isNative):
- Long-lived sessions via refresh-token rotation. Login responses carry a
refreshToken+refreshTokenExpiresAt; the kit persists them next to the access JWT and callssmartlinks.authKit.refreshToken(clientId, ...)automatically. Reuse / invalid / expired refresh tokens force re-login. - Refresh on resume.
refreshOnResumedefaults totrueon native, hookingApp.addListener('appStateChange')(dynamic import — no web runtime dep) anddocument.visibilitychange. Stale sessions self-heal the moment the user reopens the app. - Secure storage adapter. Replace IndexedDB with Keychain / Keystore via
setStorageAdapter(adapter). SeeCAPACITOR_INTEGRATION.md§5. - Native Google / Apple Sign-In via the unified
window.AuthKitbridge. SeeANDROID_NATIVE_BRIDGE.md.
Tell the SmartLinks SDK it's running native so refresh tokens are issued:
smartlinks.initializeApi({
baseURL: '…',
platform: 'native', // adds X-Client-Platform: native to every request
persistToken: false, // AuthKit owns persistence
});Full step-by-step (Keychain adapter, biometric gating, deep-link routing): CAPACITOR_INTEGRATION.md. Backend contract for the refresh endpoint: ../backend-reference/REFRESH_TOKEN_BACKEND_SPEC.md.
TypeScript Support
Full TypeScript definitions included:
import type {
AuthUser,
AuthToken,
AuthResponse,
AuthProvider,
AuthUIConfig,
SmartlinksAuthUIProps,
AccountManagementProps,
ClaimField,
ClaimResult,
PersistentStorage,
StorageBackend,
} from '@smartlinks/auth-ui';Documentation
All guides ship inside the published package so consumers can read them locally (node_modules/@proveanything/smartlinks-auth-ui/*.md).
Core
- AUTH_STATE_MANAGEMENT.md — auth state lifecycle,
onAuthStateChangecallbacks, cross-tab sync. - ACCOUNT_CACHING.md — account-info caching strategy, TTLs, manual invalidation.
- CUSTOMIZATION_GUIDE.md — theming, branding, dark mode, provider ordering, email template config.
- SMARTLINKS_INTEGRATION.md — how the kit wires into
@proveanything/smartlinks(token, refresh, profile, account, logout).
Native / Mobile
- CAPACITOR_INTEGRATION.md — Capacitor / Capgo setup: native platform flag, secure storage adapter, refresh-on-resume, deep-link routing, native sign-out, biometric gating.
- ANDROID_NATIVE_BRIDGE.md —
window.AuthKitbridge contract for native Google sign-in, scanner, and other host capabilities.
Specialized features
- SMARTLINKS_FRAME.md —
SmartlinksFrameembed component (optional auth, iframe messaging). - WHATSAPP_OTP_PLAN.md — WhatsApp OTP flow and backend contract.
- SDK_DEBUGGING_GUIDE.md — troubleshooting SDK init, proxy mode, token storage, iframe ack flow.
Backend contracts (in backend-reference/)
- REFRESH_TOKEN_BACKEND_SPEC.md — refresh-token endpoint, rotation, reuse detection, family revocation.
- APPLE_SIGNIN_BACKEND_SPEC.md — Apple Sign-In identity-token verification contract.
- ACCOUNT_MANAGEMENT_API.md — profile / email / password / delete endpoints used by
<AccountManagement>. - API_DOCUMENTATION.md — full AuthKit REST surface.
Troubleshooting
Styles Not Appearing
Problem: The authentication UI appears unstyled or has no layout.
Solution: Make sure you've imported the CSS file:
import '@smartlinks/auth-ui/dist/index.css';This import should be at the top of your app's entry point (before your component imports).
Smartlinks SDK Not Initialized
Problem: Cannot read property 'authKit' of undefined or similar SDK errors.
Solution: Initialize the Smartlinks SDK before rendering components:
import * as smartlinks from '@proveanything/smartlinks';
smartlinks.initializeApi({
baseUrl: 'https://smartlinks.app/api/v1',
proxyMode: false,
});Session Not Persisting
Problem: Users get logged out on page refresh.
Solution:
- Ensure AuthProvider wraps your entire app
- Check that IndexedDB is enabled in the browser
- Verify that third-party cookies aren't blocked (affects cross-tab sync)
TypeScript Errors
Problem: Type errors when using the components.
Solution: The package includes TypeScript definitions. Make sure:
import type { AuthUser, AuthResponse } from '@smartlinks/auth-ui';Support
For issues, questions, or feature requests:
- GitHub Issues: github.com/smartlinks/auth-ui
- Documentation: docs.smartlinks.app/auth-ui
- Smartlinks Platform: smartlinks.app
License
MIT © Smartlinks
