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

@abhiraj_patil/authifyer-sdk

v1.0.16

Published

Drop-in authentication SDK for React — OAuth, Email/Password, OTP verification, session management & pre-built UI components.

Downloads

980

Readme


✨ Features

  • 🔐 Email/Password Authentication — Sign up, sign in & OTP email verification out of the box
  • 🌐 OAuth Login — One-click Google & GitHub login with automatic token handling
  • 🎨 Pre-built UI Components — Beautiful, ready-to-use <SignIn />, <SignUp />, <UserButton />, <UserProfile /> components
  • 🔄 Automatic Session Management — JWT access tokens with silent refresh, long-lived refresh tokens
  • ⚛️ React HooksuseAuth(), useUser(), useSession(), useAuthifyer() for full control
  • 📦 Zero Config — Works with Vite, Next.js, and Create React App

📦 Installation

npm install @abhiraj_patil/authifyer-sdk

Peer dependencies (if not already in your project):

npm install react react-dom

🚀 Quick Start

1. Get Your Publishable Key

Sign up at the Authifyer Dashboard, create a project, and copy your Publishable Key.

2. Add the Provider

Wrap your app with <AuthifyerProvider>:

// main.tsx or App.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { AuthifyerProvider } from '@abhiraj_patil/authifyer-sdk';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <AuthifyerProvider publishableKey="pk_your_publishable_key_here">
    <App />
  </AuthifyerProvider>
);

3. Add Sign In / Sign Up

import { SignIn, SignUp, useUser } from '@abhiraj_patil/authifyer-sdk';

function App() {
  const { user, isSignedIn } = useUser();

  if (!isSignedIn) {
    return <SignIn />;
    // or <SignUp /> for registration
  }

  return <h1>Welcome, {user?.name}!</h1>;
}

That's it! You have a fully working auth flow. 🎉


🔧 Configuration

AuthifyerProvider Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | publishableKey | string | No* | Your project's publishable key | | backendUrl | string | No | Custom backend URL (for self-hosted deployments) | | config | ProjectConfig | No | Override project config (useful for testing) | | children | ReactNode | Yes | Your application tree |

* If not passed as a prop, the SDK will automatically read from environment variables:

  • Vite: VITE_AUTHIFYER_PUBLISHABLE_KEY
  • Next.js: NEXT_PUBLIC_AUTHIFYER_PUBLISHABLE_KEY
  • CRA: REACT_APP_AUTHIFYER_PUBLISHABLE_KEY

Example with Environment Variable (Vite)

# .env
VITE_AUTHIFYER_PUBLISHABLE_KEY=pk_your_publishable_key_here
// No need to pass publishableKey — the SDK reads it from env automatically
<AuthifyerProvider>
  <App />
</AuthifyerProvider>

Self-Hosted Backend

<AuthifyerProvider
  publishableKey="pk_your_key"
  backendUrl="https://your-auth-server.example.com"
>
  <App />
</AuthifyerProvider>

📖 Authentication Methods

1. OAuth Login (Google / GitHub)

The SDK provides one-click OAuth login. When a user clicks the OAuth button, they are redirected to the provider (Google/GitHub), authenticated, and returned to your app with tokens automatically handled.

Using Pre-built Components

The <SignIn /> and <SignUp /> components include OAuth buttons automatically based on your project configuration:

import { SignIn } from '@abhiraj_patil/authifyer-sdk';

function LoginPage() {
  return <SignIn />;
}

The component will display "Continue with Google" and "Continue with GitHub" buttons if those providers are enabled in your Authifyer dashboard.

Using the Client Directly (Custom UI)

If you want to build your own login UI, use the useAuthifyer() hook:

import { useAuthifyer } from '@abhiraj_patil/authifyer-sdk';

function CustomLogin() {
  const client = useAuthifyer();

  return (
    <div>
      <button onClick={() => client.signInWithOAuth('google')}>
        Sign in with Google
      </button>
      <button onClick={() => client.signInWithOAuth('github')}>
        Sign in with GitHub
      </button>
    </div>
  );
}

