@owlmeans/server-auth-otp 0.1.18-rc.51 → 0.1.18-rc.52

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.
Files changed (43) hide show
  1. package/README.md +2 -2
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/server-auth-otp/SKILL.md +1 -1
  4. package/build/challenge.d.ts +1 -2
  5. package/build/challenge.d.ts.map +1 -1
  6. package/build/challenge.js +2 -23
  7. package/build/challenge.js.map +1 -1
  8. package/build/consts.d.ts +6 -0
  9. package/build/consts.d.ts.map +1 -1
  10. package/build/consts.js +7 -0
  11. package/build/consts.js.map +1 -1
  12. package/build/consts.local.d.ts +4 -0
  13. package/build/consts.local.d.ts.map +1 -0
  14. package/build/consts.local.js +50 -0
  15. package/build/consts.local.js.map +1 -0
  16. package/build/plugin.d.ts.map +1 -1
  17. package/build/plugin.js +1 -2
  18. package/build/plugin.js.map +1 -1
  19. package/build/service.d.ts +1 -1
  20. package/build/service.d.ts.map +1 -1
  21. package/build/service.js +2 -3
  22. package/build/service.js.map +1 -1
  23. package/build/throttle.d.ts +1 -2
  24. package/build/throttle.d.ts.map +1 -1
  25. package/build/throttle.js +2 -28
  26. package/build/throttle.js.map +1 -1
  27. package/build/types.d.ts +1 -6
  28. package/build/types.d.ts.map +1 -1
  29. package/build/types.js +1 -7
  30. package/build/types.js.map +1 -1
  31. package/build/types.local.d.ts +14 -0
  32. package/build/types.local.d.ts.map +1 -0
  33. package/build/types.local.js +2 -0
  34. package/build/types.local.js.map +1 -0
  35. package/package.json +14 -14
  36. package/src/challenge.ts +4 -32
  37. package/src/consts.local.ts +51 -0
  38. package/src/consts.ts +7 -0
  39. package/src/plugin.ts +4 -9
  40. package/src/service.ts +3 -9
  41. package/src/throttle.ts +3 -34
  42. package/src/types.local.ts +10 -0
  43. package/src/types.ts +1 -7
package/README.md CHANGED
@@ -12,7 +12,7 @@ Email OTP `AuthPlugin` for OwlMeans servers — passwordless login via time-limi
12
12
  ## Installation
13
13
 
14
14
  ```bash
15
- bun add @owlmeans/server-auth-otp@^0.1.18-rc.51
15
+ bun add @owlmeans/server-auth-otp@^0.1.18-rc.52
16
16
  ```
17
17
 
18
18
  ## Usage
@@ -47,7 +47,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
47
47
  your project's skill store (`.agents/skills/`):
48
48
 
49
49
  ```sh
50
- npx @owlmeans/agent-skills@^0.1.18-rc.47
50
+ npx @owlmeans/agent-skills@^0.1.18-rc.48
51
51
  ```
52
52
 
53
53
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-auth-otp",
4
- "version": "0.1.18-rc.51",
5
- "generatedAt": "2026-10-03T20:05:07.593Z",
4
+ "version": "0.1.18-rc.52",
5
+ "generatedAt": "2026-10-05T08:32:19.110Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ metadata:
8
8
 
9
9
  # Using `@owlmeans/server-auth-otp`
10
10
 
11
- **Install:** `"@owlmeans/server-auth-otp": "^0.1.18-rc.51"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-auth-otp": "^0.1.18-rc.52"` in `dependencies`
12
12
 
13
13
  Email OTP authentication plugin for the OwlMeans auth-manager plugin system. Relies on `@owlmeans/auth-otp` for the OTP service interface, a Redis resource for code storage, and a `MailerService` to send codes.
14
14
 
@@ -1,8 +1,7 @@
1
1
  import type { OtpChallengeStore } from './types.js';
2
- type Clock = () => number;
2
+ import type { Clock } from './types.local.js';
3
3
  /** Real in-memory challenge store with synchronous consume/update semantics. */
4
4
  export declare const makeMemoryOtpChallengeStore: (alias?: string, now?: Clock) => OtpChallengeStore;
5
5
  /** Redis challenge store: compare, attempt increment, exhaustion, and consume are one operation. */
6
6
  export declare const makeRedisOtpChallengeStore: (alias?: string, resourceAlias?: string) => OtpChallengeStore;
7
- export {};
8
7
  //# sourceMappingURL=challenge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACyB,iBAAiB,EACrD,MAAM,YAAY,CAAA;AAGnB,KAAK,KAAK,GAAG,MAAM,MAAM,CAAA;AAGzB,gFAAgF;AAChF,eAAO,MAAM,2BAA2B,yBACJ,KAAK,KACtC,iBA+BF,CAAA;AA0BD,oGAAoG;AACpG,eAAO,MAAM,0BAA0B,8CAEpC,iBAqCF,CAAA"}
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,YAAY,CAAA;AAE1E,OAAO,KAAK,EAA2B,KAAK,EAAmB,MAAM,kBAAkB,CAAA;AAGvF,gFAAgF;AAChF,eAAO,MAAM,2BAA2B,yBACJ,KAAK,KACtC,iBA+BF,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,0BAA0B,8CAEpC,iBAqCF,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { appendContextual, createService } from '@owlmeans/context';
2
2
  import { OtpUnavailable } from './errors.js';
