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

@egintegrations/auth-services

v0.1.0

Published

React Native authentication utilities for token management, biometric authentication, and secure key storage. Works with Expo and bare React Native.

Downloads

86

Readme

@egintegrations/auth-services

React Native authentication utilities for token management, biometric authentication, and secure key storage. Works with Expo and bare React Native.

Features

  • TokenManager: Secure token storage and retrieval
  • BiometricAuth: Face ID / Touch ID authentication
  • SecureKeyStore: Generic secure key/value storage
  • TypeScript: Full type safety with TypeScript support
  • Configurable: Customizable storage keys, prompts, and behavior
  • Well-tested: 100% test coverage (69 tests)
  • Dual Module: ESM and CommonJS support

Installation

npm install @egintegrations/auth-services expo-secure-store expo-local-authentication

Peer Dependencies

This package requires:

  • expo-secure-store >= 12.0.0
  • expo-local-authentication >= 13.0.0
  • react-native >= 0.70.0

Quick Start

import { TokenManager, BiometricAuth, SecureKeyStore } from '@egintegrations/auth-services';

// Token management
const tokenManager = new TokenManager();
await tokenManager.saveToken('your-auth-token');
const token = await tokenManager.getToken();

// Biometric authentication
const bioAuth = new BiometricAuth();
if (await bioAuth.canAuthenticate()) {
  await bioAuth.enable('username');
  const username = await bioAuth.authenticate();
}

// Secure key storage
const keyStore = new SecureKeyStore({ keyPrefix: 'app_' });
await keyStore.set('api_key', 'secret-key');
const apiKey = await keyStore.get('api_key');

TokenManager

Manages authentication tokens in secure storage.

Basic Usage

import { TokenManager } from '@egintegrations/auth-services';

// Create manager with default storage key
const tokenManager = new TokenManager();

// Save token
await tokenManager.saveToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');

// Get token
const token = await tokenManager.getToken();

// Check if token exists
const hasToken = await tokenManager.hasToken();

// Clear token
await tokenManager.clearToken();

Custom Storage Key

// Use custom storage key for multiple token types
const accessTokenManager = new TokenManager({ storageKey: 'access_token' });
const refreshTokenManager = new TokenManager({ storageKey: 'refresh_token' });

await accessTokenManager.saveToken('access-token-123');
await refreshTokenManager.saveToken('refresh-token-456');

Singleton Pattern

For simple apps with single token:

import { SingletonTokenManager } from '@egintegrations/auth-services';

// All methods are static
await SingletonTokenManager.saveToken('token');
const token = await SingletonTokenManager.getToken();
const hasToken = await SingletonTokenManager.hasToken();
await SingletonTokenManager.clearToken();

BiometricAuth

Manages biometric authentication (Face ID / Touch ID).

Check Availability

import { BiometricAuth } from '@egintegrations/auth-services';

const bioAuth = new BiometricAuth();

// Check if device supports biometric auth
const canAuth = await bioAuth.canAuthenticate();

// Get biometric type
const type = await bioAuth.getBiometricType(); // 'faceId' | 'touchId' | 'fingerprint' | 'none'

Enable Biometric Login

const bioAuth = new BiometricAuth();

try {
  // Prompt user to authenticate and enable biometric login
  await bioAuth.enable('username');
  console.log('Biometric login enabled');
} catch (error) {
  console.error('Failed to enable biometric:', error.message);
}

Authenticate with Biometrics

const bioAuth = new BiometricAuth();

try {
  // Prompt biometric authentication
  const username = await bioAuth.authenticate();
  console.log('Authenticated as:', username);
} catch (error) {
  console.error('Authentication failed:', error.message);
}

Custom Prompts

const bioAuth = new BiometricAuth({
  promptMessages: {
    enable: 'Enable Face ID for MyApp',
    authenticate: 'Sign in to MyApp',
  },
  fallbackLabel: 'Use Password',
});

await bioAuth.enable('[email protected]');
const username = await bioAuth.authenticate();

Manage Saved Username

const bioAuth = new BiometricAuth();

// Save username without prompting
await bioAuth.saveUsername('[email protected]');

// Get saved username (only if biometric is enabled)
const savedUsername = await bioAuth.getSavedUsername();

