@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.
- package/README.md +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-auth/SKILL.md +1 -1
- package/build/actions/service.d.ts.map +1 -1
- package/build/actions/service.js.map +1 -1
- package/build/actions/types.local.d.ts +5 -0
- package/build/actions/types.local.d.ts.map +1 -0
- package/build/actions/types.local.js +2 -0
- package/build/actions/types.local.js.map +1 -0
- package/build/manager/consts.local.d.ts +2 -0
- package/build/manager/consts.local.d.ts.map +1 -0
- package/build/manager/consts.local.js +2 -0
- package/build/manager/consts.local.js.map +1 -0
- package/build/manager/entrypoints.d.ts +1 -1
- package/build/manager/entrypoints.d.ts.map +1 -1
- package/build/manager/model.d.ts.map +1 -1
- package/build/manager/model.js +66 -43
- package/build/manager/model.js.map +1 -1
- package/build/manager/plugins/basic-ed25519.js +1 -1
- package/build/manager/plugins/basic-ed25519.js.map +1 -1
- package/build/manager/plugins/basic-rely.d.ts.map +1 -1
- package/build/manager/plugins/basic-rely.js +5 -2
- package/build/manager/plugins/basic-rely.js.map +1 -1
- package/build/manager/plugins/re-captcha.js +1 -1
- package/build/manager/plugins/re-captcha.js.map +1 -1
- package/build/manager/plugins/supervisor.d.ts +1 -2
- package/build/manager/plugins/supervisor.d.ts.map +1 -1
- package/build/manager/plugins/supervisor.js +1 -1
- package/build/manager/plugins/supervisor.js.map +1 -1
- package/build/manager/rely/flow.d.ts.map +1 -1
- package/build/manager/rely/flow.js +7 -5
- package/build/manager/rely/flow.js.map +1 -1
- package/build/manager/rely.d.ts.map +1 -1
- package/build/manager/rely.js.map +1 -1
- package/build/manager/supervisor.d.ts +1 -42
- package/build/manager/supervisor.d.ts.map +1 -1
- package/build/manager/supervisor.js +1 -1
- package/build/manager/supervisor.js.map +1 -1
- package/build/manager/types.d.ts +41 -1
- package/build/manager/types.d.ts.map +1 -1
- package/build/manager/types.local.d.ts +4 -0
- package/build/manager/types.local.d.ts.map +1 -0
- package/build/manager/types.local.js +2 -0
- package/build/manager/types.local.js.map +1 -0
- package/build/service.d.ts +2 -3
- package/build/service.d.ts.map +1 -1
- package/build/service.js +18 -7
- package/build/service.js.map +1 -1
- package/build/types.local.d.ts +4 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/package.json +32 -31
- package/src/actions/service.ts +1 -4
- package/src/actions/types.local.ts +6 -0
- package/src/manager/README.md +1 -1
- package/src/manager/consts.local.ts +1 -0
- package/src/manager/model.ts +77 -54
- package/src/manager/plugins/basic-ed25519.ts +1 -1
- package/src/manager/plugins/basic-rely.ts +6 -2
- package/src/manager/plugins/re-captcha.ts +1 -1
- package/src/manager/plugins/supervisor.ts +3 -5
- package/src/manager/rely/flow.ts +8 -5
- package/src/manager/rely.ts +2 -5
- package/src/manager/supervisor.ts +2 -49
- package/src/manager/types.local.ts +5 -0
- package/src/manager/types.ts +46 -1
- package/src/service.ts +25 -19
- package/src/types.local.ts +5 -0
package/src/manager/rely.ts
CHANGED
|
@@ -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
|
package/src/manager/types.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
15
|
-
import {
|
|
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 {
|
|
16
|
+
import { logger } from '@owlmeans/log'
|
|
17
|
+
import type { Config, Context } from './types.local.js'
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|