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

get401

v1.0.13

Published

Easy authentication SDK for React, Vue, Next.js, Express, and React Native applications - Get401 Auth

Readme

get401

Flexible authentication SDK for React applications. Easy-to-use authentication with email/password login, OTP verification, and ready-made UI components.

Installation

npm install get401

Quick Start

1. Wrap your app with Get401Provider

import { Get401Provider } from 'get401';

function App() {
  return (
    <Get401Provider
      appId="your-app-id"
      debug={true}
      onSuccess={(user) => console.log('User logged in:', user)}
      onError={(error) => console.error('Auth error:', error)}
    >
      <YourApp />
    </Get401Provider>
  );
}

2. Use the useAuth hook

import { useAuth } from 'get401';

function LoginPage() {
  const { login, challengeOTP, user, status, nextStep, error, isLoading } = useAuth();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [otpCode, setOtpCode] = useState('');

  const handleLogin = async (e) => {
    e.preventDefault();
    try {
      // Send both email and password in one request
      const response = await login(email, password);
      // If response.next === 'otp', show OTP input form
      // Otherwise, user is authenticated
    } catch (err) {
      console.error('Login failed:', err);
    }
  };

  const handleOTP = async (e) => {
    e.preventDefault();
    try {
      await challengeOTP(otpCode);
      // User will be authenticated if successful
    } catch (err) {
      console.error('OTP verification failed:', err);
    }
  };

  if (status === 'authenticated') {
    return <div>Welcome {user?.email}!</div>;
  }

  if (nextStep === 'otp') {
    return (
      <form onSubmit={handleOTP}>
        <input
          type="text"
          value={otpCode}
          onChange={(e) => setOtpCode(e.target.value)}
          placeholder="Enter OTP code"
        />
        <button type="submit" disabled={isLoading}>
          Verify OTP
        </button>
        {error && <div>{error}</div>}
      </form>
    );
  }

  return (
    <form onSubmit={handleLogin}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
        required
      />
      <button type="submit" disabled={isLoading}>
        Login
      </button>
      {error && <div>{error}</div>}
    </form>
  );
}

Ready-made UI Components

AuthModal - Complete Modal Component

Drop-in authentication modal that handles the entire flow:

import { useState } from 'react';
import { AuthModal } from 'get401';

function App() {
  const [showAuth, setShowAuth] = useState(false);

  return (
    <>
      <button onClick={() => setShowAuth(true)}>Login</button>
      <AuthModal
        isOpen={showAuth}
        onClose={() => setShowAuth(false)}
        mode="login" // or "register"
        onSuccess={() => {
          console.log('User authenticated!');
          setShowAuth(false);
        }}
      />
    </>
  );
}

AuthModal Props:

  • isOpen: boolean - Controls modal visibility
  • onClose: () => void - Callback when modal should close
  • mode?: 'login' | 'register' - Initial mode (default: 'login')
  • title?: string - Custom modal title
  • showCloseButton?: boolean - Show/hide close button (default: true)
  • className?: string - Custom CSS classes for form container
  • overlayClassName?: string - Custom CSS classes for overlay
  • modalClassName?: string - Custom CSS classes for modal container
  • onSuccess?: () => void - Callback on successful authentication

LoginForm and RegisterForm Components

Ready-to-use form components that you can customize:

import { LoginForm, RegisterForm } from 'get401';

function AuthPage() {
  const [mode, setMode] = useState('login');

  return (
    <div>
      {mode === 'login' ? (
        <LoginForm onSuccess={() => console.log('Logged in!')} />
      ) : (
        <RegisterForm onSuccess={() => console.log('Registered!')} />
      )}
      <button onClick={() => setMode(mode === 'login' ? 'register' : 'login')}>
        Switch to {mode === 'login' ? 'Register' : 'Login'}
      </button>
    </div>
  );
}

LoginForm Props:

  • onSuccess?: () => void - Callback on successful login
  • className?: string - Custom CSS classes for form container
  • inputClassName?: string - Custom CSS classes for inputs
  • buttonClassName?: string - Custom CSS classes for buttons
  • labelClassName?: string - Custom CSS classes for labels
  • errorClassName?: string - Custom CSS classes for error messages

RegisterForm Props:

  • Same as LoginForm

Protected Routes

import { ProtectedRoute } from 'get401';

function App() {
  return (
    <Routes>
      <Route path="/login" element={<LoginPage />} />
      <Route
        path="/dashboard"
        element={
          <ProtectedRoute fallback={<Navigate to="/login" />}>
            <Dashboard />
          </ProtectedRoute>
        }
      />
    </Routes>
  );
}

