@owlmeans/server-auth 0.1.18-rc.51 → 0.1.18-rc.53

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 (69) hide show
  1. package/README.md +2 -2
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/server-auth/SKILL.md +1 -1
  4. package/build/actions/service.d.ts.map +1 -1
  5. package/build/actions/service.js.map +1 -1
  6. package/build/actions/types.local.d.ts +5 -0
  7. package/build/actions/types.local.d.ts.map +1 -0
  8. package/build/actions/types.local.js +2 -0
  9. package/build/actions/types.local.js.map +1 -0
  10. package/build/manager/consts.local.d.ts +2 -0
  11. package/build/manager/consts.local.d.ts.map +1 -0
  12. package/build/manager/consts.local.js +2 -0
  13. package/build/manager/consts.local.js.map +1 -0
  14. package/build/manager/entrypoints.d.ts +1 -1
  15. package/build/manager/entrypoints.d.ts.map +1 -1
  16. package/build/manager/model.d.ts.map +1 -1
  17. package/build/manager/model.js +66 -43
  18. package/build/manager/model.js.map +1 -1
  19. package/build/manager/plugins/basic-ed25519.js +1 -1
  20. package/build/manager/plugins/basic-ed25519.js.map +1 -1
  21. package/build/manager/plugins/basic-rely.d.ts.map +1 -1
  22. package/build/manager/plugins/basic-rely.js +5 -2
  23. package/build/manager/plugins/basic-rely.js.map +1 -1
  24. package/build/manager/plugins/re-captcha.js +1 -1
  25. package/build/manager/plugins/re-captcha.js.map +1 -1
  26. package/build/manager/plugins/supervisor.d.ts +1 -2
  27. package/build/manager/plugins/supervisor.d.ts.map +1 -1
  28. package/build/manager/plugins/supervisor.js +1 -1
  29. package/build/manager/plugins/supervisor.js.map +1 -1
  30. package/build/manager/rely/flow.d.ts.map +1 -1
  31. package/build/manager/rely/flow.js +7 -5
  32. package/build/manager/rely/flow.js.map +1 -1
  33. package/build/manager/rely.d.ts.map +1 -1
  34. package/build/manager/rely.js.map +1 -1
  35. package/build/manager/supervisor.d.ts +1 -42
  36. package/build/manager/supervisor.d.ts.map +1 -1
  37. package/build/manager/supervisor.js +1 -1
  38. package/build/manager/supervisor.js.map +1 -1
  39. package/build/manager/types.d.ts +41 -1
  40. package/build/manager/types.d.ts.map +1 -1
  41. package/build/manager/types.local.d.ts +4 -0
  42. package/build/manager/types.local.d.ts.map +1 -0
  43. package/build/manager/types.local.js +2 -0
  44. package/build/manager/types.local.js.map +1 -0
  45. package/build/service.d.ts +2 -3
  46. package/build/service.d.ts.map +1 -1
  47. package/build/service.js +18 -7
  48. package/build/service.js.map +1 -1
  49. package/build/types.local.d.ts +4 -0
  50. package/build/types.local.d.ts.map +1 -0
  51. package/build/types.local.js +2 -0
  52. package/build/types.local.js.map +1 -0
  53. package/package.json +32 -31
  54. package/src/actions/service.ts +1 -4
  55. package/src/actions/types.local.ts +6 -0
  56. package/src/manager/README.md +1 -1
  57. package/src/manager/consts.local.ts +1 -0
  58. package/src/manager/model.ts +77 -54
  59. package/src/manager/plugins/basic-ed25519.ts +1 -1
  60. package/src/manager/plugins/basic-rely.ts +6 -2
  61. package/src/manager/plugins/re-captcha.ts +1 -1
  62. package/src/manager/plugins/supervisor.ts +3 -5
  63. package/src/manager/rely/flow.ts +8 -5
  64. package/src/manager/rely.ts +2 -5
  65. package/src/manager/supervisor.ts +2 -49
  66. package/src/manager/types.local.ts +5 -0
  67. package/src/manager/types.ts +46 -1
  68. package/src/service.ts +25 -19
  69. package/src/types.local.ts +5 -0
@@ -1,18 +1,15 @@
1
1
  import { assertContext, createService } from '@owlmeans/context'
2
2
  import { DEFAULT_RELY } from './consts.js'
3
3
  import type { AppContext, RelyService } from './types.js'
