CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ionic-native

Native plugin wrappers for Cordova and Ionic with TypeScript, ES6+, Promise and Observable support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

security-auth.mddocs/

Security & Authentication

Biometric authentication, secure storage, device security features, and advanced authentication methods for protecting user data and ensuring app security.

Capabilities

Touch ID Authentication

iOS Touch ID fingerprint authentication for secure app access and user verification.

/**
 * TouchID class for iOS fingerprint authentication
 */
class TouchID {
  /**
   * Check if Touch ID is available on device
   * @returns Promise resolving to availability status string
   */
  static isAvailable(): Promise<string>;

  /**
   * Verify fingerprint with default message
   * @param message Message to display in authentication dialog
   * @returns Promise indicating authentication success
   */
  static verifyFingerprint(message: string): Promise<any>;

  /**
   * Verify fingerprint with custom password fallback
   * @param message Message to display in authentication dialog
   * @returns Promise indicating authentication success
   */
  static verifyFingerprintWithCustomPasswordFallback(message: string): Promise<any>;

  /**
   * Verify fingerprint with custom labels and password fallback
   * @param message Message to display in authentication dialog
   * @param enterPasswordLabel Label for password entry button
   * @returns Promise indicating authentication success
   */
  static verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel(message: string, enterPasswordLabel: string): Promise<any>;
}

Usage Examples:

import { TouchID } from 'ionic-native';

// Touch ID authentication service
class TouchIDService {
  
  async checkAvailability(): Promise<boolean> {
    try {
      const result = await TouchID.isAvailable();
      console.log('Touch ID availability:', result);
      return true;
    } catch (error) {
      console.log('Touch ID not available:', error);
      return false;
    }
  }
  
  async authenticate(reason: string = 'Authenticate to access the app'): Promise<boolean> {
    try {
      const isAvailable = await this.checkAvailability();
      if (!isAvailable) {
        throw new Error('Touch ID not available');
      }
      
      await TouchID.verifyFingerprint(reason);
      console.log('Touch ID authentication successful');
      return true;
    } catch (error) {
      console.error('Touch ID authentication failed:', error);
      return false;
    }
  }
  
  async authenticateWithFallback(reason: string = 'Authenticate to continue'): Promise<boolean> {
    try {
      await TouchID.verifyFingerprintWithCustomPasswordFallback(reason);
      console.log('Authentication successful (Touch ID or passcode)');
      return true;
    } catch (error) {
      console.error('Authentication failed:', error);
      return false;
    }
  }
  
  async authenticateWithCustomLabels(
    reason: string = 'Verify your identity',
    passwordLabel: string = 'Enter Passcode'
  ): Promise<boolean> {
    try {
      await TouchID.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel(reason, passwordLabel);
      console.log('Authentication successful with custom labels');
      return true;
    } catch (error) {
      console.error('Authentication with custom labels failed:', error);
      return false;
    }
  }
}

// Usage in app
const touchID = new TouchIDService();

// Check and authenticate
async function secureLaunch() {
  const available = await touchID.checkAvailability();
  
  if (available) {
    const authenticated = await touchID.authenticate('Please verify your identity to access your account');
    
    if (authenticated) {
      // Proceed to main app
      navigateToMainApp();
    } else {
      // Handle authentication failure
      showAuthenticationError();
    }
  } else {
    // Fallback to other authentication methods
    showPasswordLogin();
  }
}

Fingerprint AIO (All-in-One)

Cross-platform fingerprint authentication supporting both iOS and Android devices.

/**
 * Fingerprint authentication options
 */
interface FingerprintOptions {
  /** Client ID for keychain access */
  clientId: string;
  /** Client secret for additional security */
  clientSecret: string;
  /** Disable backup authentication methods */
  disableBackup?: boolean;
  /** Localized fallback title */
  localizedFallbackTitle?: string;
  /** Localized cancel title */
  localizedCancelTitle?: string;
}

/**
 * FingerprintAIO class for cross-platform fingerprint authentication
 */