Core JS SDK

If you need to use the SDK without React:

import { Get401Client } from 'get401';

const client = new Get401Client('your-app-id', true); // appId, debug

// Login flow - email and password are sent together in one request
const loginResponse = await client.login('[email protected]', 'password123');
// If loginResponse.next === 'otp', user needs to verify OTP
if (loginResponse.next === 'otp') {
  const otpResponse = await client.challengeOTP('123456');
}

// Get current user
const user = await client.getUser();

// Registration
const registerResponse = await client.register('[email protected]', 'password123');
// If registerResponse.setup === 'email', verify email
await client.challengeEmailSetup('email-code');
// If setup === 'otp', setup OTP
const otpSetup = await client.getOTPSetup();
await client.verifyOTPSetup('otp-code');

// Logout
await client.logout();

// Refresh token
await client.refreshToken();

API Reference

Get401Provider

Provider component that wraps your React app and manages authentication state.

Props:

  • appId?: string - Your application ID (can also be set via window.GET401_APP_ID)
  • onSuccess?: (user: User) => void - Callback on successful authentication
  • onError?: (error: string) => void - Callback on error
  • debug?: boolean - Enable debug logging (default: false)
  • children: React.ReactNode - Your app components

useAuth Hook

React hook that provides authentication state and methods.

Returns:

  • status: 'idle' | 'loading' | 'authenticated' | 'unauthenticated' - Authentication status
  • user: User | null - Current user or null
  • nextStep: 'email' | 'otp' | null - Next step in authentication flow
  • error: string | null - Error message or null
  • isLoading: boolean - Is loading state
  • isAuthenticated: boolean - Boolean authentication status
  • login(email: string, password: string) - Login with email and password (both sent together in one API request)
  • challengeOTP(code: string) - Submit OTP challenge
  • logout() - Logout current user
  • getUser() - Get current user
  • register(email: string, password: string) - Register new user
  • challengeEmailSetup(code: string) - Verify email code during registration
  • getOTPSetup() - Get OTP setup data (secret, QR code)
  • verifyOTPSetup(code: string) - Verify OTP setup code
  • refreshToken() - Refresh authentication token
  • clearError() - Clear error message

Get401Client

Pure JavaScript/TypeScript client without React dependencies.

const client = new Get401Client(appId: string, debug?: boolean);

Methods:

  • login(email: string, password: string) - Login with email and password. Both email and password are sent together in a single API request to /v1/platform/auth/login. Returns LoginResponse with next: 'otp' if OTP verification is required.
  • challengeOTP(code: string) - Submit OTP code
  • register(email: string, password: string) - Register new user
  • challengeEmailSetup(code: string) - Verify email code during registration
  • getOTPSetup() - Get OTP setup data (returns { secret, otpUrl, otpQrCode })
  • verifyOTPSetup(code: string) - Verify OTP setup code
  • getUser() - Get current user
  • logout() - Logout
  • refreshToken() - Refresh authentication token
  • isAuthenticated() - Check authentication status (always returns true)
  • getAppId() - Get client ID

Types

interface User {
  id: string;
  email: string;
  name?: string;
  picture?: string;
}

interface LoginResponse {
  next: 'email' | 'otp';
}

interface ChallengeResponse {
  next?: 'email' | 'otp' | null;
}

interface RegisterResponse {
  setup: 'email' | 'otp';
}

interface OTPSetupResponse {
  secret: string;
  otpUrl: string;
  otpQrCode: string;
}

Authentication Flow

Login Flow

Important: The login method sends both email and password in a single request.

  1. User submits email and password together via login(email, password) - both are sent in one API call
  2. Server validates credentials and responds with:
    • If MFA/OTP is required: { next: 'otp' }
    • If login is successful: user is authenticated
  3. If nextStep === 'otp', user enters OTP code and calls challengeOTP(code)
  4. On success, user is authenticated and user object is available

Registration Flow

  1. User submits email and password via register(email, password)
  2. Response will have setup: 'email' or setup: 'otp'
  3. If setup === 'email':
    • User enters email verification code
    • Call challengeEmailSetup(code)
    • May need to setup OTP next
  4. If setup === 'otp' or after email verification:
    • Call getOTPSetup() to get QR code
    • User scans QR code with authenticator app
    • User enters OTP code and calls verifyOTPSetup(code)
  5. On success, user is authenticated

TypeScript Support

This package is written in TypeScript and includes full type definitions. All exports are fully typed.

License

MIT