How OAuth Works Under the Hood

1. User clicks "Continue with Google"
2. SDK redirects to:  /oauth2/authorization/google?publishable_key=<key>&redirect_uri=<origin>
3. User authenticates on Google's consent screen
4. Backend handles the callback, creates a session
5. User is redirected back to your app with ?access_token=...&refresh_token=... in the URL
6. SDK automatically extracts tokens from the URL, stores them, and cleans the URL
7. User is now authenticated ✅

2. Email/Password Sign Up

The SDK provides a full registration flow with built-in OTP (One-Time Password) email verification.

Using the Pre-built Component

import { SignUp } from '@abhiraj_patil/authifyer-sdk';

function RegisterPage() {
  return <SignUp />;
}

How the Sign Up + OTP Verification Flow Works

Step 1: User enters email & password → clicks "Continue"
    ↓
Step 2: SDK calls POST /authifyer/project/register/email
        with { email, password, publicProjectId }
    ↓
Step 3: Backend creates the user and sends a 6-digit OTP code to the email
        Response includes { subjectId, accessToken, refreshToken }
    ↓
Step 4: SDK automatically switches to the OTP verification screen
        Shows "Verify your email — Code sent to [email protected]"
    ↓
Step 5: User enters the 6-digit code → clicks "Verify Code"
    ↓
Step 6: SDK calls POST /api/auth/verify-email
        with { token: "123456", subjectId: "user-id" }
    ↓
Step 7: Backend verifies the OTP code
    ↓
Step 8: On success → user is fully authenticated ✅
        On failure → error message, user can retry

Custom Sign Up with Manual OTP Handling

import { useAuthifyer } from '@abhiraj_patil/authifyer-sdk';
import { useState } from 'react';

function CustomSignUp() {
  const client = useAuthifyer();
  const [step, setStep] = useState<'register' | 'verify'>('register');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [subjectId, setSubjectId] = useState('');
  const [otpCode, setOtpCode] = useState('');

  // Step 1: Register the user
  const handleRegister = async () => {
    try {
      const data = await client.signUpWithEmail(email, password);
      if (data?.subjectId) {
        setSubjectId(data.subjectId);
        setStep('verify'); // Move to OTP verification
      }
    } catch (err) {
      console.error('Registration failed', err);
    }
  };

  // Step 2: Verify the OTP code
  const handleVerify = async () => {
    try {
      await client.verifyEmail(otpCode, subjectId);
      // ✅ User is now verified and signed in!
    } catch (err) {
      console.error('Verification failed', err);
    }
  };

  if (step === 'verify') {
    return (
      <div>
        <h2>Check your email</h2>
        <p>We sent a 6-digit code to {email}</p>
        <input
          value={otpCode}
          onChange={(e) => setOtpCode(e.target.value)}
          placeholder="Enter 6-digit code"
          maxLength={6}
        />
        <button onClick={handleVerify}>Verify</button>
      </div>
    );
  }

  return (
    <div>
      <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" />
      <input value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" type="password" />
      <button onClick={handleRegister}>Sign Up</button>
    </div>
  );
}

3. Email/Password Sign In

Using the Pre-built Component

import { SignIn } from '@abhiraj_patil/authifyer-sdk';

function LoginPage() {
  return <SignIn />;
}

Using the Client Directly

import { useAuthifyer } from '@abhiraj_patil/authifyer-sdk';

function CustomLogin() {
  const client = useAuthifyer();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = async () => {
    try {
      await client.signInWithEmail(email, password);
      // ✅ User is now signed in — session & tokens are managed automatically
    } catch (err) {
      console.error('Invalid credentials');
    }
  };

  return (
    <form onSubmit={(e) => { e.preventDefault(); handleLogin(); }}>
      <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" />
      <input value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" type="password" />
      <button type="submit">Sign In</button>
    </form>
  );
}

