UNPKG

react-native-nitro-totp

Version:

React Native module for TOTP (Time-based One-Time Password) and HOTP (HMAC-based One-Time Password) authentication.

155 lines (135 loc) 4.39 kB
import { NitroModules } from 'react-native-nitro-modules'; import type { NitroHotp as NitroHotpType } from './specs/NitroHotp.nitro'; import type { NitroHotpGenerateOptions, NitroHotpValidateOptions, OTPAuthURLOptions, } from './types'; import { SupportedAlgorithm } from './types'; import { NitroTotpConstants } from './constants'; /** * NitroHotp (HMAC-based One-Time Password) class that provides methods for generating and validating HOTPs. */ export class NitroHotp { private nitroHotp: NitroHotpType; constructor() { this.nitroHotp = NitroModules.createHybridObject<NitroHotpType>('NitroHotp'); } /** * Generates an HOTP code based on the secret key and options. * * @param secret - The secret key to use for generating the HOTP. * @param options - Optional parameters for HOTP generation. * @returns The generated HOTP code as a string. */ generate(secret: string, options: NitroHotpGenerateOptions = {}): string { if (!options.digits) { options.digits = NitroTotpConstants.DEFAULT_DIGITS; } if (!options.algorithm) { options.algorithm = NitroTotpConstants.DEFAULT_ALGORITHM; } if (options.counter === undefined || options.counter === null) { options.counter = NitroTotpConstants.DEFAULT_COUNTER; } return this.nitroHotp.generate(secret, options); } /** * Validates an HOTP code against the secret key and options. * * @param secret - The secret key to validate against. * @param otp - The HOTP code to validate. * @param options - Optional parameters for HOTP validation. * @returns True if the HOTP code is valid, false otherwise. */ validate( secret: string, otp: string, options: NitroHotpValidateOptions = {} ): boolean { if (!options.digits) { options.digits = NitroTotpConstants.DEFAULT_DIGITS; } if (!options.algorithm) { options.algorithm = NitroTotpConstants.DEFAULT_ALGORITHM; } if ( options.window === undefined || options.window === null || options.window < 0 ) { options.window = NitroTotpConstants.DEFAULT_WINDOW; } if ( options.counter === undefined || options.counter === null || options.counter < 0 ) { options.counter = NitroTotpConstants.DEFAULT_COUNTER; } return this.nitroHotp.validate(secret, otp, options); } /** * Generates an OTP Auth URL for HOTP that can be used to set up authenticator apps. * * @param options - The options for generating the auth URL. * @returns The generated OTP Auth URL as a string. */ generateAuthURL(options: OTPAuthURLOptions): string { return this.generateHotpAuthURL(options); } /** * Gets the algorithm name as a string. * * @param algorithm - The algorithm enum value. * @returns The algorithm name. */ private getAlgorithmName(algorithm: SupportedAlgorithm): string { switch (algorithm) { case SupportedAlgorithm.SHA1: return 'SHA1'; case SupportedAlgorithm.SHA256: return 'SHA256'; case SupportedAlgorithm.SHA512: return 'SHA512'; default: throw new Error('Unsupported algorithm'); } } /** * Generates an OTP Auth URL for HOTP. * * @param options - The options for generating the auth URL. * @returns The generated OTP Auth URL as a string. */ private generateHotpAuthURL(options: OTPAuthURLOptions): string { if (!options.secret) { throw new Error('Secret is required.'); } const { secret, label = 'OTP Auth', issuer = '', issuerInLabel = false, algorithm = SupportedAlgorithm.SHA1, digits = NitroTotpConstants.DEFAULT_DIGITS, counter = NitroTotpConstants.DEFAULT_COUNTER, } = options; let url = 'otpauth://hotp/'; if (issuer) { if (issuerInLabel) { url += `${encodeURIComponent(issuer)}:${encodeURIComponent(label)}?issuer=${encodeURIComponent(issuer)}&`; } else { url += `${encodeURIComponent(label)}?issuer=${encodeURIComponent(issuer)}&`; } } else { url += `${encodeURIComponent(label)}?`; } url += `secret=${encodeURIComponent(secret)}&`; url += `algorithm=${encodeURIComponent(this.getAlgorithmName(algorithm))}&`; url += `digits=${digits}&`; url += `counter=${counter}`; return url; } }