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

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 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.50
15
+ bun add @owlmeans/server-auth-otp@^0.1.18-rc.51
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.46
50
+ npx @owlmeans/agent-skills@^0.1.18-rc.47
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.50",
5
- "generatedAt": "2026-10-03T11:19:50.781Z",
4
+ "version": "0.1.18-rc.51",
5
+ "generatedAt": "2026-10-03T20:05:07.593Z",
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.50"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-auth-otp": "^0.1.18-rc.51"` 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 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAkBpD,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,UAiEpD,CAAA"}
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"}
package/build/service.js CHANGED
@@ -8,6 +8,10 @@ import { OTP_CHALLENGE_STORE } from './consts.js';
8
8
  import { emailThrottleKey } from './throttle.js';
9
9
  import { OtpThrottled, OtpUnavailable } from './errors.js';
10
10
  import { makeRedisOtpChallengeStore } from './challenge.js';
11
+ import { logger, logThrottle } from '@owlmeans/log';
12
+ const log = logger('server-auth-otp');
13
+ /** An e-mail as a log may carry it: its domain only. */
14
+ const domainOf = (email) => email.slice(email.lastIndexOf('@') + 1);
11
15
  const digest = (scope, value) => createHash('sha256').update(`owlmeans:otp:${scope}\0${value}`).digest('hex');
12
16
  export const otpChallengeKey = (issuanceId) => `challenge:${digest('issuance', issuanceId)}`;
13
17
  export const otpEmailKey = (email) => digest('email', email.trim().toLowerCase());
@@ -39,8 +43,14 @@ export const makeOtpService = (alias = OTP_SERVICE) => {
39
43
  if (throttleAlias != null && throttleRules != null) {
40
44
  const decision = await ctx.service(throttleAlias)
41
45
  .consume(emailThrottleKey(email), throttleRules, issuanceId);
42
- if (!decision.allowed)
46
+ if (!decision.allowed) {
47
+ if (logThrottle(`otp-throttled:${otpEmailKey(email)}`, 60_000)) {
48
+ log.warn('Login code refused: throttled', {
49
+ reason: 'otp-throttled', emailDomain: domainOf(email), retryAfter: decision.retryAfter,
50
+ }, { event: 'auth.refused' });
51
+ }
43
52
  throw new OtpThrottled(decision.retryAfter);
53
+ }
44
54
  }
45
55
  const issued = await challenges.issue({
46
56
  id: otpChallengeKey(issuanceId),
@@ -61,6 +71,8 @@ export const makeOtpService = (alias = OTP_SERVICE) => {
61
71
  const ctx = service.ctx;
62
72
  const outcome = await challengeStore(ctx).verify(otpChallengeKey(issuanceId), otpEmailKey(email), otpCodeHash(issuanceId, code), OTP_MAX_FAILED_ATTEMPTS);
63
73
  if (outcome !== OtpChallengeOutcome.Verified) {
74
+ // The sign-in refusal itself (`auth.refused`) is logged where the manager decides sign-in.
75
+ log.debug('OTP challenge refused', { outcome, emailDomain: domainOf(email) });
64
76
  throw new AuthenFailed('otp:code');
65
77
  }
66
78
  },
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-auth-otp",
3
- "version": "0.1.18-rc.50",
3
+ "version": "0.1.18-rc.51",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -26,13 +26,14 @@
26
26
  "@owlmeans/auth-otp": "^0.1.18-rc.32",
27
27
  "@owlmeans/context": "^0.1.18-rc.32",
28
28
  "@owlmeans/error": "^0.1.18-rc.36",
29
- "@owlmeans/mailer": "^0.1.18-rc.33",
30
- "@owlmeans/oidc": "^0.1.18-rc.52",
31
- "@owlmeans/redis-resource": "^0.1.18-rc.41",
32
- "@owlmeans/resource": "^0.1.18-rc.37",
33
- "@owlmeans/server-auth": "^0.1.18-rc.51",
34
- "@owlmeans/server-auth-identity": "^0.1.18-rc.44",
35
- "@owlmeans/server-context": "^0.1.18-rc.40"
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"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@owlmeans/dep-config": "workspace:*",
package/src/service.ts CHANGED
@@ -14,6 +14,12 @@ import { OTP_CHALLENGE_STORE } from './consts.js'
14
14
  import { emailThrottleKey } from './throttle.js'
15
15
  import { OtpThrottled, OtpUnavailable } from './errors.js'
16
16
  import { makeRedisOtpChallengeStore } from './challenge.js'
17
+ import { logger, logThrottle } from '@owlmeans/log'
18
+
19
+ const log = logger('server-auth-otp')
20
+
21
+ /** An e-mail as a log may carry it: its domain only. */
22
+ const domainOf = (email: string): string => email.slice(email.lastIndexOf('@') + 1)
17
23
 
18
24
  const digest = (scope: string, value: string): string =>
19
25
  createHash('sha256').update(`owlmeans:otp:${scope}\0${value}`).digest('hex')
@@ -55,7 +61,14 @@ export const makeOtpService = (alias = OTP_SERVICE): OtpService => {
55
61
  if (throttleAlias != null && throttleRules != null) {
56
62
  const decision = await ctx.service<AuthThrottleService>(throttleAlias)
57
63
  .consume(emailThrottleKey(email), throttleRules, issuanceId)
58
- if (!decision.allowed) throw new OtpThrottled(decision.retryAfter)
64
+ if (!decision.allowed) {
65
+ if (logThrottle(`otp-throttled:${otpEmailKey(email)}`, 60_000)) {
66
+ log.warn('Login code refused: throttled', {
67
+ reason: 'otp-throttled', emailDomain: domainOf(email), retryAfter: decision.retryAfter,
68
+ }, { event: 'auth.refused' })
69
+ }
70
+ throw new OtpThrottled(decision.retryAfter)
71
+ }
59
72
  }
60
73
 
61
74
  const issued = await challenges.issue({
@@ -82,6 +95,8 @@ export const makeOtpService = (alias = OTP_SERVICE): OtpService => {
82
95
  OTP_MAX_FAILED_ATTEMPTS
83
96
  )
84
97
  if (outcome !== OtpChallengeOutcome.Verified) {
98
+ // The sign-in refusal itself (`auth.refused`) is logged where the manager decides sign-in.
99
+ log.debug('OTP challenge refused', { outcome, emailDomain: domainOf(email) })
85
100
  throw new AuthenFailed('otp:code')
86
101
  }
87
102
  },