🎨 Pre-built UI Components

All components come with premium styling out of the box.

<SignIn />

Full sign-in form with OAuth buttons + email/password fields. Adapts automatically to your project's enabled auth methods.

import { SignIn } from '@abhiraj_patil/authifyer-sdk';

<SignIn />

<SignUp />

Full registration form with OAuth buttons + email/password fields + OTP email verification flow.

import { SignUp } from '@abhiraj_patil/authifyer-sdk';

<SignUp />

<UserButton />

A circular avatar button (shows user initials) that opens a dropdown menu with:

  • User info (name & email)
  • Manage Account — opens the <UserProfile /> modal
  • Sign Out
import { UserButton } from '@abhiraj_patil/authifyer-sdk';

function Navbar() {
  return (
    <nav>
      <h1>My App</h1>
      <UserButton />
    </nav>
  );
}

<UserProfile />

Full account management modal with:

  • Profile overview (name, email, provider, verification status)
  • Sign out action
  • Delete account (with confirmation prompt)
import { UserProfile } from '@abhiraj_patil/authifyer-sdk';

<UserProfile onClose={() => setShowProfile(false)} />

⚛️ React Hooks

useUser()

Returns the current user object and authentication state.

import { useUser } from '@abhiraj_patil/authifyer-sdk';

function Dashboard() {
  const { user, isSignedIn, isLoading } = useUser();

  if (isLoading) return <p>Loading...</p>;
  if (!isSignedIn) return <p>Please sign in</p>;

  return (
    <div>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
      <p>Provider: {user.provider}</p>
      <p>Email Verified: {user.emailVerified ? 'Yes' : 'No'}</p>
    </div>
  );
}

useSession()

Returns the current session object with the JWT token.

import { useSession } from '@abhiraj_patil/authifyer-sdk';

function ApiCaller() {
  const { session, isSignedIn } = useSession();

  const callProtectedApi = async () => {
    const res = await fetch('/api/data', {
      headers: {
        Authorization: `Bearer ${session.token}`,
      },
    });
    // ...
  };
}

useAuth()

Returns the full auth context including client, user, session, config, and isLoading.

import { useAuth } from '@abhiraj_patil/authifyer-sdk';

function FullControl() {
  const { client, user, session, config, isLoading } = useAuth();

  // Access everything
}

useAuthifyer()

Returns the raw AuthifyerClient instance for direct API calls.

import { useAuthifyer } from '@abhiraj_patil/authifyer-sdk';

function Actions() {
  const client = useAuthifyer();

  return (
    <div>
      <button onClick={() => client.signOut()}>Sign Out</button>
      <button onClick={() => client.deleteAccount()}>Delete Account</button>
      <button onClick={() => client.refreshSession()}>Refresh Session</button>
    </div>
  );
}

🔑 Session & Token Management

The SDK handles session management automatically. Here's how it works:

Token Architecture

| Token | Storage | Lifetime | Purpose | |-------|---------|----------|---------| | Access Token (JWT) | localStorage | 5 minutes | Authenticates API requests | | Refresh Token | localStorage | Long-lived | Obtains new access tokens silently |

Automatic Token Refresh

  • The SDK starts a background timer that refreshes the access token every 4.5 minutes (before the 5-minute expiry)
  • If the page is reloaded, the SDK restores the session from localStorage
  • If the access token has expired but a refresh token exists, the SDK automatically obtains a new access token
  • All of this happens silently — no user interaction required

Session Lifecycle

App loads → AuthifyerProvider mounts
    ↓
SDK checks URL for OAuth redirect tokens
    ↓ (if found, stores them and cleans URL)
SDK checks localStorage for existing access token
    ↓ (if valid, restores session)
If no valid access token → tries refresh using refresh token
    ↓ (if successful, new access token is issued)
If no refresh token → user needs to sign in

After sign in:
    Access token → saved to localStorage + Authorization header
    Refresh token → saved to localStorage
    Auto-refresh timer → started (every 4.5 min)