class FingerprintAIO {
  /**
   * Check if fingerprint authentication is available
   * @returns Promise resolving to availability information
   */
  static isAvailable(): Promise<any>;

  /**
   * Show fingerprint authentication dialog
   * @param options Authentication configuration options
   * @returns Promise indicating authentication result
   */
  static show(options: FingerprintOptions): Promise<any>;
}

Usage Examples:

import { FingerprintAIO, FingerprintOptions } from 'ionic-native';

// Cross-platform fingerprint authentication
class BiometricAuthService {
  
  async checkBiometricSupport(): Promise<{
    available: boolean;
    type?: string;
    hasEnrolledFingerprints?: boolean;
  }> {
    try {
      const result = await FingerprintAIO.isAvailable();
      
      return {
        available: true,
        type: result.type, // 'finger' or 'face'
        hasEnrolledFingerprints: result.hasEnrolledFingerprints
      };
    } catch (error) {
      console.log('Biometric authentication not available:', error);
      return { available: false };
    }
  }
  
  async authenticate(options: {
    title?: string;
    subtitle?: string;
    description?: string;
    fallbackEnabled?: boolean;
  } = {}): Promise<boolean> {
    try {
      const support = await this.checkBiometricSupport();
      if (!support.available) {
        throw new Error('Biometric authentication not available');
      }
      
      if (!support.hasEnrolledFingerprints) {
        throw new Error('No biometrics enrolled on device');
      }
      
      const fingerprintOptions: FingerprintOptions = {
        clientId: 'myAppBiometric',
        clientSecret: 'password123', // Use secure secret in production
        disableBackup: !options.fallbackEnabled,
        localizedFallbackTitle: 'Use Password',
        localizedCancelTitle: 'Cancel'
      };
      
      await FingerprintAIO.show(fingerprintOptions);
      console.log('Biometric authentication successful');
      return true;
      
    } catch (error) {
      console.error('Biometric authentication failed:', error);
      
      // Handle specific error cases
      if (error.message === 'BiometricLockedOut') {
        throw new Error('Too many failed attempts. Please try again later.');
      } else if (error.message === 'BiometricNotEnrolled') {
        throw new Error('No biometrics enrolled. Please set up biometric authentication in device settings.');
      } else if (error.message === 'UserCancel') {
        throw new Error('Authentication cancelled by user');
      }
      
      return false;
    }
  }
  
  async authenticateForPayment(amount: number, currency: string = 'USD'): Promise<boolean> {
    return await this.authenticate({
      title: 'Authenticate Payment',
      subtitle: `Confirm payment of ${amount} ${currency}`,
      description: 'Place your finger on the sensor to authorize this transaction',
      fallbackEnabled: true
    });
  }
  
  async authenticateForSensitiveData(): Promise<boolean> {
    return await this.authenticate({
      title: 'Access Sensitive Data',
      subtitle: 'Biometric verification required',
      description: 'Verify your identity to view sensitive information',
      fallbackEnabled: false
    });
  }
}

// Enhanced biometric service with security features
class SecureBiometricService extends BiometricAuthService {
  private maxAttempts = 3;
  private attemptCount = 0;
  private lockoutTime = 30000; // 30 seconds
  private isLockedOut = false;
  
  async secureAuthenticate(purpose: string): Promise<boolean> {
    if (this.isLockedOut) {
      throw new Error('Authentication temporarily locked due to too many failed attempts');
    }
    
    try {
      const result = await this.authenticate({
        title: 'Secure Authentication',
        subtitle: purpose,
        description: 'Verify your identity to continue',
        fallbackEnabled: true
      });
      
      // Reset attempt counter on success
      this.attemptCount = 0;
      return result;
      
    } catch (error) {
      this.attemptCount++;
      
      if (this.attemptCount >= this.maxAttempts) {
        this.lockoutUser();
      }
      
      throw error;
    }
  }
  