// Clear saved username
await bioAuth.clearSavedUsername();

// Disable biometric completely
await bioAuth.disable();

Complete Login Flow Example

import { BiometricAuth, TokenManager } from '@egintegrations/auth-services';

const bioAuth = new BiometricAuth();
const tokenManager = new TokenManager();

async function loginWithBiometric() {
  try {
    // Check if biometric is enabled
    const isEnabled = await bioAuth.isEnabled();
    
    if (!isEnabled) {
      console.log('Biometric not enabled, use password login');
      return;
    }

    // Authenticate
    const username = await bioAuth.authenticate();
    
    // Call your API to get token
    const response = await fetch('https://api.example.com/auth/biometric', {
      method: 'POST',
      body: JSON.stringify({ username }),
    });
    
    const { token } = await response.json();
    
    // Save token
    await tokenManager.saveToken(token);
    
    console.log('Logged in as:', username);
  } catch (error) {
    console.error('Biometric login failed:', error.message);
  }
}

SecureKeyStore

Generic secure key-value storage with namespace support.

Basic Usage

import { SecureKeyStore } from '@egintegrations/auth-services';

const store = new SecureKeyStore();

// Store value
await store.set('api_key', 'sk-1234567890');

// Retrieve value
const apiKey = await store.get('api_key');

// Check if key exists
const hasKey = await store.has('api_key');

// Delete key
await store.delete('api_key');

Namespace Isolation

// Create separate stores for different purposes
const apiStore = new SecureKeyStore({ keyPrefix: 'api_' });
const userStore = new SecureKeyStore({ keyPrefix: 'user_' });

await apiStore.set('openai_key', 'sk-...');
await userStore.set('preference', 'dark_mode');

// Keys are isolated
const apiKeys = await apiStore.get('openai_key'); // Works
const userKeys = await userStore.get('openai_key'); // null (different namespace)

Clear Multiple Keys

const store = new SecureKeyStore({ keyPrefix: 'app_' });

await store.set('key1', 'value1');
await store.set('key2', 'value2');
await store.set('key3', 'value3');

// Clear specific keys
await store.clear(['key1', 'key2']);

Convenience Functions

For simple use cases without creating a store instance:

import {
  getSecureKey,
  setSecureKey,
  deleteSecureKey,
  hasSecureKey,
} from '@egintegrations/auth-services';

// Direct access to secure storage (no prefix)
await setSecureKey('my_key', 'my_value');
const value = await getSecureKey('my_key');
const exists = await hasSecureKey('my_key');
await deleteSecureKey('my_key');

Advanced Examples

Complete Authentication System

import {
  TokenManager,
  BiometricAuth,
  SecureKeyStore,
} from '@egintegrations/auth-services';

class AuthService {
  private tokenManager = new TokenManager();
  private bioAuth = new BiometricAuth({
    promptMessages: {
      enable: 'Enable Face ID for faster login',
      authenticate: 'Authenticate to continue',
    },
  });
  private keyStore = new SecureKeyStore({ keyPrefix: 'auth_' });

  async login(username: string, password: string): Promise<void> {
    // Call your API
    const response = await fetch('https://api.example.com/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
    });

    const { token } = await response.json();

    // Save token
    await this.tokenManager.saveToken(token);

    // Offer biometric enrollment if available
    const canAuth = await this.bioAuth.canAuthenticate();
    if (canAuth) {
      await this.bioAuth.enable(username);
    }
  }

  async loginWithBiometric(): Promise<void> {
    const username = await this.bioAuth.authenticate();

    // Exchange biometric authentication for token
    const response = await fetch('https://api.example.com/auth/biometric', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username }),
    });

    const { token } = await response.json();
    await this.tokenManager.saveToken(token);
  }

  async logout(): Promise<void> {
    await this.tokenManager.clearToken();
    // Keep biometric enabled for next login
  }

  async getAuthToken(): Promise<string | null> {
    return this.tokenManager.getToken();
  }

  async isAuthenticated(): Promise<boolean> {
    return this.tokenManager.hasToken();
  }

  async saveApiKey(service: string, key: string): Promise<void> {
    await this.keyStore.set(`${service}_key`, key);
  }

  async getApiKey(service: string): Promise<string | null> {
    return this.keyStore.get(`${service}_key`);
  }
}