On sign out:
    Tokens → cleared from localStorage
    Session → nullified
    Timer → stopped

🗃️ TypeScript Types

User

interface User {
  authifyerId: string;    // Unique user ID
  name: string;           // User's display name
  email: string;          // User's email address
  emailVerified: boolean; // Whether email has been verified
  isActive: boolean;      // Whether the account is active
  provider: string;       // Auth provider: 'email' | 'google' | 'github'
}

Session

interface Session {
  token: string;     // The JWT access token
  sessionId: string; // Unique session identifier
  expireAt: number;  // Token expiration timestamp (Unix)
  user: User;        // The authenticated user
}

ProjectConfig

interface ProjectConfig {
  projectName?: string;                    // Your project name
  emailPasswordEnabled: boolean;           // Is email/password auth enabled
  oauthProviders: ('google' | 'github')[]; // Enabled OAuth providers
}

🧑‍💻 Client API Reference

The AuthifyerClient (accessed via useAuthifyer()) exposes these methods:

| Method | Description | |--------|-------------| | signInWithEmail(email, password) | Sign in with email & password | | signUpWithEmail(email, password) | Register a new user (returns subjectId for OTP) | | verifyEmail(token, subjectId) | Verify email with 6-digit OTP code | | signInWithOAuth('google' \| 'github') | Redirect to OAuth provider for login | | signOut() | Sign out and clear all tokens | | deleteAccount() | Permanently delete the user's account | | refreshSession() | Manually refresh the access token | | rotateSession() | Rotate the underlying long-lived session |


📋 Full Example App

// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { AuthifyerProvider } from '@abhiraj_patil/authifyer-sdk';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <AuthifyerProvider publishableKey="pk_your_key_here">
    <App />
  </AuthifyerProvider>
);
// App.tsx
import { useUser, SignIn, SignUp, UserButton } from '@abhiraj_patil/authifyer-sdk';
import { useState } from 'react';

function App() {
  const { user, isSignedIn, isLoading } = useUser();
  const [isLogin, setIsLogin] = useState(true);

  if (isLoading) {
    return <div className="loading">Loading...</div>;
  }

  // Not signed in — show auth forms
  if (!isSignedIn) {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '100vh' }}>
        <div>
          {isLogin ? <SignIn /> : <SignUp />}
          <p style={{ textAlign: 'center', marginTop: '1rem' }}>
            {isLogin ? "Don't have an account? " : 'Already have an account? '}
            <button onClick={() => setIsLogin(!isLogin)} style={{ color: '#6c63ff', background: 'none', border: 'none', cursor: 'pointer' }}>
              {isLogin ? 'Sign Up' : 'Sign In'}
            </button>
          </p>
        </div>
      </div>
    );
  }

  // Signed in — show dashboard
  return (
    <div>
      <nav style={{ display: 'flex', justifyContent: 'space-between', padding: '1rem 2rem', borderBottom: '1px solid #eee' }}>
        <h1>My App</h1>
        <UserButton />
      </nav>
      <main style={{ padding: '2rem' }}>
        <h2>Welcome, {user?.name || user?.email}!</h2>
        <p>You are signed in via <strong>{user?.provider}</strong>.</p>
      </main>
    </div>
  );
}

export default App;

❓ FAQ

Q: How do I protect routes?

Use the useUser() hook to check authentication state and conditionally render:

const { isSignedIn } = useUser();
if (!isSignedIn) return <Navigate to="/login" />;

Q: Can I use this with Next.js?

Yes. Set your key as NEXT_PUBLIC_AUTHIFYER_PUBLISHABLE_KEY in .env.local and wrap your app with <AuthifyerProvider>.

Q: How do I access the JWT token for API calls?

const { session } = useSession();
// Use session.token in your Authorization header

Q: What happens when the access token expires?

The SDK automatically refreshes it every 4.5 minutes. Your users will never experience token expiry interruptions.


📄 License

ISC