Native Touch ID Authentication for TypeScript - A TypeScript library that provides native Touch ID authentication for macOS applications with strict coding standards and comprehensive type safety.
This library is inspired by and builds upon the excellent work of node-mac-auth by @codebytere (Shelley Vohr). The authentication flow and LocalAuthentication framework usage patterns are based on the node-mac-auth implementation, which provides a clean and reliable approach to Touch ID integration on macOS.
- ✅ Persistent caching across process restarts
- ✅ Device identifiers (hardware UUID, serial, model)
- ✅ TypeScript support with full type safety
- ✅ Modern ES modules and async/await patterns
- ✅ Enhanced error handling and detailed error messages
- ✅ Event System for real-time monitoring and debugging
This library provides native Touch ID authentication for TypeScript applications on macOS. Built with strict TypeScript coding standards, it offers a clean, type-safe API for biometric authentication with comprehensive event monitoring.
import { touchID } from '@neabyte/touchid'
// Check if Touch ID is available
const available = await touchID.isAvailable()
console.log(`Touch ID available: ${available ? '✅' : '❌'}`)
// Direct authentication (always prompts)
const result = await touchID.authenticate({
  reason: 'Authenticate to access secure data',
  method: 'direct'
})
// Cached authentication (reuses recent auth)
const cachedResult = await touchID.authenticate({
  reason: 'Cached authentication',
  method: 'cached',
  ttl: 30000 // 30 seconds cache
})
if (result.success) {
  console.log('✅ Authentication successful!')
  console.log('Device:', result.data?.deviceModel)
  console.log('UUID:', result.data?.hardwareUUID)
} else {
  console.log(`❌ Authentication failed: ${result.error}`)
}// Real-time monitoring of authentication events
touchID.events.on('authentication:success', (event) => {
  console.log(`✅ Auth successful in ${event.duration}ms`)
  console.log(`Device: ${event.data?.deviceModel}`)
})
// Monitor device status
touchID.events.on('device:lockout', (event) => {
  console.log(`🔒 Device locked for ${event.duration}ms`)
})
// Track cache usage
touchID.events.on('cache:created', (event) => {
  console.log(`💾 Cache created with ${event.ttl}ms TTL`)
})
// One-time initialization listener
touchID.events.once('initialization:complete', (event) => {
  console.log(`✅ Service ready in ${event.duration}ms`)
})- Native C++ addon for maximum performance
- Direct macOS API access via LocalAuthentication framework
- Minimal overhead - no Electron or heavy dependencies
- Type-safe TypeScript interface
- Biometric authentication using Touch ID
- Secure error handling with detailed error messages
- Graceful fallbacks when Touch ID is unavailable
- Promise-based API for async operations
# Install from npm
npm install @neabyte/touchid
# Or clone the repository
git clone https://github.com/NeaByteLab/TouchID.git
cd TouchID
# Install dependencies
npm install
# Build native addon
npm run build:native
# Run examples
npm run example:direct
npm run example:cached
npm run example:eventsimport { TouchIDService, createTouchIDService } from '@neabyte/touchid'
// Use default instance
const touchID = createTouchIDService()
// Or create custom instance
const customTouchID = new TouchIDService()
// Check availability
const available = await touchID.isAvailable()
if (available) {
  // Authenticate with device data
  const result = await touchID.authenticate({
    reason: 'Access secure application',
    method: 'direct'
  })
  
  if (result.success) {
    console.log('Access granted!')
    console.log('Device info:', result.data)
  }
}TouchID/
├── src/                     # Source code
│   ├── native/              # Native C++ addon
│   │   └── touchid.mm       # Touch ID implementation
│   ├── types/               # TypeScript type definitions
│   │   ├── touchid.ts       # Touch ID types
│   │   └── index.ts         # Common types
│   ├── utils/               # Utility functions
│   │   ├── event-emitter.ts # Event system implementation
│   │   └── index.ts         # Common utilities
│   ├── touchid.ts           # Touch ID service
│   └── index.ts             # Main entry point
├── examples/                # Usage examples
│   ├── example-direct.ts    # Direct authentication example
│   ├── example-cached.ts    # Cached authentication example
│   └── example-events.ts    # Event system example
├── build/                   # Native addon build output
├── dist/                    # TypeScript build output
└── docs/                    # Auto-generated documentation
Check if Touch ID is available on the device.
const available = await touchID.isAvailable()Authenticate using Touch ID.
const result = await touchID.authenticate({
  reason: 'Authenticate to access secure data',
  method: 'direct',
  ttl: 30000
})Run a test of Touch ID functionality.
await touchID.test()Access the event emitter for monitoring and debugging.
// Listen for authentication events
touchID.events.on('authentication:success', (event) => {
  console.log(`Success in ${event.duration}ms`)
})
// Remove event listener
touchID.events.off('authentication:success', handler)
// One-time listener
touchID.events.once('initialization:complete', (event) => {
  console.log('Service ready!')
})- authentication:start- Authentication process started
- authentication:success- Authentication completed successfully
- authentication:failure- Authentication failed
- authentication:cancel- User cancelled authentication
- device:available- Touch ID device is available
- device:unavailable- Touch ID device is unavailable
- device:lockout- Device is locked out
- cache:created- New cache entry created
- cache:expired- Cache entry expired
- cache:used- Existing cache used
- initialization:start- Service initialization started
- initialization:complete- Service initialization completed
- initialization:error- Service initialization failed
interface TouchIDOptions {
  readonly reason?: string
  readonly method?: 'direct' | 'cached'
  readonly ttl?: number // Time to live in milliseconds
}interface TouchIDResult {
  readonly success: boolean
  readonly error?: string
  readonly data?: DeviceData
}
interface DeviceData {
  readonly biometryType: 'TouchID' | 'FaceID' | 'None' | 'Unsupported'
  readonly hardwareUUID: string
  readonly deviceSerial: string
  readonly deviceModel: string
}interface TouchIDEventEmitter {
  on<T extends TouchIDEventType>(event: T, handler: TouchIDEventHandler<T>): void
  off<T extends TouchIDEventType>(event: T, handler: TouchIDEventHandler<T>): void
  once<T extends TouchIDEventType>(event: T, handler: TouchIDEventHandler<T>): void
  removeAllListeners(event?: TouchIDEventType): void
}# Run direct authentication example
npm run example:direct
# Run cached authentication example
npm run example:cached
# Run event system example
npm run example:events# Build native addon
npm run build:native
# Build TypeScript
npm run build
# Development mode
npm run dev
# Quality checks
npm run check-all- Edit C++ code in src/native/touchid.mm
- Build native addon with npm run build:native
- Edit TypeScript in src/touchid.ts
- Test functionality with npm run example:direct,npm run example:cached, ornpm run example:events
- Node.js 22+
- macOS 10.15+ (Catalina or later)
- Touch ID enabled device (MacBook Pro with Touch Bar, etc.)
- Xcode Command Line Tools
- C++ compiler
- TypeScript 5.9+
- Touch ID data never leaves the device
- No biometric data is stored or transmitted
- Uses Apple's secure LocalAuthentication framework
- Follows macOS security best practices
- Fork the repository
- Create a feature branch
- Make your changes
- Run npm run check-all
- Submit a pull request
MIT License - see LICENSE file for details.