3
- import { OTP_CHALLENGE_STORE, OTP_RESOURCE } from './consts.js';
4
- import { OtpChallengeOutcome as Outcome } from './types.js';
3
+ import { OTP_CHALLENGE_STORE, OTP_RESOURCE, OtpChallengeOutcome as Outcome } from './consts.js';
4
+ import { REDIS_VERIFY_SCRIPT } from './consts.local.js';
5
5
  /** Real in-memory challenge store with synchronous consume/update semantics. */
6
6
  export const makeMemoryOtpChallengeStore = (alias = OTP_CHALLENGE_STORE, now = Date.now) => {
7
7
  const records = new Map();
@@ -34,27 +34,6 @@ export const makeMemoryOtpChallengeStore = (alias = OTP_CHALLENGE_STORE, now = D
34
34
  },
35
35
  });
36
36
  };
37
- const REDIS_VERIFY_SCRIPT = `
38
- local raw = redis.call('GET', KEYS[1])
39
- if not raw then return 0 end
40
- local record = cjson.decode(raw)
41
- if record.emailKey == ARGV[1] and record.codeHash == ARGV[2] then
42
- redis.call('DEL', KEYS[1])
43
- return 1
44
- end
45
- record.failedAttempts = tonumber(record.failedAttempts or 0) + 1
46
- if record.failedAttempts >= tonumber(ARGV[3]) then
47
- redis.call('DEL', KEYS[1])
48
- return -2
49
- end
50
- local ttl = redis.call('PTTL', KEYS[1])
51
- if ttl <= 0 then
52
- redis.call('DEL', KEYS[1])
53
- return 0
54
- end
55
- redis.call('SET', KEYS[1], cjson.encode(record), 'XX', 'PX', ttl)
56
- return -1
57
- `;
58
37
  /** Redis challenge store: compare, attempt increment, exhaustion, and consume are one operation. */
