otplib 13.2.1 → 13.4.0
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.
- package/README.md +82 -25
- package/dist/class.cjs +1 -1
- package/dist/class.cjs.map +1 -1
- package/dist/class.d.cts +17 -2
- package/dist/class.d.ts +17 -2
- package/dist/class.js +1 -1
- package/dist/class.js.map +1 -1
- package/dist/functional.cjs +1 -1
- package/dist/functional.cjs.map +1 -1
- package/dist/functional.d.cts +1 -1
- package/dist/functional.d.ts +1 -1
- package/dist/functional.js +1 -1
- package/dist/functional.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.global.js +10 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/metafile-iife.json +1 -0
- package/dist/{types-Bap9LCID.d.cts → types-BBT_82HF.d.cts} +15 -2
- package/dist/{types-Bap9LCID.d.ts → types-BBT_82HF.d.ts} +15 -2
- package/package.json +32 -10
package/README.md
CHANGED
|
@@ -2,32 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript-first library for HOTP and TOTP / Authenticator with multi-runtime (Node, Bun, Deno, Browser) support via plugins.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> [!TIP]
|
|
6
|
+
>
|
|
7
|
+
> A web based demo is available at [https://otplib.yeojz.dev](https://otplib.yeojz.dev).
|
|
8
|
+
>
|
|
9
|
+
> You can scan the TOTP / HOTP QR Code samples with your chosen authenticator app to test.
|
|
6
10
|
|
|
7
11
|
## Features
|
|
8
12
|
|
|
9
13
|
- **Zero Configuration** - Works out of the box with sensible defaults
|
|
10
|
-
- **RFC Compliant** - RFC 6238 (TOTP) and RFC 4226 (HOTP)
|
|
14
|
+
- **RFC Compliant** - RFC 6238 (TOTP) and RFC 4226 (HOTP) + Google Authenticator Compatible
|
|
11
15
|
- **TypeScript-First** - Full type definitions
|
|
12
|
-
- **Google Authenticator Compatible** - Full otpauth:// URI support
|
|
13
16
|
- **Plugin Interface** - Flexible plugin system for customising your cryptographic and base32 requirements (if you want to deviate from the defaults)
|
|
14
17
|
- **Cross-platform** - Tested against Node.js, Bun, Deno, and browsers
|
|
18
|
+
- **Security-audited plugins** — Default crypto uses `@noble/hashes` and `@scure/base`, both independently audited
|
|
19
|
+
- **Async-first API** — All operations are async by default; sync variants available for compatible plugins
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
>
|
|
19
|
-
> v13 is a complete rewrite with breaking changes:
|
|
21
|
+
> [!IMPORTANT]
|
|
22
|
+
>
|
|
23
|
+
> v13 is a complete rewrite with breaking changes. For example:
|
|
20
24
|
>
|
|
21
|
-
> - **
|
|
22
|
-
>
|
|
23
|
-
> - **Cross-platform defaults** — Works out-of-the-box in Node.js, Bun, Deno, and browsers
|
|
24
|
-
> - **Full type safety** — Comprehensive TypeScript types with strict mode from the ground up
|
|
25
|
-
> - **Async-first API** — All operations are async by default; sync variants available for compatible plugins
|
|
26
|
-
> - **Removed**
|
|
27
|
-
> - **Separate authenticator package** — TOTP now covers all authenticator functionality
|
|
28
|
-
> - **Outdated plugins** — Legacy crypto adapters removed in favor of modern, audited alternatives
|
|
25
|
+
> - **(Removed) Separate authenticator package** — TOTP now covers all authenticator functionality with default plugins
|
|
26
|
+
> - **(Removed) Outdated plugins** — Legacy crypto adapters removed in favor of modern, audited alternatives
|
|
29
27
|
>
|
|
30
|
-
> See [Migration Guide](https://otplib.yeojz.dev/guide/v12-adapter) for details.
|
|
28
|
+
> See [Migration Guide](https://otplib.yeojz.dev/guide/v12-adapter.html) for details.
|
|
31
29
|
|
|
32
30
|
## Installation
|
|
33
31
|
|
|
@@ -44,6 +42,27 @@ bun add otplib
|
|
|
44
42
|
deno install npm:otplib
|
|
45
43
|
```
|
|
46
44
|
|
|
45
|
+
### CDN / Script Tag
|
|
46
|
+
|
|
47
|
+
A self-contained IIFE build is available for use directly in browsers via a `<script>` tag:
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<!-- unpkg -->
|
|
51
|
+
<script src="https://unpkg.com/otplib/dist/index.global.js"></script>
|
|
52
|
+
|
|
53
|
+
<!-- or jsdelivr -->
|
|
54
|
+
<script src="https://cdn.jsdelivr.net/npm/otplib/dist/index.global.js"></script>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
const { generateSecret, generate, verify } = otplib;
|
|
58
|
+
|
|
59
|
+
const secret = generateSecret();
|
|
60
|
+
generate({ secret }).then((token) => console.log("Token:", token));
|
|
61
|
+
</script>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The IIFE build bundles all dependencies (including crypto and base32 plugins) into a single file and exposes everything under the `otplib` global.
|
|
65
|
+
|
|
47
66
|
## Quick Start
|
|
48
67
|
|
|
49
68
|
### Functional API (Recommended)
|
|
@@ -57,8 +76,9 @@ const secret = generateSecret();
|
|
|
57
76
|
// Generate a TOTP token
|
|
58
77
|
const token = await generate({ secret });
|
|
59
78
|
|
|
60
|
-
// Verify a token
|
|
61
|
-
const
|
|
79
|
+
// Verify a token — returns VerifyResult, not a boolean
|
|
80
|
+
const result = await verify({ secret, token });
|
|
81
|
+
console.log(result.valid); // true or false
|
|
62
82
|
|
|
63
83
|
// Generate QR code URI for authenticator apps
|
|
64
84
|
const uri = generateURI({
|
|
@@ -68,12 +88,14 @@ const uri = generateURI({
|
|
|
68
88
|
});
|
|
69
89
|
```
|
|
70
90
|
|
|
91
|
+
Sync variants (`generateSync`, `verifySync`) are available when using a sync-compatible crypto plugin such as `@otplib/plugin-crypto-node` or `@otplib/plugin-crypto-noble`.
|
|
92
|
+
|
|
71
93
|
### Class API
|
|
72
94
|
|
|
73
95
|
```typescript
|
|
74
96
|
import { OTP } from "otplib";
|
|
75
97
|
|
|
76
|
-
// Create OTP instance (defaults to TOTP)
|
|
98
|
+
// Create OTP instance (defaults to TOTP strategy)
|
|
77
99
|
const otp = new OTP();
|
|
78
100
|
|
|
79
101
|
// Generate a secret
|
|
@@ -82,8 +104,9 @@ const secret = otp.generateSecret();
|
|
|
82
104
|
// Generate a TOTP token
|
|
83
105
|
const token = await otp.generate({ secret });
|
|
84
106
|
|
|
85
|
-
// Verify a token
|
|
86
|
-
const
|
|
107
|
+
// Verify a token — returns VerifyResult, not a boolean
|
|
108
|
+
const result = await otp.verify({ secret, token });
|
|
109
|
+
console.log(result.valid); // true or false
|
|
87
110
|
|
|
88
111
|
// Generate QR code URI for authenticator apps
|
|
89
112
|
const uri = otp.generateURI({
|
|
@@ -93,11 +116,30 @@ const uri = otp.generateURI({
|
|
|
93
116
|
});
|
|
94
117
|
```
|
|
95
118
|
|
|
96
|
-
|
|
119
|
+
The class also exposes `generateSync` and `verifySync` for use with sync-compatible crypto plugins.
|
|
120
|
+
|
|
121
|
+
#### HOTP (counter-based) with the Class API
|
|
122
|
+
|
|
123
|
+
Pass `strategy: 'hotp'` to switch to counter-based OTP. A `counter` value is required for generation and verification.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { OTP } from "otplib";
|
|
127
|
+
|
|
128
|
+
const otp = new OTP({ strategy: "hotp" });
|
|
129
|
+
const secret = otp.generateSecret();
|
|
130
|
+
|
|
131
|
+
const token = await otp.generate({ secret, counter: 0 });
|
|
132
|
+
const result = await otp.verify({ secret, token, counter: 0 });
|
|
133
|
+
console.log(result.valid); // true or false
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Compatibility with Authenticator Apps
|
|
97
137
|
|
|
98
138
|
### Secret Format
|
|
99
139
|
|
|
100
|
-
By default, otplib expects secrets to be in **Base32** format.
|
|
140
|
+
By default, otplib expects secrets to be in **Base32** format. This is the ensure broader compatiblity as it the standard format used by authenticator applications and QR code URIs.
|
|
141
|
+
|
|
142
|
+
While the core HOTP (RFC 4226) and TOTP (RFC 6238) specifications work with raw binary data and don't mandate Base32 encoding, Base32
|
|
101
143
|
|
|
102
144
|
```typescript
|
|
103
145
|
// Base32 secret (standard format for authenticator compatibility)
|
|
@@ -106,7 +148,22 @@ const secret = "GEZDGNBVGY3TQOJQGEZDGNBVGY";
|
|
|
106
148
|
|
|
107
149
|
However, if you need to use secrets in other formats, you can either use the `plugin-base32-alt` plugin for raw strings or pass a byte array (using `stringToBytes` helper) for binary data.
|
|
108
150
|
|
|
109
|
-
For more details and examples, see the [Secret Handling Guide](https://otplib.yeojz.dev/guide/secret-handling
|
|
151
|
+
For more details and examples, see the [Secret Handling Guide](https://otplib.yeojz.dev/guide/secret-handling) and related plugin documentation in the guides directory.
|
|
152
|
+
|
|
153
|
+
### Configuration Defaults
|
|
154
|
+
|
|
155
|
+
RFC 4226 (HOTP) and RFC 6238 (TOTP) define flexible algorithms that allow different hash functions, digit lengths, and time steps. However, most authenticator apps (Google Authenticator, Authy, Microsoft Authenticator, 1Password, etc.) and services offering 2 factor authentication use the following defaults:
|
|
156
|
+
|
|
157
|
+
| Parameter | Value |
|
|
158
|
+
| ----------- | ------------- |
|
|
159
|
+
| `algorithm` | `sha1` |
|
|
160
|
+
| `digits` | `6` |
|
|
161
|
+
| `period` | `30` |
|
|
162
|
+
| `secret` | Base32 string |
|
|
163
|
+
|
|
164
|
+
If you are deviating from these values, do validate that it is supported by the target application.
|
|
165
|
+
|
|
166
|
+
If you need to provision an authenticator app via QR code, use [`@otplib/uri`](https://www.npmjs.com/package/@otplib/uri) to generate an `otpauth://totp/` URI.
|
|
110
167
|
|
|
111
168
|
## Documentation
|
|
112
169
|
|
|
@@ -119,4 +176,4 @@ Refer to the [Getting Started Guide](https://otplib.yeojz.dev/guide/getting-star
|
|
|
119
176
|
|
|
120
177
|
## License
|
|
121
178
|
|
|
122
|
-
[MIT](./LICENSE)
|
|
179
|
+
[MIT](./LICENSE)
|
package/dist/class.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var P=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var U=(r,e)=>{for(var t in e)P(r,t,{get:e[t],enumerable:!0})},B=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of C(e))!D.call(r,a)&&a!==t&&P(r,a,{get:()=>e[a],enumerable:!(i=k(e,a))||i.enumerable});return r};var A=r=>B(P({},"__esModule",{value:!0}),r);var I={};U(I,{OTP:()=>S});module.exports=A(I);var O=require("@otplib/core");var V=require("@otplib/core"),c=require("@otplib/plugin-base32-scure"),l=require("@otplib/plugin-crypto-noble");function m(r){return{secret:r.secret,strategy:r.strategy??"totp",crypto:r.crypto??l.crypto,base32:r.base32??c.base32,algorithm:r.algorithm??"sha1",digits:r.digits??6,period:r.period??30,epoch:r.epoch??Math.floor(Date.now()/1e3),t0:r.t0??0,counter:r.counter,guardrails:r.guardrails??(0,V.createGuardrails)(),hooks:r.hooks}}function b(r){return{...m(r),token:r.token,epochTolerance:r.epochTolerance??0,counterTolerance:r.counterTolerance??0,afterTimeStep:r.afterTimeStep}}var T=require("@otplib/core"),u=require("@otplib/hotp"),y=require("@otplib/totp"),h=require("@otplib/uri");function f(r,e,t){if(r==="totp")return t.totp();if(r==="hotp"){if(e===void 0)throw new T.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return t.hotp(e)}throw new T.ConfigurationError(`Unknown OTP strategy: ${r}. Valid strategies are 'totp' or 'hotp'.`)}function R(r){let{strategy:e="totp",issuer:t,label:i,secret:a,algorithm:o="sha1",digits:s=6,period:n=30,counter:p}=r;return f(e,p,{totp:()=>(0,h.generateTOTP)({issuer:t,label:i,secret:a,algorithm:o,digits:s,period:n}),hotp:g=>(0,h.generateHOTP)({issuer:t,label:i,secret:a,algorithm:o,digits:s,counter:g})})}async function G(r){let e=m(r),{secret:t,crypto:i,base32:a,algorithm:o,digits:s,hooks:n}=e,p={secret:t,crypto:i,base32:a,algorithm:o,digits:s,hooks:n};return f(e.strategy,e.counter,{totp:()=>(0,y.generate)({...p,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:g=>(0,u.generate)({...p,counter:g,guardrails:e.guardrails})})}function H(r){let e=m(r),{secret:t,crypto:i,base32:a,algorithm:o,digits:s}=e,n={secret:t,crypto:i,base32:a,algorithm:o,digits:s};return f(e.strategy,e.counter,{totp:()=>(0,y.generateSync)({...n,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:p=>(0,u.generateSync)({...n,counter:p,guardrails:e.guardrails})})}async function x(r){let e=b(r),{secret:t,token:i,crypto:a,base32:o,algorithm:s,digits:n,hooks:p}=e,g={secret:t,token:i,crypto:a,base32:o,algorithm:s,digits:n,hooks:p};return f(e.strategy,e.counter,{totp:()=>(0,y.verify)({...g,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:d=>(0,u.verify)({...g,counter:d,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function v(r){let e=b(r),{secret:t,token:i,crypto:a,base32:o,algorithm:s,digits:n,hooks:p}=e,g={secret:t,token:i,crypto:a,base32:o,algorithm:s,digits:n,hooks:p};return f(e.strategy,e.counter,{totp:()=>(0,y.verifySync)({...g,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:d=>(0,u.verifySync)({...g,counter:d,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}var S=class{strategy;crypto;base32;guardrails;constructor(e={}){let{strategy:t="totp",crypto:i=l.crypto,base32:a=c.base32,guardrails:o}=e;this.strategy=t,this.crypto=i,this.base32=a,this.guardrails=(0,O.createGuardrails)(o)}getStrategy(){return this.strategy}generateSecret(e=20){return(0,O.generateSecret)({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return G({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateSync(e){return H({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}async verify(e){return x({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}verifySync(e){return v({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateURI(e){return R({...e,strategy:this.strategy})}};0&&(module.exports={OTP});
|
|
2
2
|
//# sourceMappingURL=class.cjs.map
|
package/dist/class.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead. Uses pre-instantiated frozen singletons\n * from the plugin packages.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { base32 as defaultBase32 } from \"@otplib/plugin-base32-scure\";\nimport { crypto as defaultCrypto } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\nexport { defaultCrypto, defaultBase32 };\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["class_exports","__export","OTP","__toCommonJS","import_core","import_core","import_plugin_base32_scure","import_plugin_crypto_noble","normalizeGenerateOptions","options","defaultCrypto","defaultBase32","normalizeVerifyOptions","import_core","import_hotp","import_totp","import_uri","executeByStrategy","strategy","counter","handlers","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
|
|
1
|
+
{"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n OTPHooks,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n\n /**\n * Hooks for customizing token encoding and validation\n */\n hooks?: OTPHooks;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Minimum allowed TOTP time step for replay protection (optional)\n *\n * Rejects tokens with timeStep <= afterTimeStep.\n * Only used by TOTP strategy.\n */\n afterTimeStep?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n\n /**\n * Hooks for customizing token encoding and validation\n */\n hooks?: OTPHooks;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead. Uses pre-instantiated frozen singletons\n * from the plugin packages.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { base32 as defaultBase32 } from \"@otplib/plugin-base32-scure\";\nimport { crypto as defaultCrypto } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\nexport { defaultCrypto, defaultBase32 };\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n hooks: options.hooks,\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n afterTimeStep: options.afterTimeStep,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n afterTimeStep: opts.afterTimeStep,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n afterTimeStep: opts.afterTimeStep,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["class_exports","__export","OTP","__toCommonJS","import_core","import_core","import_plugin_base32_scure","import_plugin_crypto_noble","normalizeGenerateOptions","options","defaultCrypto","defaultBase32","normalizeVerifyOptions","import_core","import_hotp","import_totp","import_uri","executeByStrategy","strategy","counter","handlers","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","hooks","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
|
package/dist/class.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits } from '@otplib/core';
|
|
1
|
+
import { b as OTPStrategy } from './types-BBT_82HF.cjs';
|
|
2
|
+
import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits, OTPHooks } from '@otplib/core';
|
|
3
3
|
import { VerifyResult as VerifyResult$2 } from '@otplib/hotp';
|
|
4
4
|
import { VerifyResult as VerifyResult$1 } from '@otplib/totp';
|
|
5
5
|
|
|
@@ -79,6 +79,10 @@ type OTPGenerateOptions = {
|
|
|
79
79
|
* Validation guardrails
|
|
80
80
|
*/
|
|
81
81
|
guardrails?: OTPGuardrails;
|
|
82
|
+
/**
|
|
83
|
+
* Hooks for customizing token encoding and validation
|
|
84
|
+
*/
|
|
85
|
+
hooks?: OTPHooks;
|
|
82
86
|
};
|
|
83
87
|
/**
|
|
84
88
|
* Options for verifying a token with the OTP class
|
|
@@ -136,10 +140,21 @@ type OTPVerifyOptions = {
|
|
|
136
140
|
* - Tuple [past, future]: explicit window control
|
|
137
141
|
*/
|
|
138
142
|
counterTolerance?: number | [number, number];
|
|
143
|
+
/**
|
|
144
|
+
* Minimum allowed TOTP time step for replay protection (optional)
|
|
145
|
+
*
|
|
146
|
+
* Rejects tokens with timeStep <= afterTimeStep.
|
|
147
|
+
* Only used by TOTP strategy.
|
|
148
|
+
*/
|
|
149
|
+
afterTimeStep?: number;
|
|
139
150
|
/**
|
|
140
151
|
* Validation guardrails
|
|
141
152
|
*/
|
|
142
153
|
guardrails?: OTPGuardrails;
|
|
154
|
+
/**
|
|
155
|
+
* Hooks for customizing token encoding and validation
|
|
156
|
+
*/
|
|
157
|
+
hooks?: OTPHooks;
|
|
143
158
|
};
|
|
144
159
|
/**
|
|
145
160
|
* Options for generating URI with the OTP class
|
package/dist/class.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits } from '@otplib/core';
|
|
1
|
+
import { b as OTPStrategy } from './types-BBT_82HF.js';
|
|
2
|
+
import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits, OTPHooks } from '@otplib/core';
|
|
3
3
|
import { VerifyResult as VerifyResult$2 } from '@otplib/hotp';
|
|
4
4
|
import { VerifyResult as VerifyResult$1 } from '@otplib/totp';
|
|
5
5
|
|
|
@@ -79,6 +79,10 @@ type OTPGenerateOptions = {
|
|
|
79
79
|
* Validation guardrails
|
|
80
80
|
*/
|
|
81
81
|
guardrails?: OTPGuardrails;
|
|
82
|
+
/**
|
|
83
|
+
* Hooks for customizing token encoding and validation
|
|
84
|
+
*/
|
|
85
|
+
hooks?: OTPHooks;
|
|
82
86
|
};
|
|
83
87
|
/**
|
|
84
88
|
* Options for verifying a token with the OTP class
|
|
@@ -136,10 +140,21 @@ type OTPVerifyOptions = {
|
|
|
136
140
|
* - Tuple [past, future]: explicit window control
|
|
137
141
|
*/
|
|
138
142
|
counterTolerance?: number | [number, number];
|
|
143
|
+
/**
|
|
144
|
+
* Minimum allowed TOTP time step for replay protection (optional)
|
|
145
|
+
*
|
|
146
|
+
* Rejects tokens with timeStep <= afterTimeStep.
|
|
147
|
+
* Only used by TOTP strategy.
|
|
148
|
+
*/
|
|
149
|
+
afterTimeStep?: number;
|
|
139
150
|
/**
|
|
140
151
|
* Validation guardrails
|
|
141
152
|
*/
|
|
142
153
|
guardrails?: OTPGuardrails;
|
|
154
|
+
/**
|
|
155
|
+
* Hooks for customizing token encoding and validation
|
|
156
|
+
*/
|
|
157
|
+
hooks?: OTPHooks;
|
|
143
158
|
};
|
|
144
159
|
/**
|
|
145
160
|
* Options for generating URI with the OTP class
|
package/dist/class.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createGuardrails as A,generateSecret as I}from"@otplib/core";import{createGuardrails as
|
|
1
|
+
import{createGuardrails as A,generateSecret as I}from"@otplib/core";import{createGuardrails as V}from"@otplib/core";import{base32 as y}from"@otplib/plugin-base32-scure";import{crypto as c}from"@otplib/plugin-crypto-noble";function l(r){return{secret:r.secret,strategy:r.strategy??"totp",crypto:r.crypto??c,base32:r.base32??y,algorithm:r.algorithm??"sha1",digits:r.digits??6,period:r.period??30,epoch:r.epoch??Math.floor(Date.now()/1e3),t0:r.t0??0,counter:r.counter,guardrails:r.guardrails??V(),hooks:r.hooks}}function m(r){return{...l(r),token:r.token,epochTolerance:r.epochTolerance??0,counterTolerance:r.counterTolerance??0,afterTimeStep:r.afterTimeStep}}import{generateSecret as q,ConfigurationError as T}from"@otplib/core";import{generate as R,generateSync as G,verify as H,verifySync as x}from"@otplib/hotp";import{generate as v,generateSync as k,verify as C,verifySync as D}from"@otplib/totp";import{generateTOTP as U,generateHOTP as B}from"@otplib/uri";function u(r,e,t){if(r==="totp")return t.totp();if(r==="hotp"){if(e===void 0)throw new T("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return t.hotp(e)}throw new T(`Unknown OTP strategy: ${r}. Valid strategies are 'totp' or 'hotp'.`)}function h(r){let{strategy:e="totp",issuer:t,label:a,secret:i,algorithm:o="sha1",digits:s=6,period:n=30,counter:p}=r;return u(e,p,{totp:()=>U({issuer:t,label:a,secret:i,algorithm:o,digits:s,period:n}),hotp:g=>B({issuer:t,label:a,secret:i,algorithm:o,digits:s,counter:g})})}async function O(r){let e=l(r),{secret:t,crypto:a,base32:i,algorithm:o,digits:s,hooks:n}=e,p={secret:t,crypto:a,base32:i,algorithm:o,digits:s,hooks:n};return u(e.strategy,e.counter,{totp:()=>v({...p,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:g=>R({...p,counter:g,guardrails:e.guardrails})})}function d(r){let e=l(r),{secret:t,crypto:a,base32:i,algorithm:o,digits:s}=e,n={secret:t,crypto:a,base32:i,algorithm:o,digits:s};return u(e.strategy,e.counter,{totp:()=>k({...n,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:p=>G({...n,counter:p,guardrails:e.guardrails})})}async function P(r){let e=m(r),{secret:t,token:a,crypto:i,base32:o,algorithm:s,digits:n,hooks:p}=e,g={secret:t,token:a,crypto:i,base32:o,algorithm:s,digits:n,hooks:p};return u(e.strategy,e.counter,{totp:()=>C({...g,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:f=>H({...g,counter:f,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function b(r){let e=m(r),{secret:t,token:a,crypto:i,base32:o,algorithm:s,digits:n,hooks:p}=e,g={secret:t,token:a,crypto:i,base32:o,algorithm:s,digits:n,hooks:p};return u(e.strategy,e.counter,{totp:()=>D({...g,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:f=>x({...g,counter:f,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}var S=class{strategy;crypto;base32;guardrails;constructor(e={}){let{strategy:t="totp",crypto:a=c,base32:i=y,guardrails:o}=e;this.strategy=t,this.crypto=a,this.base32=i,this.guardrails=A(o)}getStrategy(){return this.strategy}generateSecret(e=20){return I({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return O({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateSync(e){return d({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}async verify(e){return P({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}verifySync(e){return b({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateURI(e){return h({...e,strategy:this.strategy})}};export{S as OTP};
|
|
2
2
|
//# sourceMappingURL=class.js.map
|
package/dist/class.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead. Uses pre-instantiated frozen singletons\n * from the plugin packages.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { base32 as defaultBase32 } from \"@otplib/plugin-base32-scure\";\nimport { crypto as defaultCrypto } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\nexport { defaultCrypto, defaultBase32 };\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["createGuardrails","generateSecretCore","createGuardrails","defaultBase32","defaultCrypto","normalizeGenerateOptions","options","defaultCrypto","defaultBase32","createGuardrails","normalizeVerifyOptions","generateSecretCore","ConfigurationError","generateHOTP","generateHOTPSync","verifyHOTP","verifyHOTPSync","generateTOTP","generateTOTPSync","verifyTOTP","verifyTOTPSync","generateTOTPURI","generateHOTURI","executeByStrategy","strategy","counter","handlers","ConfigurationError","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","createGuardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
|
|
1
|
+
{"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n OTPHooks,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n\n /**\n * Hooks for customizing token encoding and validation\n */\n hooks?: OTPHooks;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Minimum allowed TOTP time step for replay protection (optional)\n *\n * Rejects tokens with timeStep <= afterTimeStep.\n * Only used by TOTP strategy.\n */\n afterTimeStep?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n\n /**\n * Hooks for customizing token encoding and validation\n */\n hooks?: OTPHooks;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead. Uses pre-instantiated frozen singletons\n * from the plugin packages.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { base32 as defaultBase32 } from \"@otplib/plugin-base32-scure\";\nimport { crypto as defaultCrypto } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\nexport { defaultCrypto, defaultBase32 };\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n hooks: options.hooks,\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n afterTimeStep: options.afterTimeStep,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n afterTimeStep: opts.afterTimeStep,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits, hooks } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits, hooks };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n afterTimeStep: opts.afterTimeStep,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["createGuardrails","generateSecretCore","createGuardrails","defaultBase32","defaultCrypto","normalizeGenerateOptions","options","defaultCrypto","defaultBase32","createGuardrails","normalizeVerifyOptions","generateSecretCore","ConfigurationError","generateHOTP","generateHOTPSync","verifyHOTP","verifyHOTPSync","generateTOTP","generateTOTPSync","verifyTOTP","verifyTOTPSync","generateTOTPURI","generateHOTURI","executeByStrategy","strategy","counter","handlers","ConfigurationError","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","hooks","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","createGuardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
|
package/dist/functional.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var d=Object.defineProperty;var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var H=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},R=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of b(e))!x.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(a=V(e,o))||a.enumerable});return t};var k=t=>R(d({},"__esModule",{value:!0}),t);var z={};H(z,{generate:()=>C,generateSecret:()=>v,generateSync:()=>D,generateURI:()=>G,verify:()=>w,verifySync:()=>B});module.exports=k(z);var l=require("@otplib/core"),g=require("@otplib/hotp"),u=require("@otplib/totp"),O=require("@otplib/uri");var S=require("@otplib/core"),f=require("@otplib/plugin-base32-scure"),T=require("@otplib/plugin-crypto-noble");function m(t){return{secret:t.secret,strategy:t.strategy??"totp",crypto:t.crypto??T.crypto,base32:t.base32??f.base32,algorithm:t.algorithm??"sha1",digits:t.digits??6,period:t.period??30,epoch:t.epoch??Math.floor(Date.now()/1e3),t0:t.t0??0,counter:t.counter,guardrails:t.guardrails??(0,S.createGuardrails)(),hooks:t.hooks}}function P(t){return{...m(t),token:t.token,epochTolerance:t.epochTolerance??0,counterTolerance:t.counterTolerance??0,afterTimeStep:t.afterTimeStep}}function y(t,e,r){if(t==="totp")return r.totp();if(t==="hotp"){if(e===void 0)throw new l.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return r.hotp(e)}throw new l.ConfigurationError(`Unknown OTP strategy: ${t}. Valid strategies are 'totp' or 'hotp'.`)}function v(t){let{crypto:e=T.crypto,base32:r=f.base32,length:a=20}=t||{};return(0,l.generateSecret)({crypto:e,base32:r,length:a})}function G(t){let{strategy:e="totp",issuer:r,label:a,secret:o,algorithm:i="sha1",digits:n=6,period:s=30,counter:p}=t;return y(e,p,{totp:()=>(0,O.generateTOTP)({issuer:r,label:a,secret:o,algorithm:i,digits:n,period:s}),hotp:c=>(0,O.generateHOTP)({issuer:r,label:a,secret:o,algorithm:i,digits:n,counter:c})})}async function C(t){let e=m(t),{secret:r,crypto:a,base32:o,algorithm:i,digits:n,hooks:s}=e,p={secret:r,crypto:a,base32:o,algorithm:i,digits:n,hooks:s};return y(e.strategy,e.counter,{totp:()=>(0,u.generate)({...p,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:c=>(0,g.generate)({...p,counter:c,guardrails:e.guardrails})})}function D(t){let e=m(t),{secret:r,crypto:a,base32:o,algorithm:i,digits:n}=e,s={secret:r,crypto:a,base32:o,algorithm:i,digits:n};return y(e.strategy,e.counter,{totp:()=>(0,u.generateSync)({...s,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:p=>(0,g.generateSync)({...s,counter:p,guardrails:e.guardrails})})}async function w(t){let e=P(t),{secret:r,token:a,crypto:o,base32:i,algorithm:n,digits:s,hooks:p}=e,c={secret:r,token:a,crypto:o,base32:i,algorithm:n,digits:s,hooks:p};return y(e.strategy,e.counter,{totp:()=>(0,u.verify)({...c,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:h=>(0,g.verify)({...c,counter:h,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function B(t){let e=P(t),{secret:r,token:a,crypto:o,base32:i,algorithm:n,digits:s,hooks:p}=e,c={secret:r,token:a,crypto:o,base32:i,algorithm:n,digits:s,hooks:p};return y(e.strategy,e.counter,{totp:()=>(0,u.verifySync)({...c,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,afterTimeStep:e.afterTimeStep,guardrails:e.guardrails}),hotp:h=>(0,g.verifySync)({...c,counter:h,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}0&&(module.exports={generate,generateSecret,generateSync,generateURI,verify,verifySync});
|
|
2
2
|
//# sourceMappingURL=functional.cjs.map
|