  private lockoutUser() {
    this.isLockedOut = true;
    console.warn('User locked out due to too many failed authentication attempts');
    
    // Auto-unlock after timeout
    setTimeout(() => {
      this.isLockedOut = false;
      this.attemptCount = 0;
      console.log('Authentication lockout expired');
    }, this.lockoutTime);
  }
  
  getRemainingAttempts(): number {
    return Math.max(0, this.maxAttempts - this.attemptCount);
  }
  
  isCurrentlyLockedOut(): boolean {
    return this.isLockedOut;
  }
}

Secure Storage Implementation

Advanced secure storage implementation with encryption and key management.

/**
 * Advanced secure storage service with encryption
 */
class AdvancedSecureStorage {
  private storage: any;
  private encryptionKey: string;
  
  async initialize(storeName: string = 'secure_app_store'): Promise<void> {
    try {
      const secureStorage = new SecureStorage();
      this.storage = await secureStorage.create(storeName);
      
      // Generate or retrieve encryption key
      this.encryptionKey = await this.getOrCreateEncryptionKey();
      
      console.log('Secure storage initialized');
    } catch (error) {
      console.error('Secure storage initialization failed:', error);
      throw error;
    }
  }
  
  async storeSecureData(key: string, data: any, requireBiometric: boolean = false): Promise<void> {
    try {
      if (requireBiometric) {
        const biometricService = new BiometricAuthService();
        const authenticated = await biometricService.authenticate({
          title: 'Secure Data Storage',
          subtitle: 'Authenticate to store sensitive data',
          fallbackEnabled: true
        });
        
        if (!authenticated) {
          throw new Error('Biometric authentication required for secure storage');
        }
      }
      
      // Encrypt data before storage
      const encryptedData = this.encrypt(JSON.stringify(data));
      await this.storage.set(key, encryptedData);
      
      console.log(`Secure data stored with key: ${key}`);
    } catch (error) {
      console.error('Secure data storage failed:', error);
      throw error;
    }
  }
  
  async retrieveSecureData(key: string, requireBiometric: boolean = false): Promise<any> {
    try {
      if (requireBiometric) {
        const biometricService = new BiometricAuthService();
        const authenticated = await biometricService.authenticate({
          title: 'Access Secure Data',
          subtitle: 'Authenticate to access sensitive data',
          fallbackEnabled: true
        });
        
        if (!authenticated) {
          throw new Error('Biometric authentication required for secure access');
        }
      }
      
      const encryptedData = await this.storage.get(key);
      
      if (!encryptedData) {
        return null;
      }
      
      // Decrypt data after retrieval
      const decryptedData = this.decrypt(encryptedData);
      return JSON.parse(decryptedData);
      
    } catch (error) {
      console.error('Secure data retrieval failed:', error);
      throw error;
    }
  }
  
  async removeSecureData(key: string, requireBiometric: boolean = false): Promise<void> {
    try {
      if (requireBiometric) {
        const biometricService = new BiometricAuthService();
        const authenticated = await biometricService.authenticate({
          title: 'Remove Secure Data',
          subtitle: 'Authenticate to remove sensitive data',
          fallbackEnabled: true
        });
        
        if (!authenticated) {
          throw new Error('Biometric authentication required for secure removal');
        }
      }
      
      await this.storage.remove(key);
      console.log(`Secure data removed for key: ${key}`);
    } catch (error) {
      console.error('Secure data removal failed:', error);
      throw error;
    }
  }
  
  async listSecureKeys(): Promise<string[]> {
    try {
      return await this.storage.keys();
    } catch (error) {
      console.error('Failed to list secure keys:', error);
      return [];
    }
  }
  
  async clearAllSecureData(requireBiometric: boolean = true): Promise<void> {
    try {
      if (requireBiometric) {
        const biometricService = new BiometricAuthService();
        const authenticated = await biometricService.authenticate({
          title: 'Clear All Data',
          subtitle: 'Authenticate to clear all secure data',
          description: 'This action cannot be undone',
          fallbackEnabled: true
        });
        
        if (!authenticated) {
          throw new Error('Biometric authentication required to clear all data');
        }
      }
      
      await this.storage.clear();
      console.log('All secure data cleared');
    } catch (error) {
      console.error('Failed to clear secure data:', error);
      throw error;
    }
  }
  
