npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@authava/client

v0.1.41

Published

Client library for seamless integration with Authava's white-label authentication service

Readme

@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: '[email protected]',
  password: 'secure-password'
});

// Register a new user
const registerResponse = await authava.register({
  email: '[email protected]',
  password: 'secure-password'
});

// Request a password reset
const forgotResponse = await authava.forgotPassword({
  email: '[email protected]'
});

// 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: '[email protected]',
  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: '[email protected]',
  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