4
- import { AUTH_QUERY, AuthenFailed, AuthenticationType } from '@owlmeans/auth'
5
- import type { Auth, AuthCredentials, AuthToken } from '@owlmeans/auth'
4
+ import { AUTH_QUERY, AuthenFailed, AuthenticationType, type Auth, type AuthCredentials, type AuthToken } from '@owlmeans/auth'
6
5
  import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint'
7
6
  import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope'
8
- import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
9
7
  import { AUTH_CACHE, AUTHEN_TIMEFRAME } from '../consts.js'
10
8
  import type { AuthSpent } from '../types.js'
11
9
  import type { Resource } from '@owlmeans/resource'
12
10
  import { trusted } from './utils/trusted.js'
11
+ import type { Config, Context } from './types.local.js'
13
12
 
14
- type Config = ServerConfig
15
- type Context = ServerContext<Config>
16
13
 
17
14
  export const createRelyService = (alias: string = DEFAULT_RELY): RelyService => {
18
15
  const _keyPair = async (context: Context) => {
@@ -1,56 +1,9 @@
1
1
  import { AuthenticationType } from '@owlmeans/auth'
2
- import type { AuthPayload } from '@owlmeans/auth'
3
2
  import { DEFAULT_GUARD } from '@owlmeans/auth-common'
4
- import type { AppConfig, AppContext } from './types.js'
3
+ import type { AppConfig, AppContext, SupervisorAuthOptions, SupervisorPluginOptions } from './types.js'
5
4
  import { registerPlugin } from './plugins/index.js'
6
5
  import { makeSupervisorPlugin } from './plugins/supervisor.js'
7
-
8
- /**
9
- * What a `SupervisorUserResolver` returns: the identity the supervisor-minted
10
- * token will represent. Only `userId` is required - the rest default sensibly.
11
- */
12
- export interface SupervisorUserResolution extends Partial<Pick<AuthPayload,
13
- 'profileId' | 'entitySlug' | 'role' | 'scopes'>> {
14
- userId: string
15
- }
16
-
17
- /**
18
- * Find-or-create the target identity for a supervisor login. `register` reflects
19
- * `allowRegistration`; when false the resolver should only look existing users up.
20
- * Wire this to the project's identity store (e.g. `@owlmeans/server-auth-identity`).
21
- */
22
- export interface SupervisorUserResolver {
23
- <C extends AppConfig, T extends AppContext<C>>(
24
- userId: string, context: T, opts: { register: boolean }
25
- ): Promise<SupervisorUserResolution>
26
- }
27
-
28
- /** Resolved options handed to the plugin factory. */
29
- export interface SupervisorPluginOptions {
30
- supervisors: string[]
31
- allowRegistration: boolean
32
- resolveUser?: SupervisorUserResolver
33
- }
34
-
35
- export interface SupervisorAuthOptions {
36
- /** Trusted-record aliases authorized to act as supervisor. Default: master + superuser. */
37
- supervisors?: string[]
38
- /** Find-or-create the target user by id/email. Default: trust the id as-is. */
39
- resolveUser?: SupervisorUserResolver
40
- /** Allow minting a token for an unknown user (registration). Default: true. */
41
- allowRegistration?: boolean
42
- /** Force enable/disable. Default: development only (cfg.debug.all || cfg.debug.supervisor). */
43
- enabled?: boolean
44
- /**
45
- * Also accept internal owlmeans `Ed25519BasicToken`s even when another guard
46
- * (e.g. OIDC) is the primary guard on protected entrypoints. Default: true.
47
- */
48
- acceptInternalTokens?: boolean
49
- /** The internal-token guard to add as a coguard. Default: DEFAULT_GUARD ('auth'). */
50
- guard?: string
51
- }
52
-
53
- const DEFAULT_SUPERVISORS = ['master', 'superuser']
6
+ import { DEFAULT_SUPERVISORS } from './consts.local.js'
54
7
 
55
8
  const isDevelopment = (context: { cfg: { debug?: { all?: boolean, supervisor?: boolean } } }): boolean =>
56
9
  context.cfg.debug?.all === true || context.cfg.debug?.supervisor === true
@@ -0,0 +1,5 @@
1
+ import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
2
+
3
+ export type Config = ServerConfig
4
+
5
+ export type Context = ServerContext<Config>
@@ -1,4 +1,4 @@
1
- import type { AllowanceRequest, AllowanceResponse, Auth, AuthCredentials, AuthToken, RelyToken } from '@owlmeans/auth'
1
+ import type { AllowanceRequest, AllowanceResponse, Auth, AuthCredentials, AuthToken, RelyToken, AuthPayload } from '@owlmeans/auth'
2
2
  import type { KlusterConfig } from '@owlmeans/kluster'
3
3
  import type { GuardService } from '@owlmeans/entrypoint'
4
4
  import type { ApiServerAppend } from '@owlmeans/server-api'
@@ -40,3 +40,48 @@ export interface RelyCarrier {
40
40
  source: RelyToken,
41
41
  rely: RelyToken
42
42
  }
43
+
44
+ /**
45
+ * What a `SupervisorUserResolver` returns: the identity the supervisor-minted
46
+ * token will represent. Only `userId` is required - the rest default sensibly.
47
+ */
48
+ export interface SupervisorUserResolution extends Partial<Pick<AuthPayload,
49
+ 'profileId' | 'entitySlug' | 'role' | 'scopes'>> {
50
+ userId: string
51
+ }
52
+
53
+ /**
54
+ * Find-or-create the target identity for a supervisor login. `register` reflects
55
+ * `allowRegistration`; when false the resolver should only look existing users up.
56
+ * Wire this to the project's identity store (e.g. `@owlmeans/server-auth-identity`).
57
+ */
58
+ export interface SupervisorUserResolver {
59
+ <C extends AppConfig, T extends AppContext<C>>(
60
+ userId: string, context: T, opts: { register: boolean }
61
+ ): Promise<SupervisorUserResolution>
62
+ }
63
+
64
+ /** Resolved options handed to the plugin factory. */
65
+ export interface SupervisorPluginOptions {
66
+ supervisors: string[]
67
+ allowRegistration: boolean
68
+ resolveUser?: SupervisorUserResolver
69
+ }
70
+
71
+ export interface SupervisorAuthOptions {
72
+ /** Trusted-record aliases authorized to act as supervisor. Default: master + superuser. */
73
+ supervisors?: string[]
74
+ /** Find-or-create the target user by id/email. Default: trust the id as-is. */
75
+ resolveUser?: SupervisorUserResolver
76
+ /** Allow minting a token for an unknown user (registration). Default: true. */
77
+ allowRegistration?: boolean
78
+ /** Force enable/disable. Default: development only (cfg.debug.all || cfg.debug.supervisor). */
79
+ enabled?: boolean
80
+ /**
81
+ * Also accept internal owlmeans `Ed25519BasicToken`s even when another guard
82
+ * (e.g. OIDC) is the primary guard on protected entrypoints. Default: true.
83
+ */
84
+ acceptInternalTokens?: boolean
85
+ /** The internal-token guard to add as a coguard. Default: DEFAULT_GUARD ('auth'). */
86
+ guard?: string
87
+ }
package/src/service.ts CHANGED
@@ -1,28 +1,34 @@
1
- import type { ServerContext, ServerConfig } from '@owlmeans/server-context'
1
+ import type { ServerContext } from '@owlmeans/server-context'
2
2
  import { TRUSTED } from '@owlmeans/config'
3
3
  import { AUTH_CACHE, AUTH_SRV_KEY, AUTHEN_TIMEFRAME, DEFAULT_ALIAS } from './consts.js'
4
4
  import type { AuthServiceAppend, AuthService, AuthSpent } from './types.js'
5
5
  import { assertContext, createService } from '@owlmeans/context'
6
6
  import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope'
7
- import type { Auth, AuthCredentials } from '@owlmeans/auth'
8
- import { AuthenFailed, AuthorizationError, AuthroizationType, AuthUnavailable } from '@owlmeans/auth'
7
+ import { type Auth, type AuthCredentials, AuthenFailed, AuthorizationError, AuthroizationType, AuthUnavailable } from '@owlmeans/auth'
9
8
  import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint'
10
9
  import type { Resource } from '@owlmeans/resource'
11
10
  import { createStaticResource } from '@owlmeans/static-resource'
12
11
  import { trust, extractAuthToken } from '@owlmeans/auth-common/utils'
13
- import { ENTITY_RESOLVER } from '@owlmeans/auth-common'
14
- import type { EntityResolverService } from '@owlmeans/auth-common'
15
- import { AUTH_IDENTITY_PROFILE } from '@owlmeans/server-auth-identity'
16
- import type { IdentityProfile, IdentityProfileResource } from '@owlmeans/server-auth-identity'
17
- import {
18
- appendMemoryAuthSessionManager, AUTH_SESSION_MANAGER, AUTH_SESSION_TTL
19
- } from '@owlmeans/server-auth-session'
20
- import type { AuthSessionManager } from '@owlmeans/server-auth-session'
12
+ import { ENTITY_RESOLVER, type EntityResolverService, TOKEN_UPDATE } from '@owlmeans/auth-common'
13
+ import { AUTH_IDENTITY_PROFILE, type IdentityProfile, type IdentityProfileResource } from '@owlmeans/server-auth-identity'
14
+ import { appendMemoryAuthSessionManager, AUTH_SESSION_MANAGER, AUTH_SESSION_TTL, type AuthSessionManager } from '@owlmeans/server-auth-session'
21
15
  import { uuid } from '@owlmeans/basic-ids'
22
- import { TOKEN_UPDATE } from '@owlmeans/auth-common'
16
+ import { logger } from '@owlmeans/log'
17
+ import type { Config, Context } from './types.local.js'
23
18
 
24
- type Config = ServerConfig
25
- type Context = ServerContext<Config>
19
+
20
+ const log = logger('server-auth')
21
+
22
+ /**
23
+ * A refused token exchange — the manager's token presented to open a session. Logged with the
24
+ * reason and the account id only; returns the error for the caller to throw.
25
+ */
26
+ const refuse = (reason: string, error: AuthenFailed, userId?: string): AuthenFailed => {
27
+ const accountId = userId == null ? undefined
28
+ : userId.includes('@') ? `*@${userId.slice(userId.lastIndexOf('@') + 1)}` : userId
29
+ log.warn('Session exchange refused', { reason, ...(accountId != null ? { accountId } : {}) }, { event: 'auth.refused' })
30
+ return error
31
+ }
26
32
 
27
33
  export const makeAuthService = (alias: string = DEFAULT_ALIAS): AuthService => {
28
34
  const location = `server-auth:${alias}`
@@ -152,7 +158,7 @@ export const makeAuthService = (alias: string = DEFAULT_ALIAS): AuthService => {
152
158
 
153
159
  const authService = await trust<Config, Context>(context, TRUSTED, AUTH_SRV_KEY)
154
160
  if (!await envelope.verify(authService.key)) {
155
- throw new AuthenFailed()
161
+ throw refuse('signature', new AuthenFailed())
156
162
  }
157
163
 
158
164
  const credentials = envelope.message()
@@ -163,11 +169,11 @@ export const makeAuthService = (alias: string = DEFAULT_ALIAS): AuthService => {
163
169
  try {
164
170
  await cache(context).create({ id: msg }, { ttl: AUTHEN_TIMEFRAME / 1000 })
165
171
  } catch {
166
- throw new AuthenFailed()
172
+ throw refuse('replay', new AuthenFailed(), credentials.userId)
167
173
  }
168
174
 
169
175
  if (credentials.credential !== authService.user.id) {
170
- throw new AuthenFailed()
176
+ throw refuse('issuer', new AuthenFailed(), credentials.userId)
171
177
  }
172
178
 
173
179
  // @TODO Move to a plugin
@@ -191,12 +197,12 @@ export const makeAuthService = (alias: string = DEFAULT_ALIAS): AuthService => {
191
197
  const manager = sessions(context)
192
198
  if (manager != null) {
193
199
  const entityId = await entityIdFor(context, auth.entitySlug)
194
- if (entityId == null || auth.profileId == null) throw new AuthenFailed('session')
200
+ if (entityId == null || auth.profileId == null) throw refuse('session', new AuthenFailed('session'), auth.userId)
195
201
  const decision = await manager.register({
196
202
  id: auth.sessionId!, kind: 'bearer', entityId, profileId: auth.profileId,
197
203
  issuedAt, expiresAt: expiresAt.getTime()
198
204
  })
199
- if (decision.state !== 'active') throw new AuthenFailed('session')
205
+ if (decision.state !== 'active') throw refuse('session', new AuthenFailed('session'), auth.userId)
200
206
  auth.authorizationVersion = decision.version
201
207
  }
202
208
 
@@ -0,0 +1,5 @@
1
+ import type { ServerContext, ServerConfig } from '@owlmeans/server-context'
2
+
3
+ export type Config = ServerConfig
4
+
5
+ export type Context = ServerContext<Config>