  private async getOrCreateEncryptionKey(): Promise<string> {
    try {
      let key = await this.storage.get('_encryption_key');
      
      if (!key) {
        key = this.generateEncryptionKey();
        await this.storage.set('_encryption_key', key);
      }
      
      return key;
    } catch (error) {
      console.error('Encryption key management failed:', error);
      throw error;
    }
  }
  
  private generateEncryptionKey(): string {
    // Simple key generation (use proper crypto library in production)
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let key = '';
    for (let i = 0; i < 32; i++) {
      key += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return key;
  }
  
  private encrypt(data: string): string {
    // Simple XOR encryption (use proper encryption in production)
    let encrypted = '';
    for (let i = 0; i < data.length; i++) {
      const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length);
      const dataChar = data.charCodeAt(i);
      encrypted += String.fromCharCode(dataChar ^ keyChar);
    }
    return btoa(encrypted); // Base64 encode
  }
  
  private decrypt(encryptedData: string): string {
    const data = atob(encryptedData); // Base64 decode
    let decrypted = '';
    for (let i = 0; i < data.length; i++) {
      const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length);
      const dataChar = data.charCodeAt(i);
      decrypted += String.fromCharCode(dataChar ^ keyChar);
    }
    return decrypted;
  }
}

Authentication Manager

Comprehensive authentication system combining multiple security layers.

// Multi-factor authentication manager
class AuthenticationManager {
  private biometricService: SecureBiometricService;
  private secureStorage: AdvancedSecureStorage;
  private sessionTimeout = 300000; // 5 minutes
  private sessionTimer: any;
  
  constructor() {
    this.biometricService = new SecureBiometricService();
    this.secureStorage = new AdvancedSecureStorage();
  }
  
  async initialize(): Promise<void> {
    await this.secureStorage.initialize('auth_manager_store');
    this.startSessionManager();
  }
  
  async authenticateUser(options: {
    requireBiometric?: boolean;
    purpose?: string;
    sessionDuration?: number;
  } = {}): Promise<{
    success: boolean;
    sessionToken?: string;
    expiresAt?: Date;
  }> {
    try {
      let authenticated = false;
      
      if (options.requireBiometric) {
        const support = await this.biometricService.checkBiometricSupport();
        
        if (support.available && support.hasEnrolledFingerprints) {
          authenticated = await this.biometricService.secureAuthenticate(
            options.purpose || 'Authenticate to access the application'
          );
        } else {
          throw new Error('Biometric authentication required but not available');
        }
      } else {
        // Try biometric first, fallback to other methods
        try {
          authenticated = await this.biometricService.secureAuthenticate(
            options.purpose || 'Verify your identity'
          );
        } catch (error) {
          // Fallback to PIN/Password
          authenticated = await this.showPasswordPrompt();
        }
      }
      
      if (authenticated) {
        const sessionToken = this.generateSessionToken();
        const expiresAt = new Date(Date.now() + (options.sessionDuration || this.sessionTimeout));
        
        // Store session info securely
        await this.secureStorage.storeSecureData('active_session', {
          token: sessionToken,
          expiresAt: expiresAt.toISOString(),
          createdAt: new Date().toISOString()
        });
        
        this.resetSessionTimer();
        
        return {
          success: true,
          sessionToken,
          expiresAt
        };
      }
      
      return { success: false };
      
    } catch (error) {
      console.error('Authentication failed:', error);
      return { success: false };
    }
  }
  
  async validateSession(): Promise<boolean> {
    try {
      const sessionData = await this.secureStorage.retrieveSecureData('active_session');
      
      if (!sessionData) {
        return false;
      }
      
      const expiresAt = new Date(sessionData.expiresAt);
      const now = new Date();
      
      if (now > expiresAt) {
        await this.endSession();
        return false;
      }
      
      return true;
    } catch (error) {
      console.error('Session validation failed:', error);
      return false;
    }
  }
  
