@authava/client
TypeScript icon, indicating that this package has built-in type declarations

0.1.40 • Public • Published

@authava/client

A lightweight client library for seamless integration with Authava's white-label authentication service.

Installation

npm install @authava/client

Quick 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 valid
  • refreshing: Session is being refreshed
  • expired: Session has expired
  • error: 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

Package Sidebar

Install

npm i @authava/client

Weekly Downloads

239

Version

0.1.40

License

MIT

Unpacked Size

120 kB

Total Files

6

Last publish

Collaborators

  • stackout