59
38
  export const makeRedisOtpChallengeStore = (alias = OTP_CHALLENGE_STORE, resourceAlias = OTP_RESOURCE) => {
60
39
  const service = appendContextual(alias, {
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"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"}
package/build/consts.d.ts CHANGED
@@ -10,4 +10,10 @@ export declare const OTP_EMAIL_THROTTLE_RULES: readonly (Readonly<{
10
10
  }>)[];
11
11
  /** The OTP auth plugin type key — passed as credential.type in init requests */
12
12
  export { OTP_AUTH_TYPE, OTP_SERVICE, OTP_RESOURCE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS, } from '@owlmeans/auth-otp';
13
+ export declare enum OtpChallengeOutcome {
14
+ Verified = "verified",
15
+ Invalid = "invalid",
16
+ Exhausted = "exhausted",
17
+ Missing = "missing"
18
+ }
13
19
  //# sourceMappingURL=consts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,oBAAoB,CAAA;AAChD,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAC7D,eAAO,MAAM,oBAAoB,sBAAsB,CAAA;AAEvD,eAAO,MAAM,wBAAwB;;;;;;KAGnC,CAAA;AAEF,gFAAgF;AAChF,OAAO,EACL,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAC1E,uBAAuB,GACxB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,oBAAoB,CAAA;AAChD,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAC7D,eAAO,MAAM,oBAAoB,sBAAsB,CAAA;AAEvD,eAAO,MAAM,wBAAwB;;;;;;KAGnC,CAAA;AAEF,gFAAgF;AAChF,OAAO,EACL,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAC1E,uBAAuB,GACxB,MAAM,oBAAoB,CAAA;AAE3B,oBAAY,mBAAmB;IAC7B,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;CACpB"}
package/build/consts.js CHANGED
@@ -7,4 +7,11 @@ export const OTP_EMAIL_THROTTLE_RULES = Object.freeze([
7
7
  ]);
8
8
  /** The OTP auth plugin type key — passed as credential.type in init requests */
9
9
  export { OTP_AUTH_TYPE, OTP_SERVICE, OTP_RESOURCE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS, } from '@owlmeans/auth-otp';
10
+ export var OtpChallengeOutcome;
11
+ (function (OtpChallengeOutcome) {
12
+ OtpChallengeOutcome["Verified"] = "verified";
13
+ OtpChallengeOutcome["Invalid"] = "invalid";
14
+ OtpChallengeOutcome["Exhausted"] = "exhausted";
15
+ OtpChallengeOutcome["Missing"] = "missing";
16
+ })(OtpChallengeOutcome || (OtpChallengeOutcome = {}));
10
17
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,0BAA0B,CAAA;AAC7D,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAA;AAEvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;IAC9C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;CACrD,CAAC,CAAA;AAEF,gFAAgF;AAChF,OAAO,EACL,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAC1E,uBAAuB,GACxB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,0BAA0B,CAAA;AAC7D,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAA;AAEvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;IAC9C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;CACrD,CAAC,CAAA;AAEF,gFAAgF;AAChF,OAAO,EACL,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAC1E,uBAAuB,GACxB,MAAM,oBAAoB,CAAA;AAE3B,MAAM,CAAN,IAAY,mBAKX;AALD,WAAY,mBAAmB;IAC7B,4CAAqB,CAAA;IACrB,0CAAmB,CAAA;IACnB,8CAAuB,CAAA;IACvB,0CAAmB,CAAA;AACrB,CAAC,EALW,mBAAmB,KAAnB,mBAAmB,QAK9B"}
@@ -0,0 +1,4 @@
1
+ export declare const REDIS_VERIFY_SCRIPT = "\nlocal raw = redis.call('GET', KEYS[1])\nif not raw then return 0 end\nlocal record = cjson.decode(raw)\nif record.emailKey == ARGV[1] and record.codeHash == ARGV[2] then\n redis.call('DEL', KEYS[1])\n return 1\nend\nrecord.failedAttempts = tonumber(record.failedAttempts or 0) + 1\nif record.failedAttempts >= tonumber(ARGV[3]) then\n redis.call('DEL', KEYS[1])\n return -2\nend\nlocal ttl = redis.call('PTTL', KEYS[1])\nif ttl <= 0 then\n redis.call('DEL', KEYS[1])\n return 0\nend\nredis.call('SET', KEYS[1], cjson.encode(record), 'XX', 'PX', ttl)\nreturn -1\n";
2
+ export declare const CHALLENGE_DELIMITER = "::";
3
+ export declare const REDIS_THROTTLE_SCRIPT = "\nlocal time = redis.call('TIME')\nlocal now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)\nlocal retry = 0\nfor index = 1, #KEYS do\n local offset = (index - 1) * 2\n local limit = tonumber(ARGV[offset + 1])\n local window = tonumber(ARGV[offset + 2])\n redis.call('ZREMRANGEBYSCORE', KEYS[index], '-inf', now - window)\n local count = redis.call('ZCARD', KEYS[index])\n if count >= limit then\n local oldest = redis.call('ZRANGE', KEYS[index], 0, 0, 'WITHSCORES')\n if #oldest == 2 then\n retry = math.max(retry, math.ceil((tonumber(oldest[2]) + window - now) / 1000))\n end\n end\nend\nif retry > 0 then return {0, retry} end\nlocal token = ARGV[#KEYS * 2 + 1]\nfor index = 1, #KEYS do\n local window = tonumber(ARGV[(index - 1) * 2 + 2])\n redis.call('ZADD', KEYS[index], now, token .. ':' .. index)\n redis.call('PEXPIRE', KEYS[index], window)\nend\nreturn {1, 0}\n";
4
+ //# sourceMappingURL=consts.local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.local.d.ts","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+jBAoB/B,CAAA;AAGD,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,eAAO,MAAM,qBAAqB,u5BAyBjC,CAAA"}
@@ -0,0 +1,50 @@
1
+ export const REDIS_VERIFY_SCRIPT = `
2
+ local raw = redis.call('GET', KEYS[1])
3
+ if not raw then return 0 end
4
+ local record = cjson.decode(raw)
5
+ if record.emailKey == ARGV[1] and record.codeHash == ARGV[2] then
6
+ redis.call('DEL', KEYS[1])
7
+ return 1
8
+ end
9
+ record.failedAttempts = tonumber(record.failedAttempts or 0) + 1
10
+ if record.failedAttempts >= tonumber(ARGV[3]) then
11
+ redis.call('DEL', KEYS[1])
12
+ return -2
13
+ end
14
+ local ttl = redis.call('PTTL', KEYS[1])
15
+ if ttl <= 0 then
16
+ redis.call('DEL', KEYS[1])
17
+ return 0
18
+ end
19
+ redis.call('SET', KEYS[1], cjson.encode(record), 'XX', 'PX', ttl)
20
+ return -1
21
+ `;
22
+ // Separates the email from the opaque issuance id inside the signed challenge.
23
+ export const CHALLENGE_DELIMITER = '::';
24
+ export const REDIS_THROTTLE_SCRIPT = `
25
+ local time = redis.call('TIME')
26
+ local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)
27
+ local retry = 0
28
+ for index = 1, #KEYS do
29
+ local offset = (index - 1) * 2
30
+ local limit = tonumber(ARGV[offset + 1])
31
+ local window = tonumber(ARGV[offset + 2])
32
+ redis.call('ZREMRANGEBYSCORE', KEYS[index], '-inf', now - window)
33
+ local count = redis.call('ZCARD', KEYS[index])
34
+ if count >= limit then
35
+ local oldest = redis.call('ZRANGE', KEYS[index], 0, 0, 'WITHSCORES')
36
+ if #oldest == 2 then
37
+ retry = math.max(retry, math.ceil((tonumber(oldest[2]) + window - now) / 1000))
38
+ end
39
+ end
40
+ end
41
+ if retry > 0 then return {0, retry} end
42
+ local token = ARGV[#KEYS * 2 + 1]
43
+ for index = 1, #KEYS do
44
+ local window = tonumber(ARGV[(index - 1) * 2 + 2])
45
+ redis.call('ZADD', KEYS[index], now, token .. ':' .. index)
46
+ redis.call('PEXPIRE', KEYS[index], window)
47
+ end
48
+ return {1, 0}
49
+ `;
50
+ //# sourceMappingURL=consts.local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.local.js","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBlC,CAAA;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAA;AAEvC,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBpC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAqEvD,sGAAsG;AACtG,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,KAAG,CAG1F,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAmEvD,sGAAsG;AACtG,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,KAAG,CAG1F,CAAA"}
package/build/plugin.js CHANGED
@@ -2,8 +2,7 @@ import { ALL_SCOPES, AuthenFailed, AuthRole, AuthenticationType } from '@owlmean
2
2
  import { AuthChallengeReplayPolicy, registerPlugin } from '@owlmeans/server-auth/manager/plugins';
3
3
  import { OTP_AUTH_TYPE, OTP_SERVICE } from '@owlmeans/auth-otp';
4
4
  import { AUTH_IDENTITY_LINKING } from '@owlmeans/server-auth-identity';
5
- // Separates the email from the opaque issuance id inside the signed challenge.
6
- const CHALLENGE_DELIMITER = '::';
5
+ import { CHALLENGE_DELIMITER } from './consts.local.js';
7
6
  /** Factory that creates the email-OTP AuthPlugin bound to the given context. */
8
7
  const otpPlugin = (context) => ({
9
8
  type: OTP_AUTH_TYPE,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { OtpService } from '@owlmeans/auth-otp';
1
+ import { type OtpService } from '@owlmeans/auth-otp';
2
2
  export declare const otpChallengeKey: (issuanceId: string) => string;
3
3
  export declare const otpEmailKey: (email: string) => string;
4
4
  export declare const otpCodeHash: (issuanceId: string, code: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAwBpD,eAAO,MAAM,eAAe,eAAgB,MAAM,KAAG,MAAuD,CAAA;AAC5G,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,MAAqD,CAAA;AACjG,eAAO,MAAM,WAAW,eAAgB,MAAM,QAAQ,MAAM,KAAG,MACd,CAAA;AAEjD,eAAO,MAAM,cAAc,sBAA0B,UA0EpD,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAwF,MAAM,oBAAoB,CAAA;AAkB1I,eAAO,MAAM,eAAe,eAAgB,MAAM,KAAG,MAAuD,CAAA;AAC5G,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,MAAqD,CAAA;AACjG,eAAO,MAAM,WAAW,eAAgB,MAAM,QAAQ,MAAM,KAAG,MACd,CAAA;AAEjD,eAAO,MAAM,cAAc,sBAA0B,UA0EpD,CAAA"}
package/build/service.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { appendContextual } from '@owlmeans/context';
2
2
  import { AuthenFailed } from '@owlmeans/auth';
3
- import { OTP_SERVICE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS, OTP_RESOURCE, } from '@owlmeans/auth-otp';
3
+ import { OTP_SERVICE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS, OTP_RESOURCE } from '@owlmeans/auth-otp';
4
4
  import { MAILER_SERVICE } from '@owlmeans/mailer';
5
5
  import { createHash, randomBytes, randomInt } from 'node:crypto';
6
- import { OtpChallengeOutcome } from './types.js';
7
- import { OTP_CHALLENGE_STORE } from './consts.js';
6
+ import { OtpChallengeOutcome, OTP_CHALLENGE_STORE } from './consts.js';
8
7
  import { emailThrottleKey } from './throttle.js';
9
8
  import { OtpThrottled, OtpUnavailable } from './errors.js';
10
9
  import { makeRedisOtpChallengeStore } from './challenge.js';
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { AuthThrottleService } from './types.js';
2
- type Clock = () => number;
2
+ import type { Clock } from './types.local.js';
3
3
  /** Collision-resistant, non-raw key for case-insensitive email throttles. */
4
4
  export declare const emailThrottleKey: (email: string) => string;
5
5
  /** Non-raw key for request-source throttles. Callers remain responsible for trusted-proxy parsing. */
@@ -8,5 +8,4 @@ export declare const ipThrottleKey: (ip: string) => string;
8
8
  export declare const makeMemoryThrottleService: (alias?: string, now?: Clock) => AuthThrottleService;
9
9
  /** Redis implementation: every configured window is checked and consumed in one Lua operation. */
10
10
  export declare const makeRedisThrottleService: (alias?: string, resourceAlias?: string) => AuthThrottleService;
11
- export {};
12
11
  //# sourceMappingURL=throttle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAyD,MAAM,YAAY,CAAA;AAG5G,KAAK,KAAK,GAAG,MAAM,MAAM,CAAA;AAKzB,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,UAAW,MAAM,KAAG,MACU,CAAA;AAE3D,sGAAsG;AACtG,eAAO,MAAM,aAAa,OAAQ,MAAM,KAAG,MACO,CAAA;AASlD,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,yBACD,KAAK,KACvC,mBAyBF,CAAA;AA+BD,kGAAkG;AAClG,eAAO,MAAM,wBAAwB,8CAElC,mBA4BF,CAAA"}
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAyD,MAAM,YAAY,CAAA;AAG5G,OAAO,KAAK,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAA;AAKrE,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,UAAW,MAAM,KAAG,MACU,CAAA;AAE3D,sGAAsG;AACtG,eAAO,MAAM,aAAa,OAAQ,MAAM,KAAG,MACO,CAAA;AASlD,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,yBACD,KAAK,KACvC,mBAyBF,CAAA;AAED,kGAAkG;AAClG,eAAO,MAAM,wBAAwB,8CAElC,mBA4BF,CAAA"}
package/build/throttle.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createHash, randomBytes } from 'node:crypto';
2
- import { createService } from '@owlmeans/context';
3
- import { appendContextual } from '@owlmeans/context';
2
+ import { createService, appendContextual } from '@owlmeans/context';
4
3
  import { OtpUnavailable } from './errors.js';
5
4
  import { OTP_RESOURCE, OTP_THROTTLE_SERVICE } from './consts.js';
5
+ import { REDIS_THROTTLE_SCRIPT } from './consts.local.js';
6
6
  const digestKey = (kind, value) => createHash('sha256').update(`owlmeans:throttle:${kind}\0${value}`).digest('hex');
7
7
  /** Collision-resistant, non-raw key for case-insensitive email throttles. */
8
8
  export const emailThrottleKey = (email) => `email:${digestKey('email', email.trim().toLowerCase())}`;
@@ -39,32 +39,6 @@ export const makeMemoryThrottleService = (alias = OTP_THROTTLE_SERVICE, now = Da
39
39
  },
40
40
  });
41
41
  };
42
- const REDIS_THROTTLE_SCRIPT = `
43
- local time = redis.call('TIME')
44
- local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)
45
- local retry = 0
46
- for index = 1, #KEYS do
47
- local offset = (index - 1) * 2
48
- local limit = tonumber(ARGV[offset + 1])
49
- local window = tonumber(ARGV[offset + 2])
50
- redis.call('ZREMRANGEBYSCORE', KEYS[index], '-inf', now - window)
51
- local count = redis.call('ZCARD', KEYS[index])
52
- if count >= limit then
53
- local oldest = redis.call('ZRANGE', KEYS[index], 0, 0, 'WITHSCORES')
54
- if #oldest == 2 then
55
- retry = math.max(retry, math.ceil((tonumber(oldest[2]) + window - now) / 1000))
56
- end
57
- end
58
- end
59
- if retry > 0 then return {0, retry} end
60
- local token = ARGV[#KEYS * 2 + 1]
61
- for index = 1, #KEYS do
62
- local window = tonumber(ARGV[(index - 1) * 2 + 2])
63
- redis.call('ZADD', KEYS[index], now, token .. ':' .. index)
64
- redis.call('PEXPIRE', KEYS[index], window)
65
- end
66
- return {1, 0}
67
- `;
68
42
  /** Redis implementation: every configured window is checked and consumed in one Lua operation. */
69
43
  export const makeRedisThrottleService = (alias = OTP_THROTTLE_SERVICE, resourceAlias = OTP_RESOURCE) => {
70
44
  const service = appendContextual(alias, {
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.js","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"throttle.js","sourceRoot":"","sources":["../src/throttle.ts"],"names":[],"mappings":"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"}
package/build/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
2
2
  import type { InitializedService } from '@owlmeans/context';
3
+ import { OtpChallengeOutcome } from './consts.js';
3
4
  export interface ThrottleRule {
4
5
  limit: number;
5
6
  windowSeconds: number;
@@ -17,12 +18,6 @@ export interface OtpChallenge {
17
18
  emailKey: string;
18
19
  codeHash: string;
19
20
  }
20
- export declare enum OtpChallengeOutcome {
21
- Verified = "verified",
22
- Invalid = "invalid",
23
- Exhausted = "exhausted",
24
- Missing = "missing"
25
- }
26
21
  export interface OtpChallengeStore extends InitializedService {
27
22
  issue: (challenge: OtpChallenge, ttlSeconds: number) => Promise<boolean>;
28
23
  verify: (id: string, emailKey: string, codeHash: string, maxFailedAttempts: number) => Promise<OtpChallengeOutcome>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE3D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,sFAAsF;AACtF,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACpG;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,oBAAY,mBAAmB;IAC7B,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,KAAK,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACxE,MAAM,EAAE,CACN,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,KACtE,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,GAAG,CAAC,EAAE;QACJ,yEAAyE;QACzE,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,sEAAsE;QACtE,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,sEAAsE;QACtE,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;QACvC,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAG"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,sFAAsF;AACtF,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACpG;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,KAAK,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACxE,MAAM,EAAE,CACN,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,KACtE,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,GAAG,CAAC,EAAE;QACJ,yEAAyE;QACzE,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,sEAAsE;QACtE,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,sEAAsE;QACtE,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;QACvC,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAG"}
package/build/types.js CHANGED
@@ -1,8 +1,2 @@
1
- export var OtpChallengeOutcome;
2
- (function (OtpChallengeOutcome) {
3
- OtpChallengeOutcome["Verified"] = "verified";
4
- OtpChallengeOutcome["Invalid"] = "invalid";
5
- OtpChallengeOutcome["Exhausted"] = "exhausted";
6
- OtpChallengeOutcome["Missing"] = "missing";
7
- })(OtpChallengeOutcome || (OtpChallengeOutcome = {}));
1
+ export {};
8
2
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,mBAKX;AALD,WAAY,mBAAmB;IAC7B,4CAAqB,CAAA;IACrB,0CAAmB,CAAA;IACnB,8CAAuB,CAAA;IACvB,0CAAmB,CAAA;AACrB,CAAC,EALW,mBAAmB,KAAnB,mBAAmB,QAK9B"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { OtpChallenge } from './types.js';
2
+ import type { ResourceRecord } from '@owlmeans/resource';
3
+ export type Clock = () => number;
4
+ export type StoredChallenge = OtpChallenge & {
5
+ failedAttempts: number;
6
+ expiresAt: number;
7
+ };
8
+ export interface ChallengeResourceRecord extends ResourceRecord {
9
+ id: string;
10
+ }
11
+ export interface ThrottleResourceRecord extends ResourceRecord {
12
+ id: string;
13
+ }
14
+ //# sourceMappingURL=types.local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.local.d.ts","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,MAAM,MAAM,KAAK,GAAG,MAAM,MAAM,CAAA;AAEhC,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1F,MAAM,WAAW,uBAAwB,SAAQ,cAAc;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AAE9E,MAAM,WAAW,sBAAuB,SAAQ,cAAc;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.local.js","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-auth-otp",
3
- "version": "0.1.18-rc.51",
3
+ "version": "0.1.18-rc.52",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,22 +22,22 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
- "@owlmeans/auth": "^0.1.18-rc.38",
26
- "@owlmeans/auth-otp": "^0.1.18-rc.32",
27
- "@owlmeans/context": "^0.1.18-rc.32",
28
- "@owlmeans/error": "^0.1.18-rc.36",
29
- "@owlmeans/log": "^0.1.18-rc.0",
30
- "@owlmeans/mailer": "^0.1.18-rc.34",
31
- "@owlmeans/oidc": "^0.1.18-rc.53",
32
- "@owlmeans/redis-resource": "^0.1.18-rc.42",
33
- "@owlmeans/resource": "^0.1.18-rc.38",
34
- "@owlmeans/server-auth": "^0.1.18-rc.52",
35
- "@owlmeans/server-auth-identity": "^0.1.18-rc.45",
36
- "@owlmeans/server-context": "^0.1.18-rc.41"
25
+ "@owlmeans/auth": "^0.1.18-rc.39",
26
+ "@owlmeans/auth-otp": "^0.1.18-rc.33",
27
+ "@owlmeans/context": "^0.1.18-rc.33",
28
+ "@owlmeans/error": "^0.1.18-rc.37",
29
+ "@owlmeans/log": "^0.1.18-rc.1",
30
+ "@owlmeans/mailer": "^0.1.18-rc.35",
31
+ "@owlmeans/oidc": "^0.1.18-rc.54",
32
+ "@owlmeans/redis-resource": "^0.1.18-rc.43",
33
+ "@owlmeans/resource": "^0.1.18-rc.39",
34
+ "@owlmeans/server-auth": "^0.1.18-rc.53",
35
+ "@owlmeans/server-auth-identity": "^0.1.18-rc.46",
36
+ "@owlmeans/server-context": "^0.1.18-rc.42"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@owlmeans/dep-config": "workspace:*",
40
- "@types/bun": "^1.4.0",
40
+ "@types/bun": "^1.4.2",
41
41
  "nodemon": "^3.1.14",
42
42
  "typescript": "^7.0.2"
43
43
  },
package/src/challenge.ts CHANGED
@@ -1,15 +1,11 @@
1
1
  import { appendContextual, createService } from '@owlmeans/context'
2
2
  import type { RedisResource } from '@owlmeans/redis-resource'
3
- import type { ResourceRecord } from '@owlmeans/resource'
4
3
  import { OtpUnavailable } from './errors.js'
5
- import { OTP_CHALLENGE_STORE, OTP_RESOURCE } from './consts.js'
6
- import type {
7
- OtpChallenge, OtpChallengeOutcome, OtpChallengeStore, OtpConfig, OtpContext,
8
- } from './types.js'
9
- import { OtpChallengeOutcome as Outcome } from './types.js'
4
+ import { OTP_CHALLENGE_STORE, OTP_RESOURCE, type OtpChallengeOutcome, OtpChallengeOutcome as Outcome } from './consts.js'
5
+ import type { OtpChallengeStore, OtpConfig, OtpContext } from './types.js'
6
+ import { REDIS_VERIFY_SCRIPT } from './consts.local.js'
7
+ import type { ChallengeResourceRecord, Clock, StoredChallenge } from './types.local.js'
10
8
 
11
- type Clock = () => number
12
- type StoredChallenge = OtpChallenge & { failedAttempts: number, expiresAt: number }
13
9
 
14
10
  /** Real in-memory challenge store with synchronous consume/update semantics. */
15
11
  export const makeMemoryOtpChallengeStore = (
@@ -47,30 +43,6 @@ export const makeMemoryOtpChallengeStore = (
47
43
  })
48
44
  }
49
45
 
50
- interface ChallengeResourceRecord extends ResourceRecord { id: string }
51
-
52
- const REDIS_VERIFY_SCRIPT = `
53
- local raw = redis.call('GET', KEYS[1])
54
- if not raw then return 0 end
55
- local record = cjson.decode(raw)
56
- if record.emailKey == ARGV[1] and record.codeHash == ARGV[2] then
57
- redis.call('DEL', KEYS[1])
58
- return 1
59
- end
60
- record.failedAttempts = tonumber(record.failedAttempts or 0) + 1
61
- if record.failedAttempts >= tonumber(ARGV[3]) then
62
- redis.call('DEL', KEYS[1])
63
- return -2
64
- end
65
- local ttl = redis.call('PTTL', KEYS[1])
66
- if ttl <= 0 then
67
- redis.call('DEL', KEYS[1])
68
- return 0
69
- end
70
- redis.call('SET', KEYS[1], cjson.encode(record), 'XX', 'PX', ttl)
71
- return -1
72
- `
73
-
74
46
  /** Redis challenge store: compare, attempt increment, exhaustion, and consume are one operation. */
75
47
  export const makeRedisOtpChallengeStore = (
76
48
  alias = OTP_CHALLENGE_STORE, resourceAlias = OTP_RESOURCE
@@ -0,0 +1,51 @@
1
+ export const REDIS_VERIFY_SCRIPT = `
2
+ local raw = redis.call('GET', KEYS[1])
3
+ if not raw then return 0 end
4
+ local record = cjson.decode(raw)
5
+ if record.emailKey == ARGV[1] and record.codeHash == ARGV[2] then
6
+ redis.call('DEL', KEYS[1])
7
+ return 1
8
+ end
9
+ record.failedAttempts = tonumber(record.failedAttempts or 0) + 1
10
+ if record.failedAttempts >= tonumber(ARGV[3]) then
11
+ redis.call('DEL', KEYS[1])
12
+ return -2
13
+ end
14
+ local ttl = redis.call('PTTL', KEYS[1])
15
+ if ttl <= 0 then
16
+ redis.call('DEL', KEYS[1])
17
+ return 0
18
+ end
19
+ redis.call('SET', KEYS[1], cjson.encode(record), 'XX', 'PX', ttl)
20
+ return -1
21
+ `
22
+
23
+ // Separates the email from the opaque issuance id inside the signed challenge.
24
+ export const CHALLENGE_DELIMITER = '::'
25
+
26
+ export const REDIS_THROTTLE_SCRIPT = `
27
+ local time = redis.call('TIME')
28
+ local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)
29
+ local retry = 0
30
+ for index = 1, #KEYS do
31
+ local offset = (index - 1) * 2
32
+ local limit = tonumber(ARGV[offset + 1])
33
+ local window = tonumber(ARGV[offset + 2])
34
+ redis.call('ZREMRANGEBYSCORE', KEYS[index], '-inf', now - window)
35
+ local count = redis.call('ZCARD', KEYS[index])
36
+ if count >= limit then
37
+ local oldest = redis.call('ZRANGE', KEYS[index], 0, 0, 'WITHSCORES')
38
+ if #oldest == 2 then
39
+ retry = math.max(retry, math.ceil((tonumber(oldest[2]) + window - now) / 1000))
40
+ end
41
+ end
42
+ end
43
+ if retry > 0 then return {0, retry} end
44
+ local token = ARGV[#KEYS * 2 + 1]
45
+ for index = 1, #KEYS do
46
+ local window = tonumber(ARGV[(index - 1) * 2 + 2])
47
+ redis.call('ZADD', KEYS[index], now, token .. ':' .. index)
48
+ redis.call('PEXPIRE', KEYS[index], window)
49
+ end
50
+ return {1, 0}
51
+ `
package/src/consts.ts CHANGED
@@ -12,3 +12,10 @@ export {
12
12
  OTP_AUTH_TYPE, OTP_SERVICE, OTP_RESOURCE, OTP_TTL_SECONDS, OTP_CODE_LENGTH,
13
13
  OTP_MAX_FAILED_ATTEMPTS,
14
14
  } from '@owlmeans/auth-otp'
15
+
16
+ export enum OtpChallengeOutcome {
17
+ Verified = 'verified',
18
+ Invalid = 'invalid',
19
+ Exhausted = 'exhausted',
20
+ Missing = 'missing',
21
+ }
package/src/plugin.ts CHANGED
@@ -1,14 +1,9 @@
1
1
  import { ALL_SCOPES, AuthenFailed, AuthRole, AuthenticationType } from '@owlmeans/auth'
2
- import type { AuthPlugin } from '@owlmeans/server-auth/manager/plugins'
3
- import { AuthChallengeReplayPolicy, registerPlugin } from '@owlmeans/server-auth/manager/plugins'
4
- import type { OtpService } from '@owlmeans/auth-otp'
5
- import { OTP_AUTH_TYPE, OTP_SERVICE } from '@owlmeans/auth-otp'
6
- import type { IdentityLinkingService } from '@owlmeans/server-auth-identity'
7
- import { AUTH_IDENTITY_LINKING } from '@owlmeans/server-auth-identity'
2
+ import { type AuthPlugin, AuthChallengeReplayPolicy, registerPlugin } from '@owlmeans/server-auth/manager/plugins'
3
+ import { type OtpService, OTP_AUTH_TYPE, OTP_SERVICE } from '@owlmeans/auth-otp'
4
+ import { type IdentityLinkingService, AUTH_IDENTITY_LINKING } from '@owlmeans/server-auth-identity'
8
5
  import type { OtpConfig, OtpContext } from './types.js'
9
-
10
- // Separates the email from the opaque issuance id inside the signed challenge.
11
- const CHALLENGE_DELIMITER = '::'
6
+ import { CHALLENGE_DELIMITER } from './consts.local.js'
12
7
 
13
8
  /** Factory that creates the email-OTP AuthPlugin bound to the given context. */
14
9
  const otpPlugin = <C extends OtpConfig, T extends OtpContext<C>>(context: T): AuthPlugin => ({
package/src/service.ts CHANGED
@@ -1,16 +1,10 @@
1
1
  import { appendContextual } from '@owlmeans/context'
2
2
  import { AuthenFailed } from '@owlmeans/auth'
3
- import type { OtpService } from '@owlmeans/auth-otp'
4
- import {
5
- OTP_SERVICE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS,
6
- OTP_RESOURCE,
7
- } from '@owlmeans/auth-otp'
8
- import type { MailerService } from '@owlmeans/mailer'
9
- import { MAILER_SERVICE } from '@owlmeans/mailer'
3
+ import { type OtpService, OTP_SERVICE, OTP_TTL_SECONDS, OTP_CODE_LENGTH, OTP_MAX_FAILED_ATTEMPTS, OTP_RESOURCE } from '@owlmeans/auth-otp'
4
+ import { type MailerService, MAILER_SERVICE } from '@owlmeans/mailer'
10
5
  import { createHash, randomBytes, randomInt } from 'node:crypto'
11
6
  import type { AuthThrottleService, OtpChallengeStore, OtpConfig, OtpContext } from './types.js'
12
- import { OtpChallengeOutcome } from './types.js'
13
- import { OTP_CHALLENGE_STORE } from './consts.js'
7
+ import { OtpChallengeOutcome, OTP_CHALLENGE_STORE } from './consts.js'
14
8
  import { emailThrottleKey } from './throttle.js'
15
9
  import { OtpThrottled, OtpUnavailable } from './errors.js'
16
10
  import { makeRedisOtpChallengeStore } from './challenge.js'
package/src/throttle.ts CHANGED
@@ -1,13 +1,11 @@
1
1
  import { createHash, randomBytes } from 'node:crypto'
2
- import { createService } from '@owlmeans/context'
2
+ import { createService, appendContextual } from '@owlmeans/context'
3
3
  import type { RedisResource } from '@owlmeans/redis-resource'
4
- import type { ResourceRecord } from '@owlmeans/resource'
5
- import { appendContextual } from '@owlmeans/context'
6
4
  import { OtpUnavailable } from './errors.js'
7
5
  import type { AuthThrottleService, OtpConfig, OtpContext, ThrottleDecision, ThrottleRule } from './types.js'
8
6
  import { OTP_RESOURCE, OTP_THROTTLE_SERVICE } from './consts.js'
9
-
10
- type Clock = () => number
7
+ import { REDIS_THROTTLE_SCRIPT } from './consts.local.js'
8
+ import type { Clock, ThrottleResourceRecord } from './types.local.js'
11
9
 
12
10
  const digestKey = (kind: string, value: string): string =>
13
11
  createHash('sha256').update(`owlmeans:throttle:${kind}\0${value}`).digest('hex')
@@ -57,35 +55,6 @@ export const makeMemoryThrottleService = (
57
55
  })
58
56
  }
59
57
 
60
- interface ThrottleResourceRecord extends ResourceRecord { id: string }
61
-
62
- const REDIS_THROTTLE_SCRIPT = `
63
- local time = redis.call('TIME')
64
- local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)
65
- local retry = 0
66
- for index = 1, #KEYS do
67
- local offset = (index - 1) * 2
68
- local limit = tonumber(ARGV[offset + 1])
69
- local window = tonumber(ARGV[offset + 2])
70
- redis.call('ZREMRANGEBYSCORE', KEYS[index], '-inf', now - window)
71
- local count = redis.call('ZCARD', KEYS[index])
72
- if count >= limit then
73
- local oldest = redis.call('ZRANGE', KEYS[index], 0, 0, 'WITHSCORES')
74
- if #oldest == 2 then
75
- retry = math.max(retry, math.ceil((tonumber(oldest[2]) + window - now) / 1000))
76
- end
77
- end
78
- end
79
- if retry > 0 then return {0, retry} end
80
- local token = ARGV[#KEYS * 2 + 1]
81
- for index = 1, #KEYS do
82
- local window = tonumber(ARGV[(index - 1) * 2 + 2])
83
- redis.call('ZADD', KEYS[index], now, token .. ':' .. index)
84
- redis.call('PEXPIRE', KEYS[index], window)
85
- end
86
- return {1, 0}
87
- `
88
-
89
58
  /** Redis implementation: every configured window is checked and consumed in one Lua operation. */
90
59
  export const makeRedisThrottleService = (
91
60
  alias = OTP_THROTTLE_SERVICE, resourceAlias = OTP_RESOURCE
@@ -0,0 +1,10 @@
1
+ import type { OtpChallenge } from './types.js'
2
+ import type { ResourceRecord } from '@owlmeans/resource'
3
+
4
+ export type Clock = () => number
5
+
6
+ export type StoredChallenge = OtpChallenge & { failedAttempts: number, expiresAt: number }
7
+
8
+ export interface ChallengeResourceRecord extends ResourceRecord { id: string }
9
+
10
+ export interface ThrottleResourceRecord extends ResourceRecord { id: string }
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
2
2
  import type { InitializedService } from '@owlmeans/context'
3
+ import { OtpChallengeOutcome } from './consts.js'
3
4
 
4
5
  export interface ThrottleRule {
5
6
  limit: number
@@ -22,13 +23,6 @@ export interface OtpChallenge {
22
23
  codeHash: string
23
24
  }
24
25
 
25
- export enum OtpChallengeOutcome {
26
- Verified = 'verified',
27
- Invalid = 'invalid',
28
- Exhausted = 'exhausted',
29
- Missing = 'missing',
30
- }
31
-
32
26
  export interface OtpChallengeStore extends InitializedService {
33
27
  issue: (challenge: OtpChallenge, ttlSeconds: number) => Promise<boolean>
34
28
  verify: (