@authava/client v0.1.40
@authava/client
A lightweight client library for seamless integration with Authava's white-label authentication service.
Installation
npm install @authava/clientQuick Start
import { AuthavaClient } from '@authava/client';
// Initialize the client
const authava = new AuthavaClient({
domain: 'auth.yourdomain.com' // Your white-labeled Authava domain
});
// Get current session
const session = await authava.getSession();
if (session) {
console.log('User is logged in:', session.user);
} else {
console.log('No active session');
}Features
- 🚀 Zero dependencies
- 🔒 Automatic session handling
- 🌐 TypeScript support
- 🎨 White-label domain support
- 🍪 Cookie-based session management
- 📱 Cross-tab session synchronization
- 🔄 Automatic session refresh
- 🔐 Multi-factor authentication (MFA) support
- 👤 User profile management
- 📧 Email change and verification
- 🔑 Password reset and recovery
- 🔔 Notification preferences management
Configuration
interface AuthavaConfig {
domain: string; // Your Authava domain (e.g., auth.yourdomain.com)
resolverDomain?: string; // Domain for API requests (defaults to domain)
secure?: boolean; // Use HTTPS (default: true)
autoRefresh?: boolean; // Auto refresh session (default: true)
refreshBuffer?: number; // Minutes before expiration to refresh (default: 5)
customHeaders?: Record<string, string> | (() => Record<string, string>); // Custom headers for API requests
debug?: boolean; // Enable debug logging (default: false)
}API Reference
Authentication
// Login with email and password
const loginResponse = await authava.login({
email: 'user@example.com',
password: 'secure-password'
});
// Register a new user
const registerResponse = await authava.register({
email: 'newuser@example.com',
password: 'secure-password'
});
// Request a password reset
const forgotResponse = await authava.forgotPassword({
email: 'user@example.com'
});
// Reset password with token
const resetResponse = await authava.resetPassword({
token: 'reset-token-from-email',
password: 'new-secure-password'
});
// Logout the current user
await authava.logout();Multi-Factor Authentication (MFA)
// Setup Email MFA
const setupEmailResponse = await authava.setupEmailMfa({
name: 'My Email MFA'
});
// Verify Email MFA
const verifyEmailResponse = await authava.verifyEmailMfa({
code: '123456'
});
// Setup TOTP MFA (e.g., Google Authenticator)
const setupTotpResponse = await authava.setupTotp({
name: 'My Authenticator'
});
// Verify TOTP MFA
const verifyTotpResponse = await authava.verifyTotp({
method_id: setupTotpResponse.data.method_id,
code: '123456'
});
// Remove an MFA method
await authava.removeMfaMethod('mfa-method-id');
// Verify MFA during login
const verifyMfaResponse = await authava.verifyMfa({
session_id: 'session-id',
method_id: 'mfa-method-id',
code: '123456'
});
// Send MFA verification email
await authava.sendMfaEmail({
session_id: 'session-id',
method_id: 'mfa-method-id'
});User Profile Management
// Get user profile information
const profileResponse = await authava.getProfile();
// Change email address
const changeEmailResponse = await authava.changeEmail({
new_email: 'newemail@example.com',
password: 'current-password'
});
// Change password
const changePasswordResponse = await authava.changePassword({
current_password: 'current-password',
new_password: 'new-secure-password'
});
// Update notification preferences
const updateNotificationsResponse = await authava.updateNotificationPreferences({
security_alerts: true,
account_activity: true,
product_updates: false,
marketing_emails: false
});Response Handling
All API methods return a consistent response format:
interface T;
interface ErrorResponse {
error: String;
};
// Example usage
const response = await authava.login({
email: 'user@example.com',
password: 'password'
});
if (response.error) {
console.error('Login failed:', response.error);
return;
}
console.log('Login successful:', response.data);Session Management
The client automatically handles session management, including:
- Automatic session refresh before expiration
- Cross-tab session synchronization
- Error handling and retry logic
Session States
Sessions can be in one of the following states:
valid: Session is active and validrefreshing: Session is being refreshedexpired: Session has expirederror: An error occurred
Subscribing to Session Changes
const unsubscribe = authava.onSessionChange((state) => {
switch (state.status) {
case 'valid':
console.log('Session is valid:', state.user);
break;
case 'refreshing':
console.log('Refreshing session...');
break;
case 'expired':
console.log('Session has expired');
break;
case 'error':
console.error('Session error:', state.error);
break;
}
});
// Later: cleanup subscription
unsubscribe();Framework Integration Examples
React Integration
import { useEffect, useState } from 'react';
import { AuthavaClient, AuthavaUser, ProfileResponse } from '@authava/client';
const authava = new AuthavaClient({
domain: 'auth.yourdomain.com'
});
function App() {
const [user, setUser] = useState<AuthavaUser | null>(null);
const [profile, setProfile] = useState<ProfileResponse | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Check initial session
authava.getSession().then(session => {
if (session) {
setUser(session.user);
// Fetch user profile
authava.getProfile().then(response => {
if (response.data) {
setProfile(response.data);
}
setLoading(false);
});
} else {
setLoading(false);
}
});
// Listen for session changes
return authava.onSessionChange(state => {
setUser(state.status === 'valid' ? state.user : null);
// Fetch profile when session becomes valid
if (state.status === 'valid' && state.user) {
authava.getProfile().then(response => {
if (response.data) {
setProfile(response.data);
}
});
} else if (state.status !== 'valid') {
setProfile(null);
}
});
}, []);
// Login handler
const handleLogin = async (email: string, password: string) => {
const response = await authava.login({ email, password });
if (response.error) {
console.error('Login failed:', response.error);
return false;
}
return true;
};
// Profile update handler
const updateNotifications = async (preferences: {
security_alerts: boolean;
account_activity: boolean;
product_updates: boolean;
marketing_emails: boolean;
}) => {
const response = await authava.updateNotificationPreferences(preferences);
if (response) {
// Update local profile state
setProfile(prev => prev ? {
...prev,
notification_preferences: response
} : null);
return true;
}
return false;
};
if (loading) {
return <div>Loading...</div>;
}
if (!user) {
return (
<div>
<h2>Login</h2>
<LoginForm onSubmit={handleLogin} />
</div>
);
}
return (
<div>
<h1>Welcome, {user.email}!</h1>
{profile && (
<div>
<h2>Your Profile</h2>
<p>Email: {profile.user.email}</p>
<p>Status: {profile.user.status}</p>
<h3>MFA Methods</h3>
<ul>
{profile.mfa_methods.map(method => (
<li key={method.id}>
{method.mfa_type} - {method.verified ? 'Verified' : 'Not Verified'}
<button onClick={() => authava.removeMfaMethod(method.id)}>
Remove
</button>
</li>
))}
</ul>
<h3>Notification Preferences</h3>
<NotificationForm
preferences={profile.notification_preferences}
onUpdate={updateNotifications}
/>
</div>
)}
<button onClick={() => authava.logout()}>Logout</button>
</div>
);
}Next.js Integration
// utils/authava.ts
import { AuthavaClient } from '@authava/client';
export const authava = new AuthavaClient({
domain: process.env.NEXT_PUBLIC_AUTHAVA_DOMAIN!
});
// hooks/useAuth.ts
import { useEffect, useState } from 'react';
import { authava } from '../utils/authava';
import type { AuthavaUser, ProfileResponse } from '@authava/client';
export function useAuth() {
const [user, setUser] = useState<AuthavaUser | null>(null);
const [profile, setProfile] = useState<ProfileResponse | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Check initial session
authava.getSession().then(session => {
if (session) {
setUser(session.user);
// Fetch user profile
authava.getProfile().then(response => {
if (response.data) {
setProfile(response.data);
}
setLoading(false);
});
} else {
setLoading(false);
}
});
// Listen for session changes
return authava.onSessionChange(state => {
setUser(state.status === 'valid' ? state.user : null);
if (state.status === 'valid' && state.user) {
authava.getProfile().then(response => {
if (response.data) {
setProfile(response.data);
}
});
} else if (state.status !== 'valid') {
setProfile(null);
}
});
}, []);
const login = async (email: string, password: string) => {
const response = await authava.login({ email, password });
return response;
};
const register = async (email: string, password: string) => {
const response = await authava.register({ email, password });
return response;
};
const logout = () => authava.logout();
const changePassword = async (currentPassword: string, newPassword: string) => {
return authava.changePassword({
current_password: currentPassword,
new_password: newPassword
});
};
return {
user,
profile,
loading,
login,
register,
logout,
changePassword,
authava, // Expose the client for advanced usage
};
}
// pages/_app.tsx
import { useEffect } from 'react';
import { authava } from '../utils/authava';
import { AuthProvider } from '../context/AuthContext';
function MyApp({ Component, pageProps }) {
useEffect(() => {
// Initialize session
authava.getSession();
}, []);
return (
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
);
}
// context/AuthContext.tsx
import { createContext, useContext } from 'react';
import { useAuth } from '../hooks/useAuth';
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const auth = useAuth();
return (
<AuthContext.Provider value={auth}>
{children}
</AuthContext.Provider>
);
}
export const useAuthContext = () => useContext(AuthContext);
// pages/profile.tsx
import { useAuthContext } from '../context/AuthContext';
import { useRouter } from 'next/router';
export default function ProfilePage() {
const { user, profile, loading, logout } = useAuthContext();
const router = useRouter();
useEffect(() => {
if (!loading && !user) {
router.push('/login');
}
}, [loading, user, router]);
if (loading) {
return <div>Loading...</div>;
}
if (!user || !profile) {
return null;
}
return (
<div>
<h1>Profile</h1>
<p>Email: {profile.user.email}</p>
<h2>MFA Methods</h2>
<ul>
{profile.mfa_methods.map(method => (
<li key={method.id}>
{method.mfa_type} - {method.verified ? 'Verified' : 'Not Verified'}
</li>
))}
</ul>
<button onClick={() => router.push('/profile/setup-mfa')}>
Setup MFA
</button>
<button onClick={logout}>Logout</button>
</div>
);
}Security Considerations
- All communication with the Authava server is done over HTTPS by default
- Session tokens are stored in secure, HTTP-only cookies
- Cross-tab synchronization is handled securely using the BroadcastChannel API
- Automatic session refresh helps prevent session expiration
- Error handling includes exponential backoff for failed requests
- Multi-factor authentication (MFA) provides an additional layer of security
- Backup codes are provided when setting up MFA methods
- Password changes require verification of the current password
- Email changes require password verification
- Security events are tracked and available in the user profile
- Notification preferences allow users to stay informed about security events
Contributing
We welcome contributions! Please see our contributing guidelines for details.
License
MIT
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago