@nauth-toolkit/mfa-totp 0.1.13 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,12 +3,92 @@ import { BaseMFADevice, BaseUser, IUser, NAuthConfig, NAuthLogger, MFAMethod } f
3
3
  import { BaseMFAProviderService } from '@nauth-toolkit/core/internal';
4
4
  import { TOTPService } from './totp.service';
5
5
  import { SetupTOTPResponseDTO } from './dto/mfa.dto';
6
+ /**
7
+ * TOTP MFA Provider Service
8
+ *
9
+ * Implements TOTP (Time-based One-Time Password) MFA method.
10
+ * Extends BaseMFAProviderService to provide TOTP-specific functionality.
11
+ *
12
+ * This service handles:
13
+ * - TOTP secret generation and QR code creation
14
+ * - TOTP code verification during setup and authentication
15
+ * - MFA device creation for TOTP
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * @Module({
20
+ * imports: [TOTPMFAModule],
21
+ * })
22
+ * export class AppModule {}
23
+ * ```
24
+ */
6
25
  export declare class TOTPMFAProviderService extends BaseMFAProviderService {
7
26
  private readonly totpService;
8
27
  readonly methodName = MFAMethod.TOTP;
9
- constructor(mfaDeviceRepository: Repository<BaseMFADevice>, userRepository: Repository<BaseUser>, config: NAuthConfig, logger: NAuthLogger, passwordService: unknown, totpService: TOTPService, challengeService?: unknown, auditService?: unknown, clientInfoService?: unknown);
28
+ constructor(mfaDeviceRepository: Repository<BaseMFADevice>, userRepository: Repository<BaseUser>, config: NAuthConfig, logger: NAuthLogger, passwordService: unknown, totpService: TOTPService, challengeService?: unknown, // ChallengeService (optional)
29
+ auditService?: unknown, // AuthAuditService (optional)
30
+ clientInfoService?: unknown);
31
+ /**
32
+ * Setup TOTP for user
33
+ *
34
+ * Generates TOTP secret and QR code for authenticator app setup.
35
+ * User must scan QR code and verify with a code to complete setup.
36
+ *
37
+ * @param user - User setting up TOTP
38
+ * @param _setupData - Not used for TOTP
39
+ * @returns TOTP setup information (secret, QR code, manual entry key)
40
+ * @throws {NAuthException} If TOTP is not enabled
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const setup = await provider.setup(user);
45
+ * // Client displays setup.qrCode and setup.manualEntryKey
46
+ * ```
47
+ */
10
48
  setup(user: IUser, _setupData?: unknown): Promise<SetupTOTPResponseDTO>;
49
+ /**
50
+ * Verify and complete TOTP setup
51
+ *
52
+ * Validates the TOTP code and stores the device if valid.
53
+ * Enables MFA for user if this is their first device.
54
+ *
55
+ * **Race Condition Safety:**
56
+ * Device creation uses transaction with pessimistic locking to prevent duplicates.
57
+ * If device already exists (e.g., from concurrent request), returns existing device.
58
+ * Database unique constraint (userId, type) provides final safety net.
59
+ *
60
+ * @param user - User completing TOTP setup
61
+ * @param verificationData - Verification data (must be VerifyTOTPSetupDTO)
62
+ * @param deviceName - Optional device name override
63
+ * @returns MFA device ID (created or existing)
64
+ * @throws {NAuthException} If code is invalid
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const deviceId = await provider.verifySetup(user, {
69
+ * secret: 'base32secret',
70
+ * code: '123456',
71
+ * deviceName: 'Google Authenticator'
72
+ * });
73
+ * ```
74
+ */
11
75
  verifySetup(user: IUser, verificationData: unknown, deviceName?: string): Promise<number>;
76
+ /**
77
+ * Verify TOTP code during authentication
78
+ *
79
+ * Validates the TOTP code for an existing device.
80
+ *
81
+ * @param user - User being authenticated
82
+ * @param code - TOTP code (string)
83
+ * @param deviceId - Optional device ID to verify against
84
+ * @returns True if verification succeeds
85
+ * @throws {NAuthException} If device not found or verification fails
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const isValid = await provider.verify(user, '123456');
90
+ * ```
91
+ */
12
92
  verify(user: IUser, code: unknown, deviceId?: number): Promise<boolean>;
13
93
  }
