@owlmeans/server-auth-otp 0.1.7 → 0.1.8

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 ADDED
@@ -0,0 +1,45 @@
1
+ # @owlmeans/server-auth-otp
2
+
3
+ Email OTP `AuthPlugin` for OwlMeans servers — passwordless login via time-limited one-time codes.
4
+
5
+ ## Overview
6
+
7
+ - `makeOtpPlugin(context)` — factory for the `AuthPlugin` that handles `OTP_AUTH_TYPE` authentication requests
8
+ - `OtpService` — issues email challenges and verifies submitted codes; backed by `@owlmeans/auth-otp`
9
+ - Integrates with `@owlmeans/server-auth` plugin registry — plugs in alongside other auth strategies
10
+ - Resolves identities through `@owlmeans/server-auth-identity` after OTP verification
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ bun add @owlmeans/server-auth-otp
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```typescript
21
+ import { makeOtpPlugin, OTP_SERVICE } from '@owlmeans/server-auth-otp'
22
+ import { registerPlugin } from '@owlmeans/server-auth/manager/plugins'
23
+
24
+ // Register in a server context that already has an OtpService wired
25
+ registerPlugin(context, makeOtpPlugin(context))
26
+ ```
27
+
28
+ The OTP service must be backed by a transport (e.g. `@owlmeans/mailer` → `@owlmeans/server-mailer-mailgun`) that can deliver the one-time code.
29
+
30
+ <!-- owlmeans:agent-guidance:start -->
31
+ ## Agent guidance
32
+
33
+ This package ships embedded Claude Code skills and GitHub Copilot instructions under
34
+ `agent-meta/`. After installing your `@owlmeans/*` packages, run the OwlMeans
35
+ agent-skills installer to place them into your project's native locations
36
+ (`.claude/skills/` and `.github/instructions/`):
37
+
38
+ ```sh
39
+ npx @owlmeans/agent-skills
40
+ ```
41
+
42
+ The embedded files are version-matched to this package release. Do not edit them
43
+ directly — they are regenerated on each publish. To contribute guidance edits,
44
+ open a PR against the source monorepo.
45
+ <!-- owlmeans:agent-guidance:end -->
@@ -0,0 +1,83 @@
1
+ ---
2
+ description: "How to use @owlmeans/server-auth-otp — email OTP AuthPlugin and OtpService. Use when wiring passwordless email login in an OwlMeans server context."
3
+ applyTo: "**/context.ts, **/app/auth/*, **/services/otp*"
4
+ ---
5
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
6
+
7
+ # Using `@owlmeans/server-auth-otp`
8
+
9
+ 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.
10
+
11
+ ## Public API surface
12
+
13
+ | Symbol | Kind | Purpose |
14
+ |--------|------|---------|
15
+ | `makeOtpService(alias?)` | fn | Service factory — stores/verifies OTP codes |
16
+ | `appendOtpPlugin(context)` | fn | Registers the OTP `AuthPlugin` into the server-auth plugin registry |
17
+ | `OTP_AUTH_TYPE` | const | `'email-otp'` — the auth type string to pass in `init` requests |
18
+ | `OTP_RESOURCE` | const | Redis resource alias for code storage |
19
+ | `OTP_TTL_SECONDS` | const | Code TTL (600 s = 10 min) |
20
+ | `OTP_CODE_LENGTH` | const | 6 |
21
+
22
+ ## Registration requirements
23
+
24
+ ```ts
25
+ import { makeOtpService, appendOtpPlugin, OTP_RESOURCE } from '@owlmeans/server-auth-otp'
26
+ import { makeRedisResource } from '@owlmeans/redis-resource'
27
+ import { makeConsoleMailerService, CONSOLE_MAILER, MAILER_SERVICE } from '@owlmeans/mailer'
28
+ import { makeMailgunMailerService } from '@owlmeans/server-mailer-mailgun'
29
+
30
+ // 1. Register the Redis code-cache resource.
31
+ context.registerResource(makeRedisResource(OTP_RESOURCE))
32
+
33
+ // 2. Register a MailerService (console for dev/tests, Mailgun for prod).
34
+ context.registerService(makeConsoleMailerService(MAILER_SERVICE))
35
+ // or:
36
+ context.registerService(makeMailgunMailerService(MAILER_SERVICE))
37
+
38
+ // 3. Register the OTP service (reads from Redis + Mailer).
39
+ context.registerService(makeOtpService())
40
+
41
+ // 4. Register the OTP AuthPlugin into the auth-manager plugin registry.
42
+ appendOtpPlugin(context)
43
+ ```
44
+
45
+ ## Auth flow
46
+
47
+ **Init** — client sends `{ type: 'email-otp', userId: 'user@email.com' }`:
48
+ - OTP service generates a 6-digit code, stores it in Redis with 10 min TTL, emails it.
49
+ - Returns `{ challenge: email }` in a signed envelope.
50
+
51
+ **Authenticate** — client sends `{ challenge: <signed-envelope>, userId: email, credential: '123456', entityId: 'the-entity' }`:
52
+ - Envelope is opened → email is extracted.
53
+ - OTP service verifies the code (throws `AuthenFailed` if wrong or expired), then deletes it.
54
+ - `IdentityLinkingService` finds or creates the user profile scoped to `entityId`.
55
+ - Sets `credential.type = AuthenticationType.OneTimeToken` and returns the signed auth token.
56
+
57
+ ## Config overrides (optional)
58
+
59
+ Pass `ctx.cfg.otp` to override defaults:
60
+
61
+ ```ts
62
+ cfg.otp = {
63
+ mailerAlias: 'my-mailer', // default: MAILER_SERVICE ('mailer-service')
64
+ resourceAlias: 'my-otp-cache', // default: OTP_RESOURCE ('auth-otp-cache')
65
+ identityAlias: 'my-identity', // default: AUTH_IDENTITY_LINKING
66
+ }
67
+ ```
68
+
69
+ ## Rules
70
+
71
+ - Always register the Redis resource AND the mailer service BEFORE the OTP service.
72
+ - Call `appendOtpPlugin(context)` once per context — it adds to the shared plugin registry singleton.
73
+ - The `credential.entityId` in the authenticate request determines which entity the resulting identity profile is scoped to. Pass it from the OIDC interaction.
74
+ - Errors from this plugin are `AuthenFailed` (from `@owlmeans/auth`) — callers catch that, not raw `Error`.
75
+ - For tests, use `makeConsoleMailerService()` and read `svc.captured[n].text` to extract the code.
76
+
77
+ ## Related instructions
78
+
79
+ - `@owlmeans/auth-otp` (common) — `OtpService` interface and constants
80
+ - `@owlmeans/mailer` (common) — `MailerService` interface, console transport
81
+ - `@owlmeans/server-mailer-mailgun` (common) — production Mailgun transport
82
+ - `@owlmeans/server-auth` (common) — auth-manager plugin system
83
+ - `auth-protocol` instructions — error hierarchy, identity read rules
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "package": "@owlmeans/server-auth-otp",
4
+ "version": "0.1.8",
5
+ "generatedAt": "2026-06-11T16:30:27.191Z",
6
+ "canonicalRepo": "https://github.com/owlmeans/common",
7
+ "entries": [
8
+ {
9
+ "kind": "instruction",
10
+ "name": "server-auth-otp",
11
+ "category": "package-specific",
12
+ "file": "instructions/server-auth-otp.instructions.md",
13
+ "canonicalPath": ".github/instructions/server-auth-otp.instructions.md"
14
+ }
15
+ ]
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-auth-otp",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,17 +22,17 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
- "@owlmeans/auth": "^0.1.7",
26
- "@owlmeans/auth-otp": "^0.1.7",
27
- "@owlmeans/basic-ids": "^0.1.7",
28
- "@owlmeans/context": "^0.1.7",
29
- "@owlmeans/mailer": "^0.1.7",
30
- "@owlmeans/oidc": "^0.1.7",
31
- "@owlmeans/redis-resource": "^0.1.7",
32
- "@owlmeans/resource": "^0.1.7",
33
- "@owlmeans/server-auth": "^0.1.7",
34
- "@owlmeans/server-auth-identity": "^0.1.7",
35
- "@owlmeans/server-context": "^0.1.7"
25
+ "@owlmeans/auth": "^0.1.8",
26
+ "@owlmeans/auth-otp": "^0.1.8",
27
+ "@owlmeans/basic-ids": "^0.1.8",
28
+ "@owlmeans/context": "^0.1.8",
29
+ "@owlmeans/mailer": "^0.1.8",
30
+ "@owlmeans/oidc": "^0.1.8",
31
+ "@owlmeans/redis-resource": "^0.1.8",
32
+ "@owlmeans/resource": "^0.1.8",
33
+ "@owlmeans/server-auth": "^0.1.8",
34
+ "@owlmeans/server-auth-identity": "^0.1.8",
35
+ "@owlmeans/server-context": "^0.1.8"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@owlmeans/dep-config": "workspace:*",