// Usage
const auth = new AuthService();

// Normal login
await auth.login('[email protected]', 'password123');

// Biometric login
if (await auth.bioAuth.canAuthenticate()) {
  await auth.loginWithBiometric();
}

// Get auth token for API calls
const token = await auth.getAuthToken();

API Integration with TokenManager

import { TokenManager } from '@egintegrations/auth-services';
import { ApiClient } from '@egintegrations/api-client';

const tokenManager = new TokenManager();

// Create API client
const apiClient = new ApiClient({
  baseUrl: 'https://api.example.com',
});

// Add token to all requests
apiClient.addRequestInterceptor(async (config) => {
  const token = await tokenManager.getToken();
  if (token) {
    config.headers = config.headers || {};
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Handle 401 errors
apiClient.addErrorInterceptor(async (error) => {
  if (error.response?.status === 401) {
    await tokenManager.clearToken();
    // Redirect to login
  }
  throw error;
});

API Reference

TokenManager

Constructor

new TokenManager(config?: TokenManagerConfig)

Config:

  • storageKey?: string - Storage key (default: 'auth_token')

Methods

  • getToken(): Promise<string | null> - Get stored token
  • saveToken(token: string): Promise<void> - Save token
  • clearToken(): Promise<void> - Delete token
  • hasToken(): Promise<boolean> - Check if token exists

SingletonTokenManager

Static methods matching TokenManager interface.

BiometricAuth

Constructor

new BiometricAuth(config?: BiometricAuthConfig)

Config:

  • savedUsernameKey?: string - Username storage key (default: 'biometric_username')
  • enabledKey?: string - Enabled flag key (default: 'biometric_enabled')
  • promptMessages?: { enable?: string, authenticate?: string } - Custom prompts
  • fallbackLabel?: string - Fallback button label (default: 'Use password')

Methods

  • canAuthenticate(): Promise<boolean> - Check device support
  • isEnabled(): Promise<boolean> - Check if biometric enabled
  • enable(username: string): Promise<void> - Enable biometric login
  • disable(): Promise<void> - Disable biometric login
  • getBiometricType(): Promise<BiometricType> - Get biometric type
  • authenticate(): Promise<string> - Authenticate and get username
  • saveUsername(username: string): Promise<void> - Save username
  • clearSavedUsername(): Promise<void> - Clear username
  • getSavedUsername(): Promise<string | null> - Get saved username

SecureKeyStore

Constructor

new SecureKeyStore(config?: SecureKeyStoreConfig)

Config:

  • keyPrefix?: string - Key prefix for namespace isolation (default: 'secure_key_')

Methods

  • get(key: string): Promise<string | null> - Get value
  • set(key: string, value: string): Promise<void> - Set value
  • delete(key: string): Promise<void> - Delete key
  • has(key: string): Promise<boolean> - Check if key exists
  • clear(keys?: string[]): Promise<void> - Clear multiple keys

Error Handling

All methods can throw errors. Always use try-catch:

try {
  await tokenManager.saveToken(token);
} catch (error) {
  console.error('Failed to save token:', error);
}

try {
  const username = await bioAuth.authenticate();
} catch (error) {
  console.error('Biometric auth failed:', error.message);
  // Handle failure (show password login)
}

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Run tests with coverage
npm test -- --coverage

# Type check
npm run typecheck

# Lint
npm run lint

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass (npm test)
  2. Code coverage remains 100%
  3. TypeScript types are properly defined
  4. Code follows the existing style (run npm run lint)

License

MIT © EGI Integrations

Extracted From

This package was extracted from AutismTrainerApp's authentication services and refactored to be reusable across React Native applications.

What was removed:

  • App-specific user management (roles, permissions, progress tracking)
  • Local user database and AsyncStorage user management
  • Supervised user relationships
  • Application-specific authentication flows

What was kept and improved:

  • Token management (now configurable)
  • Biometric authentication (now with custom prompts)
  • Secure key storage (now with namespace support)

Related Packages

Support

For issues and questions, please open an issue on GitHub.