14
94
  //# sourceMappingURL=totp-mfa-provider.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"totp-mfa-provider.service.d.ts","sourceRoot":"","sources":["../../src/totp-mfa-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EAGX,SAAS,EACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAsB,MAAM,eAAe,CAAC;AAsBzE,qBAAa,sBAAuB,SAAQ,sBAAsB;IAS9D,OAAO,CAAC,QAAQ,CAAC,WAAW;IAR9B,QAAQ,CAAC,UAAU,kBAAkB;gBAGnC,mBAAmB,EAAE,UAAU,CAAC,aAAa,CAAC,EAC9C,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,EACpC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,OAAO,EACP,WAAW,EAAE,WAAW,EACzC,gBAAgB,CAAC,EAAE,OAAO,EAC1B,YAAY,CAAC,EAAE,OAAO,EACtB,iBAAiB,CAAC,EAAE,OAAO;IA+BvB,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA0CvE,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA0DzF,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAoC9E"}
1
+ {"version":3,"file":"totp-mfa-provider.service.d.ts","sourceRoot":"","sources":["../../src/totp-mfa-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EAGX,SAAS,EACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAsB,MAAM,eAAe,CAAC;AAEzE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,qBAAa,sBAAuB,SAAQ,sBAAsB;IAS9D,OAAO,CAAC,QAAQ,CAAC,WAAW;IAR9B,QAAQ,CAAC,UAAU,kBAAkB;gBAGnC,mBAAmB,EAAE,UAAU,CAAC,aAAa,CAAC,EAC9C,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,EACpC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,OAAO,EACP,WAAW,EAAE,WAAW,EACzC,gBAAgB,CAAC,EAAE,OAAO,EAAE,8BAA8B;IAC1D,YAAY,CAAC,EAAE,OAAO,EAAE,8BAA8B;IACtD,iBAAiB,CAAC,EAAE,OAAO;IAc7B;;;;;;;;;;;;;;;;OAgBG;IACG,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAgB7E;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA0C/F;;;;;;;;;;;;;;;OAeG;IACG,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAoC9E"}
@@ -1,47 +1,141 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TOTPMFAProviderService = void 0;
4
+ // Public API imports
4
5
  const core_1 = require("@nauth-toolkit/core");
6
+ // Internal API imports (for provider implementations)
5
7
  const internal_1 = require("@nauth-toolkit/core/internal");
8
+ /**
9
+ * TOTP MFA Provider Service
10
+ *
11
+ * Implements TOTP (Time-based One-Time Password) MFA method.
12
+ * Extends BaseMFAProviderService to provide TOTP-specific functionality.
13
+ *
14
+ * This service handles:
15
+ * - TOTP secret generation and QR code creation
16
+ * - TOTP code verification during setup and authentication
17
+ * - MFA device creation for TOTP
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * @Module({
22
+ * imports: [TOTPMFAModule],
23
+ * })
24
+ * export class AppModule {}
25
+ * ```
26
+ */
6
27
  class TOTPMFAProviderService extends internal_1.BaseMFAProviderService {
7
28
  totpService;
8
29
  methodName = core_1.MFAMethod.TOTP;
9
- constructor(mfaDeviceRepository, userRepository, config, logger, passwordService, totpService, challengeService, auditService, clientInfoService) {
30
+ constructor(mfaDeviceRepository, userRepository, config, logger, passwordService, totpService, challengeService, // ChallengeService (optional)
31
+ auditService, // AuthAuditService (optional)
32
+ clientInfoService) {
10
33
  super(mfaDeviceRepository, userRepository, config, logger, passwordService, challengeService, auditService, clientInfoService);
11
34
  this.totpService = totpService;
12
35
  }
36
+ /**
37
+ * Setup TOTP for user
38
+ *
39
+ * Generates TOTP secret and QR code for authenticator app setup.
40
+ * User must scan QR code and verify with a code to complete setup.
41
+ *
42
+ * @param user - User setting up TOTP
43
+ * @param _setupData - Not used for TOTP
44
+ * @returns TOTP setup information (secret, QR code, manual entry key)
45
+ * @throws {NAuthException} If TOTP is not enabled
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const setup = await provider.setup(user);
50
+ * // Client displays setup.qrCode and setup.manualEntryKey
51
+ * ```
52
+ */
13
53
  async setup(user, _setupData) {
14
54
  this.logger?.log?.(`Setting up TOTP for user: ${user.sub}`);
55
+ // Check if TOTP is allowed
15
56
  if (!this.isMethodAllowed()) {
16
57
  throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'TOTP is not enabled', { feature: 'totp' });
17
58
  }
59
+ // Generate secret and QR code
18
60
  const setup = await this.totpService.generateSecret(user.email);
19
61
  this.logger?.log?.(`TOTP setup initiated for user: ${user.sub}`);
20
62
  return setup;
21
63
  }
64
+ /**
65
+ * Verify and complete TOTP setup
66
+ *
67
+ * Validates the TOTP code and stores the device if valid.
68
+ * Enables MFA for user if this is their first device.
69
+ *
70
+ * **Race Condition Safety:**
71
+ * Device creation uses transaction with pessimistic locking to prevent duplicates.
72
+ * If device already exists (e.g., from concurrent request), returns existing device.
73
+ * Database unique constraint (userId, type) provides final safety net.
74
+ *
75
+ * @param user - User completing TOTP setup
76
+ * @param verificationData - Verification data (must be VerifyTOTPSetupDTO)
77
+ * @param deviceName - Optional device name override
78
+ * @returns MFA device ID (created or existing)
79
+ * @throws {NAuthException} If code is invalid
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const deviceId = await provider.verifySetup(user, {
84
+ * secret: 'base32secret',
85
+ * code: '123456',
86
+ * deviceName: 'Google Authenticator'
87
+ * });
88
+ * ```
89
+ */
22
90
  async verifySetup(user, verificationData, deviceName) {
23
91
  this.logger?.log?.(`Verifying TOTP setup for user: ${user.sub}`);
24
92
  const dto = verificationData;
93
+ // Validate secret format
25
94
  if (!this.totpService.isValidSecret(dto.secret)) {
26
95
  throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'Invalid TOTP secret', { field: 'secret' });
27
96
  }
97
+ // Verify code
28
98
  const result = this.totpService.verifyCodeWithDetails(dto.secret, dto.code);
29
99
  if (!result.valid) {
30
100
  throw new core_1.NAuthException(core_1.AuthErrorCode.VERIFICATION_CODE_INVALID, result.error || 'Invalid TOTP code');
31
101
  }
102
+ // Get user entity for MFA status check
32
103
  const userEntity = user;
33
104
  const userId = userEntity.id;
34
105
  const userMfaEnabled = userEntity.mfaEnabled || false;
106
+ // ============================================================================
107
+ // Create MFA device (transaction-safe with duplicate prevention)
108
+ // ============================================================================
109
+ // createDevice() uses pessimistic locking to prevent race conditions
110
+ // If device already exists, returns existing device instead of creating duplicate
111
+ // Database unique constraint (userId, type) provides additional safety
35
112
  const device = await this.createDevice(userId, {
36
113
  name: deviceName || dto.deviceName || 'Authenticator App',
37
- secret: dto.secret,
114
+ secret: dto.secret, // TODO: Encrypt at rest in production
38
115
  isActive: true,
39
- isPrimary: !userMfaEnabled,
116
+ isPrimary: !userMfaEnabled, // First device becomes primary
40
117
  });
118
+ // Enable MFA if not already enabled
41
119
  await this.enableMFAForUser(user);
42
120
  this.logger?.log?.(`TOTP setup completed for user: ${user.sub}`);
43
121
  return device.id;
44
122
  }
123
+ /**
124
+ * Verify TOTP code during authentication
125
+ *
126
+ * Validates the TOTP code for an existing device.
127
+ *
128
+ * @param user - User being authenticated
129
+ * @param code - TOTP code (string)
130
+ * @param deviceId - Optional device ID to verify against
131
+ * @returns True if verification succeeds
132
+ * @throws {NAuthException} If device not found or verification fails
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const isValid = await provider.verify(user, '123456');
137
+ * ```
138
+ */
45
139
  async verify(user, code, deviceId) {
46
140
  this.logger?.log?.(`Verifying TOTP code for user: ${user.sub}`);
47
141
  const totpCode = code;
@@ -49,15 +143,19 @@ class TOTPMFAProviderService extends internal_1.BaseMFAProviderService {
49
143
  this.logger?.warn?.('Invalid TOTP code format');
50
144
  return false;
51
145
  }
146
+ // Get user entity
52
147
  const userEntity = user;
53
148
  const userId = userEntity.id;
149
+ // Find device
54
150
  const device = await this.findDevice(userId, deviceId);
55
151
  if (!device || !device.secret) {
56
152
  this.logger?.warn?.(`No active TOTP device found for user: ${user.sub}`);
57
153
  return false;
58
154
  }
155
+ // Verify code
59
156
  const isValid = this.totpService.verifyCode(device.secret, totpCode);
60
157
  if (isValid) {
158
+ // Update device usage
61
159
  await this.updateDeviceUsage(device.id);
62
160
  this.logger?.log?.(`TOTP code verified successfully for user: ${user.sub}`);
63
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"totp-mfa-provider.service.js","sourceRoot":"","sources":["../../src/totp-mfa-provider.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"totp-mfa-provider.service.js","sourceRoot":"","sources":["../../src/totp-mfa-provider.service.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,180 @@
1
1
  import { NAuthConfig, NAuthLogger } from '@nauth-toolkit/core';
2
2
  import { SetupTOTPResponseDTO } from './dto/mfa.dto';
3
+ /**
4
+ * TOTP (Time-based One-Time Password) Service
5
+ *
6
+ * Handles authenticator app functionality including:
7
+ * - Secret generation for new TOTP devices
8
+ * - QR code generation for easy setup
9
+ * - TOTP code validation with time window
10
+ * - Compatible with Google Authenticator, Authy, 1Password, etc.
11
+ *
12
+ * Uses industry-standard TOTP (RFC 6238) with configurable parameters.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Generate TOTP setup
17
+ * const setup = await totpService.generateSecret('user@example.com');
18
+ * // Returns: { secret, qrCode, manualEntryKey, issuer, accountName }
19
+ *
20
+ * // Verify TOTP code
21
+ * const isValid = totpService.verifyCode('base32secret', '123456');
22
+ * // Returns: true if code is valid
23
+ * ```
24
+ */
3
25
  export declare class TOTPService {
4
26
  private readonly config;
5
27
  private readonly logger;
6
28
  private readonly defaultConfig;
7
29
  constructor(config: NAuthConfig, logger: NAuthLogger);
30
+ /**
31
+ * Configure otplib authenticator with config settings
32
+ *
33
+ * Applies TOTP configuration from NAuthConfig or uses defaults.
34
+ * Called during service initialization.
35
+ *
36
+ * @private
37
+ */
8
38
  private configureAuthenticator;
39
+ /**
40
+ * Get TOTP configuration with defaults
41
+ *
42
+ * @returns Complete TOTP configuration
43
+ * @private
44
+ */
9
45
  private getTOTPConfig;
46
+ /**
47
+ * Get issuer name for TOTP URIs
48
+ *
49
+ * @returns Issuer name from config or default
50
+ * @private
51
+ */
10
52
  private getIssuer;
53
+ /**
54
+ * Generate TOTP secret and QR code for user setup
55
+ *
56
+ * Creates a new TOTP secret, generates QR code and manual entry key.
57
+ * User must scan QR code with authenticator app to complete setup.
58
+ *
59
+ * @param accountName - User's email or username (displayed in authenticator app)
60
+ * @returns Setup information including QR code and secret
61
+ * @throws {BadRequestException} If QR code generation fails
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const setup = await totpService.generateSecret('user@example.com');
66
+ * // Client displays QR code and manual entry key
67
+ * // User scans QR with Google Authenticator, Authy, etc.
68
+ * ```
69
+ */
11
70
  generateSecret(accountName: string): Promise<SetupTOTPResponseDTO>;
71
+ /**
72
+ * Format secret for manual entry
73
+ *
74
+ * Converts base32 secret into groups of 4 characters for easy manual input.
75
+ *
76
+ * @param secret - Base32-encoded secret
77
+ * @returns Formatted secret (e.g., 'ABCD EFGH IJKL MNOP')
78
+ * @private
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * formatSecretForManualEntry('ABCDEFGHIJKLMNOP')
83
+ * // Returns: 'ABCD EFGH IJKL MNOP'
84
+ * ```
85
+ */
12
86
  private formatSecretForManualEntry;
87
+ /**
88
+ * Verify TOTP code against secret
89
+ *
90
+ * Validates a 6-digit TOTP code using time-based verification.
91
+ * Checks current time step plus configured window (before/after).
92
+ *
93
+ * SECURITY: Uses time window to account for clock drift and user delay.
94
+ * Default window of 1 checks 3 time steps (current, ±1).
95
+ *
96
+ * @param secret - Base32-encoded TOTP secret
97
+ * @param code - 6-digit TOTP code from authenticator app
98
+ * @returns True if code is valid within time window
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * // User enters code from Google Authenticator
103
+ * const isValid = totpService.verifyCode(user.totpSecret, '123456');
104
+ * if (isValid) {
105
+ * // Grant access
106
+ * }
107
+ * ```
108
+ */
13
109
  verifyCode(secret: string, code: string): boolean;
110
+ /**
111
+ * Verify TOTP code with additional validation
112
+ *
113
+ * Extended verification that checks code format and provides detailed error messages.
114
+ *
115
+ * @param secret - Base32-encoded TOTP secret
116
+ * @param code - TOTP code to verify
117
+ * @returns Verification result with error message if invalid
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const result = totpService.verifyCodeWithDetails(secret, '123456');
122
+ * if (!result.valid) {
123
+ * throw new BadRequestException(result.error);
124
+ * }
125
+ * ```
126
+ */
14
127
  verifyCodeWithDetails(secret: string, code: string): {
15
128
  valid: boolean;
16
129
  error?: string;
17
130
  };
131
+ /**
132
+ * Generate current TOTP code for secret
133
+ *
134
+ * FOR TESTING ONLY - Do not use in production authentication flow.
135
+ * This method generates the current valid code for a secret.
136
+ *
137
+ * @param secret - Base32-encoded TOTP secret
138
+ * @returns Current 6-digit TOTP code
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * // Testing only
143
+ * const code = totpService.generateCode(secret);
144
+ * // Returns: '123456'
145
+ * ```
146
+ */
18
147
  generateCode(secret: string): string;
148
+ /**
149
+ * Validate secret format
150
+ *
151
+ * Checks if a secret is valid base32 and has sufficient length.
152
+ *
153
+ * @param secret - Secret to validate
154
+ * @returns True if secret is valid
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * if (!totpService.isValidSecret(secret)) {
159
+ * throw new BadRequestException('Invalid TOTP secret');
160
+ * }
161
+ * ```
162
+ */
19
163
  isValidSecret(secret: string): boolean;
164
+ /**
165
+ * Get time remaining until next code
166
+ *
167
+ * Returns seconds until the current TOTP code expires.
168
+ * Useful for UI countdowns.
169
+ *
170
+ * @returns Seconds remaining (0-30 for default 30s step)
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * const remaining = totpService.getTimeRemaining();
175
+ * // Returns: 15 (seconds until code changes)
176
+ * ```
177
+ */
20
178
  getTimeRemaining(): number;
21
179
  }
22
180
  //# sourceMappingURL=totp.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"totp.service.d.ts","sourceRoot":"","sources":["../../src/totp.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAc,WAAW,EAAiC,MAAM,qBAAqB,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAyBrD,qBAAa,WAAW;IASpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAK5B;gBAGiB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW;IAkBtC,OAAO,CAAC,sBAAsB;IAqB9B,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,SAAS;IAyBX,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAkDxE,OAAO,CAAC,0BAA0B;IA8BlC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IA8CjD,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IA+CvF,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAmBpC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAgCtC,gBAAgB,IAAI,MAAM;CAM3B"}
1
+ {"version":3,"file":"totp.service.d.ts","sourceRoot":"","sources":["../../src/totp.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAc,WAAW,EAAiC,MAAM,qBAAqB,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,qBAAa,WAAW;IASpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAK5B;gBAGiB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW;IAUtC;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAmCxE;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,0BAA0B;IAQlC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IA6BjD;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IA+BvF;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIpC;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAkBtC;;;;;;;;;;;;;OAaG;IACH,gBAAgB,IAAI,MAAM;CAM3B"}