@proveanything/smartlinks-auth-ui
Version:
Lightweight React authentication UI components with bearer token support and Smartlinks SDK integration
579 lines (444 loc) • 16.4 kB
Markdown
# @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
- 🎯 **Product Claiming**: Claim physical products/proofs with custom attestations
### 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
```bash
npm install @smartlinks/auth-ui @proveanything/smartlinks
```
**Note**: 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:
```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
});
```
### 2. Import the CSS (Required!)
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. Wrap Your App with AuthProvider
```tsx
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
```tsx
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 |
| `onAuthSuccess` | (response: AuthResponse) => void | No | Callback when authentication succeeds |
| `onAuthError` | (error: Error) => void | No | Callback when authentication fails |
| `redirectUrl` | string | No | URL to redirect after auth (default: current page) |
| `launchMode` | 'login' \| 'signup' | No | Initial view (default: 'login') |
| `customization` | AuthUIConfig | No | UI customization (colors, fonts, logo) |
#### Example
```tsx
<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);
}}
launchMode="signup"
/>
```
### 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
```tsx
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
}}
/>
```
### SmartlinksClaimUI
Product claiming component for authenticating users and claiming physical products/proofs with optional custom questions.
#### Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `clientId` | string | **Yes** | Client identifier for your application |
| `collectionId` | string | **Yes** | Collection ID of the product |
| `productId` | string | **Yes** | Product ID to claim |
| `proofId` | string | **Yes** | Specific proof ID to claim |
| `additionalQuestions` | ClaimField[] | No | Custom questions for claim attestations |
| `onClaimSuccess` | (result: ClaimResult) => void | **Yes** | Callback when claim succeeds |
| `onClaimError` | (error: Error) => void | No | Callback when claim fails |
#### Example
```tsx
import { SmartlinksClaimUI } from '@smartlinks/auth-ui';
<SmartlinksClaimUI
clientId="your-client-123"
collectionId="col_abc123"
productId="prod_xyz789"
proofId="proof_def456"
additionalQuestions={[
{
id: 'serial_number',
label: 'Serial Number',
type: 'text',
required: true
},
{
id: 'purchase_date',
label: 'Purchase Date',
type: 'date',
required: false
}
]}
onClaimSuccess={(result) => {
console.log('Claimed!', result.proof);
}}
/>
```
## 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 | **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
<AuthProvider
clientId="your-client-123"
clientName="Acme Corp"
accountCacheTTL={600000} // 10 minutes
preloadAccountInfo={true}
>
<App />
</AuthProvider>
```
### useAuth Hook
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 (
<div>
{isAuthenticated ? (
<p>Welcome, {user.displayName}!</p>
) : (
<p>Please log in</p>
)}
</div>
);
}
```
### ProtectedRoute
Protect routes that require authentication:
```tsx
import { ProtectedRoute } from '@smartlinks/auth-ui';
<ProtectedRoute
fallback={<LoginPage />}
redirectTo="/login"
>
<DashboardPage />
</ProtectedRoute>
```
### Auth State Change Callbacks
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](./ACCOUNT_CACHING.md) for detailed documentation.
## Authentication Methods
### Email/Password
Standard email and password authentication with registration, login, password reset, and email verification.
```tsx
<SmartlinksAuthUI
clientId="your-client-123"
launchMode="signup"
/>
```
### Google OAuth
One-click Google authentication with automatic account creation.
```tsx
<SmartlinksAuthUI
clientId="your-client-123"
// Google Auth is enabled by default
/>
```
### Phone/SMS
Phone number authentication with SMS verification codes.
```tsx
<SmartlinksAuthUI
clientId="your-client-123"
// Phone auth is enabled by default
/>
```
### Magic Links
Passwordless authentication via email magic links.
```tsx
<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:
```tsx
<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](./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:
```tsx
// 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:
```tsx
<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.
## 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](./AUTH_STATE_MANAGEMENT.md)** - Complete guide to authentication state, callbacks, and cross-tab sync
- **[ACCOUNT_CACHING.md](./ACCOUNT_CACHING.md)** - Account information caching strategies and configuration
- **[CUSTOMIZATION_GUIDE.md](./CUSTOMIZATION_GUIDE.md)** - Detailed customization and theming guide
- **[SMARTLINKS_INTEGRATION.md](./SMARTLINKS_INTEGRATION.md)** - Smartlinks SDK integration details
## Troubleshooting
### Styles Not Appearing
**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).
### Smartlinks SDK Not Initialized
**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,
});
```
### Session Not Persisting
**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)
### TypeScript Errors
**Problem**: Type errors when using the components.
**Solution**: The package includes TypeScript definitions. Make sure:
```tsx
import type { AuthUser, AuthResponse } from '@smartlinks/auth-ui';
```
## Support
For issues, questions, or feature requests:
- GitHub Issues: [github.com/smartlinks/auth-ui](https://github.com/smartlinks/auth-ui)
- Documentation: [docs.smartlinks.app/auth-ui](https://docs.smartlinks.app/auth-ui)
- Smartlinks Platform: [smartlinks.app](https://smartlinks.app)
## License
MIT © Smartlinks