  async endSession(): Promise<void> {
    try {
      await this.secureStorage.removeSecureData('active_session');
      this.clearSessionTimer();
      console.log('Session ended');
    } catch (error) {
      console.error('Failed to end session:', error);
    }
  }
  
  async extendSession(additionalTime: number = 300000): Promise<void> {
    try {
      const sessionData = await this.secureStorage.retrieveSecureData('active_session');
      
      if (sessionData) {
        const newExpiresAt = new Date(Date.now() + additionalTime);
        sessionData.expiresAt = newExpiresAt.toISOString();
        
        await this.secureStorage.storeSecureData('active_session', sessionData);
        this.resetSessionTimer();
        
        console.log('Session extended until:', newExpiresAt);
      }
    } catch (error) {
      console.error('Failed to extend session:', error);
    }
  }
  
  async requireSecureAccess(action: string): Promise<boolean> {
    // Check if user has current valid session
    const hasValidSession = await this.validateSession();
    
    if (!hasValidSession) {
      // Require fresh authentication
      const authResult = await this.authenticateUser({
        requireBiometric: true,
        purpose: `Authenticate to ${action}`
      });
      
      return authResult.success;
    }
    
    // For sensitive operations, require fresh biometric even with valid session
    if (this.isSensitiveAction(action)) {
      return await this.biometricService.secureAuthenticate(`Confirm ${action}`);
    }
    
    return true;
  }
  
  private isSensitiveAction(action: string): boolean {
    const sensitiveActions = [
      'delete account',
      'change password',
      'export data',
      'financial transaction',
      'modify security settings'
    ];
    
    return sensitiveActions.some(sensitive => 
      action.toLowerCase().includes(sensitive)
    );
  }
  
  private generateSessionToken(): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let token = '';
    for (let i = 0; i < 64; i++) {
      token += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return token;
  }
  
  private async showPasswordPrompt(): Promise<boolean> {
    // Implement custom password/PIN prompt
    // This would show a secure input dialog
    return new Promise((resolve) => {
      // Placeholder implementation
      const password = prompt('Enter your password:');
      resolve(password === 'correct_password'); // Replace with real validation
    });
  }
  
  private startSessionManager(): void {
    // Check session validity periodically
    setInterval(async () => {
      const isValid = await this.validateSession();
      if (!isValid) {
        this.onSessionExpired();
      }
    }, 60000); // Check every minute
  }
  
  private resetSessionTimer(): void {
    this.clearSessionTimer();
    this.sessionTimer = setTimeout(() => {
      this.endSession();
      this.onSessionExpired();
    }, this.sessionTimeout);
  }
  
  private clearSessionTimer(): void {
    if (this.sessionTimer) {
      clearTimeout(this.sessionTimer);
      this.sessionTimer = null;
    }
  }
  
  private onSessionExpired(): void {
    console.log('Session expired - user needs to re-authenticate');
    // Implement UI to handle session expiry
    // e.g., redirect to login screen, show re-auth dialog
  }
}

// Usage example
const authManager = new AuthenticationManager();

async function secureAppFlow() {
  await authManager.initialize();
  
  // Authenticate user on app start
  const authResult = await authManager.authenticateUser({
    requireBiometric: false,
    purpose: 'Access your account'
  });
  
  if (authResult.success) {
    console.log('User authenticated successfully');
    
    // Later, for sensitive operations
    const canDelete = await authManager.requireSecureAccess('delete account');
    if (canDelete) {
      // Proceed with sensitive operation
      console.log('User authorized for sensitive operation');
    }
  }
}

docs

analytics-monetization.md

camera-media.md

device-sensors.md

device-system.md

index.md

input-hardware.md

location-maps.md

network-communication.md

notifications-ui.md

security-auth.md

social-sharing.md

storage-files.md

tile.json