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 🙏

© 2025 – Pkg Stats / Ryan Hefner

zenuxs-oauth

v2.3.2

Published

Lightweight OAuth 2.0 client for Zenuxs authentication system

Downloads

1,601

Readme

🔐 Zenuxs OAuth

Universal OAuth 2.0 + PKCE Client for Modern Applications

npm version License: MIT Bundle Size Downloads

A comprehensive, production-ready OAuth 2.0 + PKCE client library that works seamlessly across Browser, Node.js, React Native, and Web Workers. Built with security, developer experience, and universal compatibility in mind.


🚀 Why Zenuxs OAuth?

Universal Platform Support

Unlike most OAuth libraries that lock you into a specific environment, Zenuxs OAuth works everywhere:

  • Browser (Chrome, Firefox, Safari, Edge)
  • Node.js (Server-side authentication)
  • React Native (iOS & Android)
  • Web Workers (Background authentication)

Enterprise-Grade Security

  • 🔒 PKCE (RFC 7636) - Protection against authorization code interception
  • 🛡️ CSRF Protection - Built-in state parameter validation
  • 🔐 Secure Token Storage - Flexible storage options (Memory, Session, Local)
  • Automatic Token Refresh - Seamless token renewal before expiration
  • 🚫 Token Revocation - Properly invalidate tokens on logout

Developer-First Experience

  • 📦 Zero Dependencies - Lightweight and fast
  • 🎯 TypeScript Support - Full type definitions included
  • 🔌 Multiple Auth Flows - Redirect, Popup, and Manual flows
  • 📡 Event System - React to authentication state changes
  • 🎨 Framework Agnostic - Works with React, Vue, Angular, Svelte, or vanilla JS
  • 📚 Comprehensive Documentation - Clear examples and API reference

📦 Installation

Browser (CDN)

<script src="https://unpkg.com/[email protected]/dist/zenux-oauth.min.js"></script>

NPM / Yarn

npm install zenuxs-oauth
# or
yarn add zenuxs-oauth

ES6 Module

import ZenuxOAuth from 'zenuxs-oauth';

CommonJS

const ZenuxOAuth = require('zenuxs-oauth');

🎯 Quick Start

Browser - Popup Flow

const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    authServer: "https://api.auth.zenuxs.in",
    redirectUri: window.location.origin + "/callback.html",
    scopes: "openid profile email",
    storage: "sessionStorage"
});

// Login with popup
async function login() {
    try {
        const tokens = await oauth.login({ popup: true });
        console.log("Logged in!", tokens);
    } catch (error) {
        console.error("Login failed:", error);
    }
}

// Get user info
async function getUserInfo() {
    const user = await oauth.getUserInfo();
    console.log("User:", user);
}

// Logout
async function logout() {
    await oauth.logout({ revokeTokens: true });
}

Node.js - Server-Side

const ZenuxOAuth = require('zenuxs-oauth');

const oauth = new ZenuxOAuth({
    clientId: process.env.CLIENT_ID,
    authServer: "https://api.auth.zenuxs.in",
    redirectUri: "https://yourapp.com/callback",
    scopes: "openid profile email",
    storage: "memory",
    fetchFunction: require('node-fetch')
});

// Express.js route
app.get('/auth/login', async (req, res) => {
    const authData = await oauth.login();
    req.session.state = authData.state;
    req.session.codeVerifier = authData.codeVerifier;
    res.redirect(authData.url);
});

app.get('/auth/callback', async (req, res) => {
    const tokens = await oauth.handleCallback(req.url);
    req.session.tokens = tokens;
    res.redirect('/dashboard');
});

React Native

import ZenuxOAuth from 'zenuxs-oauth';
import { Linking } from 'react-native';

const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    authServer: "https://api.auth.zenuxs.in",
    redirectUri: "myapp://callback",
    scopes: "openid profile email",
    storage: "memory"
});

async function login() {
    const authData = await oauth.login();
    await Linking.openURL(authData.url);
    
    // Listen for callback
    Linking.addEventListener('url', async (event) => {
        if (event.url.startsWith('myapp://callback')) {
            const tokens = await oauth.handleCallback(event.url);
            console.log("Tokens:", tokens);
        }
    });
}

🎨 Features Overview

🌐 Multiple Authentication Flows

1. Redirect Flow (Traditional)

// Redirects the entire page
oauth.login();

2. Popup Flow (Modern)

// Opens authentication in a popup window
const tokens = await oauth.login({ 
    popup: true,
    popupWidth: 600,
    popupHeight: 700
});

3. Manual Flow (Non-Browser)

// Get authorization URL for manual handling
const authData = await oauth.login();
console.log("Redirect user to:", authData.url);
// Handle callback manually with authData.state and authData.codeVerifier

🔄 Automatic Token Refresh

const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    authServer: "https://api.auth.zenuxs.in",
    autoRefresh: true,           // Enable auto-refresh
    refreshThreshold: 300        // Refresh 5 minutes before expiry
});

// Listen to refresh events
oauth.on('tokenRefresh', (newTokens) => {
    console.log("Tokens automatically refreshed!");
});

📡 Comprehensive Event System

// Authentication events
oauth.on('login', (tokens) => {
    console.log("User logged in");
});

oauth.on('logout', () => {
    console.log("User logged out");
});

// Token management events
oauth.on('tokenRefresh', (newTokens) => {
    console.log("Tokens refreshed");
});

oauth.on('tokenExpired', () => {
    console.log("Token expired");
});

// Error handling
oauth.on('error', (error) => {
    console.error("OAuth error:", error);
});

// State changes
oauth.on('stateChange', (change) => {
    console.log("State changed:", change);
});

🛡️ Built-in Callback Handler

Create a beautiful, functional callback page with zero effort:

<!DOCTYPE html>
<html>
<head>
    <title>OAuth Callback</title>
</head>
<body>
    <div id="zenux-oauth-callback-container"></div>
    <script src="https://unpkg.com/[email protected]/dist/zenux-oauth.min.js"></script>
    <script>
        // Automatically handles OAuth callback and closes popup
        window.zenuxOAuthCallback = new ZenuxOAuthCallbackHandler({
            debug: true,
            autoClose: true,
            autoCloseDelay: 2000,
            successMessage: "Authentication successful! Redirecting...",
            errorMessage: "Authentication failed. Please try again."
        });
    </script>
</body>
</html>

💾 Flexible Storage Options

// Session Storage (default) - survives page reload, cleared on tab close
storage: "sessionStorage"

// Local Storage - persists across browser sessions
storage: "localStorage"

// Memory Storage - cleared on page reload (best for Node.js/React Native)
storage: "memory"

// Custom prefix for storage keys
storagePrefix: "myapp_auth_"

🔍 Token Management

// Check authentication status
if (oauth.isAuthenticated()) {
    console.log("User is authenticated");
}

// Get current tokens
const tokens = oauth.getTokens();

// Check if token is expired
if (oauth.isTokenExpired()) {
    await oauth.refreshTokens();
}

// Manually refresh tokens
const newTokens = await oauth.refreshTokens();

// Revoke specific token
await oauth.revokeToken(tokens.access_token, 'access_token');

// Revoke all tokens on logout
await oauth.logout({ revokeTokens: true });

// Introspect token validity
const tokenInfo = await oauth.introspectToken();
console.log("Token active:", tokenInfo.active);

👤 User Information

// Get user profile from userinfo endpoint
const user = await oauth.getUserInfo();
console.log(user.name, user.email, user.picture);

// Multiple userinfo endpoints supported
const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    authServer: "https://api.auth.zenuxs.in",
    userinfoEndpoint: "/oauth/userinfo"  // or custom endpoint
});

📤 Session Export/Import

// Export session (for cross-device sync or persistence)
const sessionData = oauth.exportSession();
localStorage.setItem('oauth_backup', JSON.stringify(sessionData));

// Import session (restore authentication state)
const savedSession = JSON.parse(localStorage.getItem('oauth_backup'));
oauth.importSession(savedSession);

🎯 Authenticated Fetch

// Get pre-configured fetch with automatic token injection
const authFetch = oauth.getAuthenticatedFetch();

// Use it like regular fetch
const response = await authFetch('https://api.yourapp.com/protected', {
    method: 'GET'
});

// Automatically adds Authorization header and handles token refresh

🔧 Advanced Configuration

Complete Configuration Object

const oauth = new ZenuxOAuth({
    // Required
    clientId: "your-client-id",
    
    // Server Configuration
    authServer: "https://api.auth.zenuxs.in",
    authorizeEndpoint: "/oauth/authorize",
    tokenEndpoint: "/oauth/token",
    userinfoEndpoint: "/oauth/userinfo",
    revokeEndpoint: "/oauth/revoke",
    introspectEndpoint: "/oauth/introspect",
    
    // OAuth Parameters
    redirectUri: window.location.origin + "/callback.html",
    scopes: "openid profile email offline_access",
    responseType: "code",
    
    // Security
    usePKCE: true,              // Enable PKCE
    useCSRF: true,              // Enable CSRF protection (browser only)
    validateState: true,         // Validate state parameter
    
    // Storage
    storage: "sessionStorage",   // sessionStorage | localStorage | memory
    storagePrefix: "zenux_oauth_",
    
    // Token Management
    autoRefresh: true,           // Enable automatic token refresh
    refreshThreshold: 300,       // Refresh 5 minutes before expiry
    
    // UI Configuration (Browser only)
    popupWidth: 600,
    popupHeight: 700,
    popupFeatures: "toolbar=no,location=no,status=no,menubar=no",
    
    // Lifecycle Callbacks
    onBeforeLogin: (config) => {
        console.log("About to login");
    },
    onAfterLogin: (tokens) => {
        console.log("Login successful");
    },
    onBeforeLogout: () => {
        console.log("About to logout");
    },
    onAfterLogout: () => {
        console.log("Logout complete");
    },
    
    // Additional Parameters
    extraAuthParams: {
        prompt: "login",
        display: "popup"
    },
    extraTokenParams: {
        client_secret: "secret"  // Only for confidential clients
    },
    
    // Environment
    environment: "browser",      // Auto-detected: browser | node | react-native | worker
    fetchFunction: fetch,        // Custom fetch implementation
    debug: true                  // Enable debug logging
});

🎭 Framework Integration Examples

React Hook

import { useState, useEffect } from 'react';
import ZenuxOAuth from 'zenuxs-oauth';

function useZenuxAuth(config) {
    const [isAuthenticated, setIsAuthenticated] = useState(false);
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);
    const [oauth] = useState(() => new ZenuxOAuth(config));

    useEffect(() => {
        setIsAuthenticated(oauth.isAuthenticated());
        
        oauth.on('login', async (tokens) => {
            setIsAuthenticated(true);
            const userInfo = await oauth.getUserInfo();
            setUser(userInfo);
        });

        oauth.on('logout', () => {
            setIsAuthenticated(false);
            setUser(null);
        });

        setLoading(false);

        return () => {
            oauth.off('login');
            oauth.off('logout');
        };
    }, [oauth]);

    return {
        isAuthenticated,
        user,
        loading,
        login: (options) => oauth.login(options),
        logout: (options) => oauth.logout(options),
        getTokens: () => oauth.getTokens()
    };
}

// Usage in component
function App() {
    const { isAuthenticated, user, loading, login, logout } = useZenuxAuth({
        clientId: "your-client-id",
        authServer: "https://api.auth.zenuxs.in",
        redirectUri: window.location.origin + "/callback.html",
        scopes: "openid profile email"
    });

    if (loading) return <div>Loading...</div>;

    return (
        <div>
            {isAuthenticated ? (
                <div>
                    <h1>Welcome, {user?.name}!</h1>
                    <button onClick={() => logout({ revokeTokens: true })}>
                        Logout
                    </button>
                </div>
            ) : (
                <button onClick={() => login({ popup: true })}>
                    Login with Zenuxs
                </button>
            )}
        </div>
    );
}

Vue 3 Composable

import { ref, onMounted, onUnmounted } from 'vue';
import ZenuxOAuth from 'zenuxs-oauth';

export function useZenuxAuth(config) {
    const isAuthenticated = ref(false);
    const user = ref(null);
    const loading = ref(true);
    
    let oauth;

    onMounted(() => {
        oauth = new ZenuxOAuth(config);
        isAuthenticated.value = oauth.isAuthenticated();
        
        oauth.on('login', async (tokens) => {
            isAuthenticated.value = true;
            user.value = await oauth.getUserInfo();
        });

        oauth.on('logout', () => {
            isAuthenticated.value = false;
            user.value = null;
        });

        loading.value = false;
    });

    onUnmounted(() => {
        if (oauth) {
            oauth.off('login');
            oauth.off('logout');
        }
    });

    return {
        isAuthenticated,
        user,
        loading,
        login: (options) => oauth.login(options),
        logout: (options) => oauth.logout(options)
    };
}

Angular Service

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import ZenuxOAuth from 'zenuxs-oauth';

@Injectable({
    providedIn: 'root'
})
export class AuthService {
    private oauth: any;
    private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
    private userSubject = new BehaviorSubject<any>(null);

    public isAuthenticated$: Observable<boolean> = this.isAuthenticatedSubject.asObservable();
    public user$: Observable<any> = this.userSubject.asObservable();

    constructor() {
        this.oauth = new ZenuxOAuth({
            clientId: 'your-client-id',
            authServer: 'https://api.auth.zenuxs.in',
            redirectUri: window.location.origin + '/callback.html',
            scopes: 'openid profile email'
        });

        this.isAuthenticatedSubject.next(this.oauth.isAuthenticated());

        this.oauth.on('login', async (tokens: any) => {
            this.isAuthenticatedSubject.next(true);
            const user = await this.oauth.getUserInfo();
            this.userSubject.next(user);
        });

        this.oauth.on('logout', () => {
            this.isAuthenticatedSubject.next(false);
            this.userSubject.next(null);
        });
    }

    async login(options?: any): Promise<void> {
        await this.oauth.login(options);
    }

    async logout(options?: any): Promise<void> {
        await this.oauth.logout(options);
    }

    getTokens() {
        return this.oauth.getTokens();
    }
}

📊 Comparison with Other OAuth Libraries

| Feature | Zenuxs OAuth | Auth0-SPA | Firebase Auth | Hello.js | OAuth2-Client | |---------|--------------|-----------|---------------|----------|---------------| | Universal Support | ✅ All platforms | ❌ Browser only | ⚠️ Limited | ❌ Browser only | ⚠️ Node only | | PKCE Support | ✅ Built-in | ✅ Yes | ✅ Yes | ❌ No | ⚠️ Manual | | Popup Flow | ✅ Native | ✅ Yes | ❌ No | ✅ Yes | ❌ No | | Auto Token Refresh | ✅ Configurable | ✅ Yes | ✅ Yes | ❌ No | ⚠️ Manual | | Event System | ✅ Comprehensive | ⚠️ Limited | ✅ Good | ❌ No | ❌ No | | Zero Dependencies | ✅ Yes | ❌ No | ❌ No | ✅ Yes | ❌ No | | TypeScript | ✅ Full support | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | | Bundle Size | 🟢 ~15KB | 🟡 ~50KB | 🔴 ~150KB | 🟢 ~10KB | 🟡 ~30KB | | React Native | ✅ Native | ❌ No | ✅ Separate pkg | ❌ No | ❌ No | | Web Workers | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | | Custom Storage | ✅ Flexible | ⚠️ Limited | ❌ Fixed | ❌ Fixed | ⚠️ Limited | | Token Revocation | ✅ Built-in | ✅ Yes | ⚠️ Limited | ❌ No | ⚠️ Manual | | Session Export | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | | Learning Curve | 🟢 Low | 🟡 Medium | 🟡 Medium | 🟢 Low | 🔴 High | | Provider Lock-in | ✅ None | 🔴 Auth0 only | 🔴 Firebase only | ⚠️ Multiple | ✅ None | | License | ✅ MIT | ✅ MIT | ⚠️ Proprietary | ✅ MIT | ✅ MIT |

Key Advantages

🎯 Zenuxs OAuth stands out with:

  1. True Universal Support - One library for browser, Node.js, React Native, and Web Workers
  2. Zero Dependencies - No bloat, just pure OAuth functionality
  3. Developer Experience - Intuitive API with comprehensive events
  4. Flexibility - Works with any OAuth 2.0 provider, not locked to a specific service
  5. Modern Architecture - Built with PKCE, CSRF protection, and auto-refresh from the ground up
  6. Session Portability - Export/import sessions for cross-device authentication
  7. Lightweight - Only ~15KB minified + gzipped

🔒 Security Best Practices

1. Always Use PKCE

const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    usePKCE: true  // Always enabled by default
});

2. Enable CSRF Protection

const oauth = new ZenuxOAuth({
    clientId: "your-client-id",
    useCSRF: true,      // Browser only
    validateState: true  // Verify state parameter
});

3. Use Secure Storage

// For web apps: Use sessionStorage (cleared on tab close)
storage: "sessionStorage"

// For SPAs with persistence: Use localStorage with caution
storage: "localStorage"

// For server-side: Always use memory storage
storage: "memory"

4. Revoke Tokens on Logout

await oauth.logout({ 
    revokeTokens: true  // Properly invalidate tokens
});

5. Handle Token Refresh Gracefully

oauth.on('tokenRefresh', (newTokens) => {
    // Update your application state
    updateAuthState(newTokens);
});

oauth.on('error', async (error) => {
    if (error.code === 'TOKEN_REFRESH_FAILED') {
        // Force re-login if refresh fails
        await oauth.logout();
        redirectToLogin();
    }
});

6. Implement Timeout for Popups

try {
    const tokens = await oauth.login({ 
        popup: true,
        timeout: 300000  // 5 minutes timeout
    });
} catch (error) {
    if (error.code === 'LOGIN_TIMEOUT') {
        console.log('Login took too long');
    }
}

🐛 Error Handling

Error Codes Reference

try {
    await oauth.login({ popup: true });
} catch (error) {
    switch (error.code) {
        case 'INVALID_CONFIG':
            // Configuration validation failed
            break;
        case 'FETCH_UNAVAILABLE':
            // Fetch API not available
            break;
        case 'POPUP_BLOCKED':
            // Browser blocked popup window
            alert('Please allow popups for this site');
            break;
        case 'AUTH_CANCELLED':
            // User closed popup or cancelled authentication
            console.log('User cancelled login');
            break;
        case 'LOGIN_TIMEOUT':
            // Login process exceeded timeout
            console.log('Login timeout');
            break;
        case 'STATE_MISMATCH':
            // CSRF protection: state parameter mismatch
            console.error('Security error detected');
            break;
        case 'NO_AUTH_CODE':
            // Authorization code not received
            break;
        case 'TOKEN_EXCHANGE_FAILED':
            // Failed to exchange code for tokens
            break;
        case 'TOKEN_REFRESH_FAILED':
            // Failed to refresh access token
            await oauth.logout();
            break;
        case 'NO_REFRESH_TOKEN':
            // No refresh token available
            break;
        case 'NO_ACCESS_TOKEN':
            // No access token available
            break;
        case 'USERINFO_FAILED':
            // Failed to fetch user information
            break;
        case 'REVOKE_FAILED':
            // Token revocation failed
            break;
        case 'INTROSPECT_FAILED':
            // Token introspection failed
            break;
        default:
            console.error('Unknown error:', error);
    }
}

Custom Error Handling

// Global error handler
oauth.on('error', (error) => {
    console.error('OAuth Error:', {
        code: error.code,
        message: error.message,
        details: error.details,
        environment: error.environment,
        timestamp: error.timestamp
    });
    
    // Send to error tracking service
    trackError(error);
});

📚 API Reference

Constructor

new ZenuxOAuth(config)

Methods

Authentication

  • login(options?) - Start OAuth flow
  • handleCallback(url) - Process OAuth callback
  • logout(options?) - Logout user

Token Management

  • getTokens() - Get current tokens
  • isAuthenticated() - Check authentication status
  • isTokenExpired() - Check if token is expired
  • refreshTokens() - Manually refresh tokens
  • revokeToken(token, tokenType) - Revoke specific token

User Information

  • getUserInfo() - Fetch user profile
  • introspectToken(token?) - Validate token

Session Management

  • getSessionState() - Get current session state
  • exportSession() - Export session data
  • importSession(data) - Import session data

Events

  • on(event, handler) - Add event listener
  • off(event, handler) - Remove event listener

Utilities

  • getAuthenticatedFetch() - Get authenticated fetch function
  • updateConfig(config) - Update configuration
  • destroy() - Cleanup resources

Static Methods

  • ZenuxOAuth.create(config) - Create new instance
  • ZenuxOAuth.getInstance(config) - Get singleton instance
  • ZenuxOAuth.destroyInstance() - Destroy singleton
  • ZenuxOAuth.createCallbackHandler(config) - Create callback handler

🧪 Testing

Unit Testing with Jest

import ZenuxOAuth from 'zenuxs-oauth';

describe('ZenuxOAuth', () => {
    let oauth;

    beforeEach(() => {
        oauth = new ZenuxOAuth({
            clientId: 'test-client-id',
            authServer: 'https://test-auth.example.com',
            storage: 'memory'
        });
    });

    afterEach(() => {
        oauth.destroy();
    });

    test('should initialize correctly', () => {
        expect(oauth).toBeDefined();
        expect(oauth.isAuthenticated()).toBe(false);
    });

    test('should handle login flow', async () => {
        const authData = await oauth.login();
        expect(authData).toHaveProperty('url');
        expect(authData).toHaveProperty('state');
        expect(authData).toHaveProperty('codeVerifier');
    });

    test('should emit login event on successful authentication', (done) => {
        oauth.on('login', (tokens) => {
            expect(tokens).toHaveProperty('access_token');
            done();
        });

        // Simulate login...
    });
});

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone repository
git clone https://github.com/developers-rs5/zenuxs-oauth.git
cd zenuxs-oauth

# Install dependencies
npm install

# Run tests
npm test

# Build library
npm run build

# Run examples
npm run dev

📄 License

MIT License © 2025 Zenuxs Team

Developed by Rishabh Sharma (rs)


🔗 Links


💬 Support

Need help? We're here for you:


🎉 Acknowledgments

Special thanks to all contributors and the OAuth 2.0 community for making secure authentication accessible to everyone.


Made with ❤️ by the Zenuxs Team