@furystack/rest-service 13.0.0 → 14.1.0
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/CHANGELOG.md +124 -0
- package/README.md +47 -28
- package/esm/actions/error-action.d.ts +7 -2
- package/esm/actions/error-action.d.ts.map +1 -1
- package/esm/actions/error-action.js +7 -2
- package/esm/actions/error-action.js.map +1 -1
- package/esm/actions/get-current-user.d.ts +1 -4
- package/esm/actions/get-current-user.d.ts.map +1 -1
- package/esm/actions/get-current-user.js +1 -4
- package/esm/actions/get-current-user.js.map +1 -1
- package/esm/actions/get-current-user.spec.js +10 -6
- package/esm/actions/get-current-user.spec.js.map +1 -1
- package/esm/actions/is-authenticated.d.ts +3 -4
- package/esm/actions/is-authenticated.d.ts.map +1 -1
- package/esm/actions/is-authenticated.js +3 -4
- package/esm/actions/is-authenticated.js.map +1 -1
- package/esm/actions/is-authenticated.spec.js +10 -6
- package/esm/actions/is-authenticated.spec.js.map +1 -1
- package/esm/actions/logout-action.spec.js +11 -9
- package/esm/actions/logout-action.spec.js.map +1 -1
- package/esm/actions/logout.d.ts +2 -6
- package/esm/actions/logout.d.ts.map +1 -1
- package/esm/actions/logout.js +3 -7
- package/esm/actions/logout.js.map +1 -1
- package/esm/actions/not-found-action.d.ts +1 -3
- package/esm/actions/not-found-action.d.ts.map +1 -1
- package/esm/actions/not-found-action.js +1 -3
- package/esm/actions/not-found-action.js.map +1 -1
- package/esm/actions/password-login-action.d.ts +5 -12
- package/esm/actions/password-login-action.d.ts.map +1 -1
- package/esm/actions/password-login-action.js +6 -13
- package/esm/actions/password-login-action.js.map +1 -1
- package/esm/actions/password-login-action.spec.js +23 -28
- package/esm/actions/password-login-action.spec.js.map +1 -1
- package/esm/authenticate.d.ts +5 -11
- package/esm/authenticate.d.ts.map +1 -1
- package/esm/authenticate.js +6 -12
- package/esm/authenticate.js.map +1 -1
- package/esm/authenticate.spec.js +41 -33
- package/esm/authenticate.spec.js.map +1 -1
- package/esm/authentication-providers/authentication-provider.d.ts +17 -0
- package/esm/authentication-providers/authentication-provider.d.ts.map +1 -1
- package/esm/authentication-providers/basic-auth-provider.d.ts +7 -0
- package/esm/authentication-providers/basic-auth-provider.d.ts.map +1 -1
- package/esm/authentication-providers/basic-auth-provider.js +7 -0
- package/esm/authentication-providers/basic-auth-provider.js.map +1 -1
- package/esm/authentication-providers/cookie-auth-provider.d.ts.map +1 -1
- package/esm/authentication-providers/cookie-auth-provider.js +8 -0
- package/esm/authentication-providers/cookie-auth-provider.js.map +1 -1
- package/esm/authorize.d.ts +5 -17
- package/esm/authorize.d.ts.map +1 -1
- package/esm/authorize.js +5 -17
- package/esm/authorize.js.map +1 -1
- package/esm/authorize.spec.js +34 -29
- package/esm/authorize.spec.js.map +1 -1
- package/esm/endpoint-generators/create-delete-endpoint.d.ts +6 -11
- package/esm/endpoint-generators/create-delete-endpoint.d.ts.map +1 -1
- package/esm/endpoint-generators/create-delete-endpoint.js +7 -11
- package/esm/endpoint-generators/create-delete-endpoint.js.map +1 -1
- package/esm/endpoint-generators/create-delete-endpoint.spec.js +14 -21
- package/esm/endpoint-generators/create-delete-endpoint.spec.js.map +1 -1
- package/esm/endpoint-generators/create-get-collection-endpoint.d.ts +11 -11
- package/esm/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -1
- package/esm/endpoint-generators/create-get-collection-endpoint.js +13 -12
- package/esm/endpoint-generators/create-get-collection-endpoint.js.map +1 -1
- package/esm/endpoint-generators/create-get-collection-endpoint.spec.js +43 -70
- package/esm/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -1
- package/esm/endpoint-generators/create-get-entity-endpoint.d.ts +6 -11
- package/esm/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -1
- package/esm/endpoint-generators/create-get-entity-endpoint.js +7 -11
- package/esm/endpoint-generators/create-get-entity-endpoint.js.map +1 -1
- package/esm/endpoint-generators/create-get-entity-endpoint.spec.js +16 -33
- package/esm/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -1
- package/esm/endpoint-generators/create-get-openapi-document-action.d.ts +1 -1
- package/esm/endpoint-generators/create-get-openapi-document-action.d.ts.map +1 -1
- package/esm/endpoint-generators/create-get-openapi-document-action.js +1 -1
- package/esm/endpoint-generators/create-get-openapi-document-action.js.map +1 -1
- package/esm/endpoint-generators/create-get-schema-action.d.ts +1 -1
- package/esm/endpoint-generators/create-get-schema-action.d.ts.map +1 -1
- package/esm/endpoint-generators/create-get-schema-action.js.map +1 -1
- package/esm/endpoint-generators/create-patch-endpoint.d.ts +7 -13
- package/esm/endpoint-generators/create-patch-endpoint.d.ts.map +1 -1
- package/esm/endpoint-generators/create-patch-endpoint.js +8 -13
- package/esm/endpoint-generators/create-patch-endpoint.js.map +1 -1
- package/esm/endpoint-generators/create-patch-endpoint.spec.js +10 -17
- package/esm/endpoint-generators/create-patch-endpoint.spec.js.map +1 -1
- package/esm/endpoint-generators/create-post-endpoint.d.ts +7 -13
- package/esm/endpoint-generators/create-post-endpoint.d.ts.map +1 -1
- package/esm/endpoint-generators/create-post-endpoint.js +8 -13
- package/esm/endpoint-generators/create-post-endpoint.js.map +1 -1
- package/esm/endpoint-generators/create-post-endpoint.spec.js +41 -14
- package/esm/endpoint-generators/create-post-endpoint.spec.js.map +1 -1
- package/esm/endpoint-generators/utils.d.ts +17 -2
- package/esm/endpoint-generators/utils.d.ts.map +1 -1
- package/esm/endpoint-generators/utils.js +33 -20
- package/esm/endpoint-generators/utils.js.map +1 -1
- package/esm/get-schema-from-api.d.ts +1 -1
- package/esm/get-schema-from-api.d.ts.map +1 -1
- package/esm/get-schema-from-api.js +1 -0
- package/esm/get-schema-from-api.js.map +1 -1
- package/esm/get-schema-from-api.spec.js.map +1 -1
- package/esm/helpers.d.ts +54 -88
- package/esm/helpers.d.ts.map +1 -1
- package/esm/helpers.js +90 -92
- package/esm/helpers.js.map +1 -1
- package/esm/helpers.spec.d.ts +2 -1
- package/esm/helpers.spec.d.ts.map +1 -1
- package/esm/helpers.spec.js +41 -38
- package/esm/helpers.spec.js.map +1 -1
- package/esm/http-authentication-settings.d.ts +56 -12
- package/esm/http-authentication-settings.d.ts.map +1 -1
- package/esm/http-authentication-settings.js +27 -29
- package/esm/http-authentication-settings.js.map +1 -1
- package/esm/http-server-pool.d.ts +64 -0
- package/esm/http-server-pool.d.ts.map +1 -0
- package/esm/http-server-pool.js +95 -0
- package/esm/http-server-pool.js.map +1 -0
- package/esm/http-server-pool.spec.d.ts +2 -0
- package/esm/http-server-pool.spec.d.ts.map +1 -0
- package/esm/http-server-pool.spec.js +193 -0
- package/esm/http-server-pool.spec.js.map +1 -0
- package/esm/http-user-context.d.ts +34 -44
- package/esm/http-user-context.d.ts.map +1 -1
- package/esm/http-user-context.js +75 -95
- package/esm/http-user-context.js.map +1 -1
- package/esm/http-user-context.spec.d.ts +8 -2
- package/esm/http-user-context.spec.d.ts.map +1 -1
- package/esm/http-user-context.spec.js +226 -332
- package/esm/http-user-context.spec.js.map +1 -1
- package/esm/identity-cache-keys.d.ts +28 -0
- package/esm/identity-cache-keys.d.ts.map +1 -0
- package/esm/identity-cache-keys.js +13 -0
- package/esm/identity-cache-keys.js.map +1 -0
- package/esm/identity-cache-keys.spec.d.ts +2 -0
- package/esm/identity-cache-keys.spec.d.ts.map +1 -0
- package/esm/identity-cache-keys.spec.js +21 -0
- package/esm/identity-cache-keys.spec.js.map +1 -0
- package/esm/identity-event-bus.d.ts +102 -0
- package/esm/identity-event-bus.d.ts.map +1 -0
- package/esm/identity-event-bus.js +151 -0
- package/esm/identity-event-bus.js.map +1 -0
- package/esm/identity-event-bus.spec.d.ts +2 -0
- package/esm/identity-event-bus.spec.d.ts.map +1 -0
- package/esm/identity-event-bus.spec.js +392 -0
- package/esm/identity-event-bus.spec.js.map +1 -0
- package/esm/index.d.ts +9 -4
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -4
- package/esm/index.js.map +1 -1
- package/esm/login-response-strategy.d.ts +11 -10
- package/esm/login-response-strategy.d.ts.map +1 -1
- package/esm/login-response-strategy.js +7 -6
- package/esm/login-response-strategy.js.map +1 -1
- package/esm/login-response-strategy.spec.js +25 -29
- package/esm/login-response-strategy.spec.js.map +1 -1
- package/esm/openapi/generate-openapi-document.spec.js.map +1 -1
- package/esm/proxy-manager.spec.js +152 -176
- package/esm/proxy-manager.spec.js.map +1 -1
- package/esm/proxy-runtime.d.ts +27 -0
- package/esm/proxy-runtime.d.ts.map +1 -0
- package/esm/proxy-runtime.js +45 -0
- package/esm/proxy-runtime.js.map +1 -0
- package/esm/proxy-runtime.spec.d.ts +2 -0
- package/esm/proxy-runtime.spec.d.ts.map +1 -0
- package/esm/proxy-runtime.spec.js +39 -0
- package/esm/proxy-runtime.spec.js.map +1 -0
- package/esm/request-action-implementation.d.ts +25 -0
- package/esm/request-action-implementation.d.ts.map +1 -1
- package/esm/request-action-implementation.js +9 -0
- package/esm/request-action-implementation.js.map +1 -1
- package/esm/rest-api-runtime.d.ts +76 -0
- package/esm/rest-api-runtime.d.ts.map +1 -0
- package/esm/rest-api-runtime.js +131 -0
- package/esm/rest-api-runtime.js.map +1 -0
- package/esm/rest-api-runtime.spec.d.ts +2 -0
- package/esm/rest-api-runtime.spec.d.ts.map +1 -0
- package/esm/rest-api-runtime.spec.js +58 -0
- package/esm/rest-api-runtime.spec.js.map +1 -0
- package/esm/rest-service.integration.spec.d.ts +1 -1
- package/esm/rest-service.integration.spec.d.ts.map +1 -1
- package/esm/rest-service.integration.spec.js +57 -80
- package/esm/rest-service.integration.spec.js.map +1 -1
- package/esm/rest.integration.test.js +26 -84
- package/esm/rest.integration.test.js.map +1 -1
- package/esm/server-telemetry.d.ts +49 -0
- package/esm/server-telemetry.d.ts.map +1 -0
- package/esm/server-telemetry.js +25 -0
- package/esm/server-telemetry.js.map +1 -0
- package/esm/server-telemetry.spec.d.ts +2 -0
- package/esm/server-telemetry.spec.d.ts.map +1 -0
- package/esm/server-telemetry.spec.js +52 -0
- package/esm/server-telemetry.spec.js.map +1 -0
- package/esm/static-server-manager.spec.js +60 -125
- package/esm/static-server-manager.spec.js.map +1 -1
- package/esm/static-site-runtime.d.ts +21 -0
- package/esm/static-site-runtime.d.ts.map +1 -0
- package/esm/static-site-runtime.js +48 -0
- package/esm/static-site-runtime.js.map +1 -0
- package/esm/static-site-runtime.spec.d.ts +2 -0
- package/esm/static-site-runtime.spec.d.ts.map +1 -0
- package/esm/static-site-runtime.spec.js +30 -0
- package/esm/static-site-runtime.spec.js.map +1 -0
- package/esm/user-resolution-cache.d.ts +65 -0
- package/esm/user-resolution-cache.d.ts.map +1 -0
- package/esm/user-resolution-cache.js +101 -0
- package/esm/user-resolution-cache.js.map +1 -0
- package/esm/user-resolution-cache.spec.d.ts +2 -0
- package/esm/user-resolution-cache.spec.d.ts.map +1 -0
- package/esm/user-resolution-cache.spec.js +220 -0
- package/esm/user-resolution-cache.spec.js.map +1 -0
- package/esm/user-store.d.ts +39 -0
- package/esm/user-store.d.ts.map +1 -0
- package/esm/user-store.js +62 -0
- package/esm/user-store.js.map +1 -0
- package/esm/user-store.spec.d.ts +2 -0
- package/esm/user-store.spec.d.ts.map +1 -0
- package/esm/user-store.spec.js +72 -0
- package/esm/user-store.spec.js.map +1 -0
- package/esm/validate.d.ts +13 -12
- package/esm/validate.d.ts.map +1 -1
- package/esm/validate.integration.spec.js +27 -28
- package/esm/validate.integration.spec.js.map +1 -1
- package/esm/validate.js +12 -0
- package/esm/validate.js.map +1 -1
- package/package.json +14 -12
- package/src/actions/error-action.ts +7 -3
- package/src/actions/get-current-user.spec.ts +11 -10
- package/src/actions/get-current-user.ts +1 -4
- package/src/actions/is-authenticated.spec.ts +12 -7
- package/src/actions/is-authenticated.ts +3 -4
- package/src/actions/logout-action.spec.ts +12 -12
- package/src/actions/logout.ts +3 -7
- package/src/actions/not-found-action.ts +1 -3
- package/src/actions/password-login-action.spec.ts +30 -30
- package/src/actions/password-login-action.ts +6 -13
- package/src/authenticate.spec.ts +45 -51
- package/src/authenticate.ts +6 -12
- package/src/authentication-providers/authentication-provider.ts +17 -0
- package/src/authentication-providers/basic-auth-provider.ts +7 -0
- package/src/authentication-providers/cookie-auth-provider.ts +8 -0
- package/src/authorize.spec.ts +37 -39
- package/src/authorize.ts +6 -17
- package/src/endpoint-generators/create-delete-endpoint.spec.ts +16 -24
- package/src/endpoint-generators/create-delete-endpoint.ts +11 -17
- package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +45 -78
- package/src/endpoint-generators/create-get-collection-endpoint.ts +17 -19
- package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +17 -33
- package/src/endpoint-generators/create-get-entity-endpoint.ts +11 -17
- package/src/endpoint-generators/create-get-openapi-document-action.ts +2 -2
- package/src/endpoint-generators/create-get-schema-action.ts +1 -1
- package/src/endpoint-generators/create-patch-endpoint.spec.ts +11 -18
- package/src/endpoint-generators/create-patch-endpoint.ts +12 -23
- package/src/endpoint-generators/create-post-endpoint.spec.ts +45 -14
- package/src/endpoint-generators/create-post-endpoint.ts +13 -23
- package/src/endpoint-generators/utils.ts +36 -28
- package/src/get-schema-from-api.spec.ts +1 -1
- package/src/get-schema-from-api.ts +2 -1
- package/src/helpers.spec.ts +51 -41
- package/src/helpers.ts +140 -109
- package/src/http-authentication-settings.ts +78 -24
- package/src/http-server-pool.spec.ts +220 -0
- package/src/http-server-pool.ts +169 -0
- package/src/http-user-context.spec.ts +246 -378
- package/src/http-user-context.ts +122 -92
- package/src/identity-cache-keys.spec.ts +24 -0
- package/src/identity-cache-keys.ts +31 -0
- package/src/identity-event-bus.spec.ts +285 -0
- package/src/identity-event-bus.ts +230 -0
- package/src/index.ts +9 -4
- package/src/login-response-strategy.spec.ts +32 -31
- package/src/login-response-strategy.ts +14 -12
- package/src/openapi/generate-openapi-document.spec.ts +2 -2
- package/src/proxy-manager.spec.ts +158 -188
- package/src/proxy-runtime.spec.ts +50 -0
- package/src/proxy-runtime.ts +75 -0
- package/src/request-action-implementation.ts +25 -0
- package/src/rest-api-runtime.spec.ts +77 -0
- package/src/rest-api-runtime.ts +204 -0
- package/src/rest-service.integration.spec.ts +65 -85
- package/src/rest.integration.test.ts +27 -87
- package/src/server-telemetry.spec.ts +56 -0
- package/src/server-telemetry.ts +43 -0
- package/src/static-server-manager.spec.ts +63 -151
- package/src/static-site-runtime.spec.ts +39 -0
- package/src/static-site-runtime.ts +75 -0
- package/src/user-resolution-cache.spec.ts +241 -0
- package/src/user-resolution-cache.ts +164 -0
- package/src/user-store.spec.ts +86 -0
- package/src/user-store.ts +69 -0
- package/src/validate.integration.spec.ts +40 -35
- package/src/validate.ts +14 -12
- package/esm/api-manager.d.ts +0 -104
- package/esm/api-manager.d.ts.map +0 -1
- package/esm/api-manager.js +0 -179
- package/esm/api-manager.js.map +0 -1
- package/esm/proxy-manager.d.ts +0 -53
- package/esm/proxy-manager.d.ts.map +0 -1
- package/esm/proxy-manager.js +0 -84
- package/esm/proxy-manager.js.map +0 -1
- package/esm/server-manager.d.ts +0 -48
- package/esm/server-manager.d.ts.map +0 -1
- package/esm/server-manager.js +0 -100
- package/esm/server-manager.js.map +0 -1
- package/esm/static-server-manager.d.ts +0 -19
- package/esm/static-server-manager.d.ts.map +0 -1
- package/esm/static-server-manager.js +0 -65
- package/esm/static-server-manager.js.map +0 -1
- package/src/api-manager.ts +0 -304
- package/src/proxy-manager.ts +0 -102
- package/src/server-manager.ts +0 -135
- package/src/static-server-manager.ts +0 -90
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import type { LoginResponseStrategy } from '../login-response-strategy.js';
|
|
2
2
|
import type { RequestAction } from '../request-action-implementation.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Cookie strategy -> `ActionResult<User>`
|
|
10
|
-
* - JWT strategy -> `ActionResult<{ accessToken: string; refreshToken: string }>`
|
|
11
|
-
*
|
|
12
|
-
* A random delay (0-1 s) is added on failure to mitigate timing attacks.
|
|
13
|
-
*
|
|
14
|
-
* @param strategy The login response strategy that produces the session/token result
|
|
15
|
-
* @returns A `RequestAction` that can be wired into a REST API route
|
|
4
|
+
* Username + password login action. Authenticates via {@link HttpUserContext},
|
|
5
|
+
* then delegates session/token creation to `strategy`. The result type is
|
|
6
|
+
* inferred from the strategy (e.g. `User` for cookies, `{ accessToken,
|
|
7
|
+
* refreshToken }` for JWT). Adds a 0–1 s random delay on failure to mitigate
|
|
8
|
+
* timing attacks; rethrows as `RequestError(400)`.
|
|
16
9
|
*/
|
|
17
10
|
export declare const createPasswordLoginAction: <TResult>(strategy: LoginResponseStrategy<TResult>) => RequestAction<{
|
|
18
11
|
result: TResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-login-action.d.ts","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAExE
|
|
1
|
+
{"version":3,"file":"password-login-action.d.ts","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAExE;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,EAC/C,UAAU,qBAAqB,CAAC,OAAO,CAAC,KACvC,aAAa,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAWjF,CAAA"}
|
|
@@ -2,24 +2,17 @@ import { RequestError } from '@furystack/rest';
|
|
|
2
2
|
import { sleepAsync } from '@furystack/utils';
|
|
3
3
|
import { HttpUserContext } from '../http-user-context.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - Cookie strategy -> `ActionResult<User>`
|
|
11
|
-
* - JWT strategy -> `ActionResult<{ accessToken: string; refreshToken: string }>`
|
|
12
|
-
*
|
|
13
|
-
* A random delay (0-1 s) is added on failure to mitigate timing attacks.
|
|
14
|
-
*
|
|
15
|
-
* @param strategy The login response strategy that produces the session/token result
|
|
16
|
-
* @returns A `RequestAction` that can be wired into a REST API route
|
|
5
|
+
* Username + password login action. Authenticates via {@link HttpUserContext},
|
|
6
|
+
* then delegates session/token creation to `strategy`. The result type is
|
|
7
|
+
* inferred from the strategy (e.g. `User` for cookies, `{ accessToken,
|
|
8
|
+
* refreshToken }` for JWT). Adds a 0–1 s random delay on failure to mitigate
|
|
9
|
+
* timing attacks; rethrows as `RequestError(400)`.
|
|
17
10
|
*/
|
|
18
11
|
export const createPasswordLoginAction = (strategy) => {
|
|
19
12
|
return async ({ injector, getBody }) => {
|
|
20
13
|
const body = await getBody();
|
|
21
14
|
try {
|
|
22
|
-
const user = await injector.
|
|
15
|
+
const user = await injector.get(HttpUserContext).authenticateUser(body.username, body.password);
|
|
23
16
|
return strategy.createLoginResponse(user, injector);
|
|
24
17
|
}
|
|
25
18
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-login-action.js","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAIzD
|
|
1
|
+
{"version":3,"file":"password-login-action.js","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAIzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,QAAwC,EAC0C,EAAE;IACpF,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC/F,OAAO,QAAQ,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
import { InMemoryStore,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { PasswordAuthenticator, PasswordCredential, PasswordResetToken, usePasswordPolicy } from '@furystack/security';
|
|
1
|
+
import { InMemoryStore, User as UserModel } from '@furystack/core';
|
|
2
|
+
import { createInjector } from '@furystack/inject';
|
|
3
|
+
import { PasswordCredential, PasswordCredentialStore, PasswordResetToken, PasswordResetTokenStore, usePasswordPolicy, } from '@furystack/security';
|
|
5
4
|
import { usingAsync } from '@furystack/utils';
|
|
6
5
|
import { describe, expect, it, vi } from 'vitest';
|
|
7
6
|
import { useHttpAuthentication } from '../helpers.js';
|
|
8
7
|
import { DefaultSession } from '../models/default-session.js';
|
|
9
8
|
import { JsonResult } from '../request-action-implementation.js';
|
|
9
|
+
import { SessionStore, UserStore } from '../user-store.js';
|
|
10
|
+
import { PasswordAuthenticator } from '@furystack/security';
|
|
10
11
|
import { createPasswordLoginAction } from './password-login-action.js';
|
|
11
12
|
const setupInjector = async (i, username, password) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const repo = getRepository(i);
|
|
17
|
-
repo.createDataSet(User, 'username');
|
|
18
|
-
repo.createDataSet(DefaultSession, 'sessionId');
|
|
19
|
-
repo.createDataSet(PasswordCredential, 'userName');
|
|
20
|
-
repo.createDataSet(PasswordResetToken, 'token');
|
|
13
|
+
i.bind(UserStore, () => new InMemoryStore({ model: UserModel, primaryKey: 'username' }));
|
|
14
|
+
i.bind(SessionStore, () => new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
|
|
15
|
+
i.bind(PasswordCredentialStore, () => new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }));
|
|
16
|
+
i.bind(PasswordResetTokenStore, () => new InMemoryStore({ model: PasswordResetToken, primaryKey: 'token' }));
|
|
21
17
|
usePasswordPolicy(i);
|
|
22
18
|
useHttpAuthentication(i);
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
-
await sm.getStoreFor(User, 'username').add({ username, roles: ['admin'] });
|
|
19
|
+
const authenticator = i.get(PasswordAuthenticator);
|
|
20
|
+
const cred = await authenticator.hasher.createCredential(username, password);
|
|
21
|
+
await i.get(PasswordCredentialStore).add(cred);
|
|
22
|
+
await i.get(UserStore).add({ username, roles: ['admin'] });
|
|
28
23
|
};
|
|
29
24
|
const mockStrategy = {
|
|
30
25
|
createLoginResponse: vi.fn(async (user) => JsonResult(user, 200)),
|
|
@@ -32,8 +27,8 @@ const mockStrategy = {
|
|
|
32
27
|
describe('createPasswordLoginAction', () => {
|
|
33
28
|
const request = {};
|
|
34
29
|
const response = {};
|
|
35
|
-
it('
|
|
36
|
-
await usingAsync(
|
|
30
|
+
it('delegates to the strategy on successful authentication', async () => {
|
|
31
|
+
await usingAsync(createInjector(), async (i) => {
|
|
37
32
|
await setupInjector(i, 'testuser', 'testpass');
|
|
38
33
|
const action = createPasswordLoginAction(mockStrategy);
|
|
39
34
|
const result = await action({
|
|
@@ -46,8 +41,8 @@ describe('createPasswordLoginAction', () => {
|
|
|
46
41
|
expect(result.chunk.username).toBe('testuser');
|
|
47
42
|
});
|
|
48
43
|
});
|
|
49
|
-
it('
|
|
50
|
-
await usingAsync(
|
|
44
|
+
it('passes the authenticated user to the strategy', async () => {
|
|
45
|
+
await usingAsync(createInjector(), async (i) => {
|
|
51
46
|
await setupInjector(i, 'testuser', 'testpass');
|
|
52
47
|
const strategyFn = vi.fn(async (user) => JsonResult(user, 200));
|
|
53
48
|
const strategy = { createLoginResponse: strategyFn };
|
|
@@ -61,8 +56,8 @@ describe('createPasswordLoginAction', () => {
|
|
|
61
56
|
expect(strategyFn).toHaveBeenCalledWith(expect.objectContaining({ username: 'testuser', roles: ['admin'] }), i);
|
|
62
57
|
});
|
|
63
58
|
});
|
|
64
|
-
it('
|
|
65
|
-
await usingAsync(
|
|
59
|
+
it('throws RequestError on invalid password', async () => {
|
|
60
|
+
await usingAsync(createInjector(), async (i) => {
|
|
66
61
|
await setupInjector(i, 'testuser', 'testpass');
|
|
67
62
|
const action = createPasswordLoginAction(mockStrategy);
|
|
68
63
|
await expect(action({
|
|
@@ -73,8 +68,8 @@ describe('createPasswordLoginAction', () => {
|
|
|
73
68
|
})).rejects.toThrow('Login Failed');
|
|
74
69
|
});
|
|
75
70
|
});
|
|
76
|
-
it('
|
|
77
|
-
await usingAsync(
|
|
71
|
+
it('throws RequestError for an unknown user', async () => {
|
|
72
|
+
await usingAsync(createInjector(), async (i) => {
|
|
78
73
|
await setupInjector(i, 'testuser', 'testpass');
|
|
79
74
|
const action = createPasswordLoginAction(mockStrategy);
|
|
80
75
|
await expect(action({
|
|
@@ -85,8 +80,8 @@ describe('createPasswordLoginAction', () => {
|
|
|
85
80
|
})).rejects.toThrow('Login Failed');
|
|
86
81
|
});
|
|
87
82
|
});
|
|
88
|
-
it('
|
|
89
|
-
await usingAsync(
|
|
83
|
+
it('supports strategies returning custom result shapes', async () => {
|
|
84
|
+
await usingAsync(createInjector(), async (i) => {
|
|
90
85
|
await setupInjector(i, 'testuser', 'testpass');
|
|
91
86
|
const tokenStrategy = {
|
|
92
87
|
createLoginResponse: async () => JsonResult({ accessToken: 'tok123' }, 200),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-login-action.spec.js","sourceRoot":"","sources":["../../src/actions/password-login-action.spec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"password-login-action.spec.js","sourceRoot":"","sources":["../../src/actions/password-login-action.spec.ts"],"names":[],"mappings":"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"}
|
package/esm/authenticate.d.ts
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import type { RequestAction } from './request-action-implementation.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Wraps a {@link RequestAction} to require authentication. Unauthenticated
|
|
4
|
+
* requests return `401 Unauthorized` (with `WWW-Authenticate: Basic` when
|
|
5
|
+
* the chain includes Basic Auth). Adds a 0–1 s random delay on rejection to
|
|
6
|
+
* mitigate timing attacks.
|
|
6
7
|
*
|
|
7
|
-
* @returns A function that wraps the provided action with authentication check
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
10
|
-
* // Wrap an endpoint to require authentication
|
|
11
|
-
* const protectedEndpoint = Authenticate()(myEndpoint)
|
|
12
|
-
*
|
|
13
|
-
* // Or use directly in API definition
|
|
14
10
|
* api: {
|
|
15
|
-
* GET: {
|
|
16
|
-
* '/users': Authenticate()(getUsersEndpoint)
|
|
17
|
-
* }
|
|
11
|
+
* GET: { '/users': Authenticate()(getUsersEndpoint) },
|
|
18
12
|
* }
|
|
19
13
|
* ```
|
|
20
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAG3G
|
|
1
|
+
{"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAG3G;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,SAEtB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAqBzE,CAAA"}
|
package/esm/authenticate.js
CHANGED
|
@@ -3,21 +3,15 @@ import { sleepAsync } from '@furystack/utils';
|
|
|
3
3
|
import { HttpUserContext } from './http-user-context.js';
|
|
4
4
|
import { JsonResult } from './request-action-implementation.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Wraps a {@link RequestAction} to require authentication. Unauthenticated
|
|
7
|
+
* requests return `401 Unauthorized` (with `WWW-Authenticate: Basic` when
|
|
8
|
+
* the chain includes Basic Auth). Adds a 0–1 s random delay on rejection to
|
|
9
|
+
* mitigate timing attacks.
|
|
9
10
|
*
|
|
10
|
-
* @returns A function that wraps the provided action with authentication check
|
|
11
11
|
* @example
|
|
12
12
|
* ```ts
|
|
13
|
-
* // Wrap an endpoint to require authentication
|
|
14
|
-
* const protectedEndpoint = Authenticate()(myEndpoint)
|
|
15
|
-
*
|
|
16
|
-
* // Or use directly in API definition
|
|
17
13
|
* api: {
|
|
18
|
-
* GET: {
|
|
19
|
-
* '/users': Authenticate()(getUsersEndpoint)
|
|
20
|
-
* }
|
|
14
|
+
* GET: { '/users': Authenticate()(getUsersEndpoint) },
|
|
21
15
|
* }
|
|
22
16
|
* ```
|
|
23
17
|
*/
|
|
@@ -28,7 +22,7 @@ export const Authenticate = () => (action) => {
|
|
|
28
22
|
if (!authenticated) {
|
|
29
23
|
await sleepAsync(Math.random() * 1000);
|
|
30
24
|
const hasBasicAuth = injector
|
|
31
|
-
.
|
|
25
|
+
.get(HttpUserContext)
|
|
32
26
|
.authentication.authenticationProviders.some((p) => p.name === 'basic-auth');
|
|
33
27
|
return JsonResult({ error: 'unauthorized' }, 401, hasBasicAuth ? { 'WWW-Authenticate': 'Basic' } : {});
|
|
34
28
|
}
|
package/esm/authenticate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAE/D
|
|
1
|
+
{"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAE/D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,GAAG,EAAE,CACL,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,MAAM,OAAO,GAAG,KAAK,EAAE,IAA6B,EAA4B,EAAE;QAChF,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;QACzB,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAA;QACrD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,YAAY,GAAG,QAAQ;iBAC1B,GAAG,CAAC,eAAe,CAAC;iBACpB,cAAc,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;YAC9E,OAAO,UAAU,CACf,EAAE,KAAK,EAAE,cAAc,EAAE,EACzB,GAAG,EACH,YAAY,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CACtB,CAAA;QACjC,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAoB,CAAA;IAChD,CAAC,CAAA;IAED,OAAO,CAAC,eAAe,GAAG,IAAI,CAAA;IAE9B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
package/esm/authenticate.spec.js
CHANGED
|
@@ -1,58 +1,66 @@
|
|
|
1
1
|
import { IdentityContext } from '@furystack/core';
|
|
2
|
-
import {
|
|
3
|
-
import { usingAsync } from '@furystack/utils';
|
|
2
|
+
import { createInjector } from '@furystack/inject';
|
|
3
|
+
import { EventHub, usingAsync } from '@furystack/utils';
|
|
4
4
|
import { describe, expect, it, vi } from 'vitest';
|
|
5
5
|
import { Authenticate } from './authenticate.js';
|
|
6
|
-
import { HttpUserContext } from './http-user-context.js';
|
|
6
|
+
import { HttpUserContext as HttpUserContextToken } from './http-user-context.js';
|
|
7
7
|
import { EmptyResult } from './request-action-implementation.js';
|
|
8
|
+
const makeHttpUserContextStub = (providers) => Object.assign(new EventHub(), {
|
|
9
|
+
authentication: { authenticationProviders: providers },
|
|
10
|
+
});
|
|
8
11
|
describe('Authenticate', () => {
|
|
9
12
|
const response = {};
|
|
10
13
|
const request = { url: 'http://google.com' };
|
|
11
|
-
it('
|
|
12
|
-
await usingAsync(
|
|
13
|
-
const
|
|
14
|
-
i.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
it('returns 401 without WWW-Authenticate when no basic-auth provider is registered', async () => {
|
|
15
|
+
await usingAsync(createInjector(), async (i) => {
|
|
16
|
+
const isAuthenticated = vi.fn(async () => false);
|
|
17
|
+
i.bind(IdentityContext, () => ({
|
|
18
|
+
isAuthenticated,
|
|
19
|
+
getCurrentUser: () => Promise.reject(new Error(':(')),
|
|
20
|
+
isAuthorized: () => Promise.resolve(false),
|
|
21
|
+
}));
|
|
22
|
+
i.bind(HttpUserContextToken, () => makeHttpUserContextStub([]));
|
|
23
|
+
const exampleAction = vi.fn(async () => EmptyResult());
|
|
24
|
+
const authorized = Authenticate()(exampleAction);
|
|
20
25
|
const result = await authorized({ injector: i, request, response });
|
|
21
26
|
expect(result.statusCode).toBe(401);
|
|
22
27
|
expect(result.chunk).toEqual({ error: 'unauthorized' });
|
|
23
28
|
expect(result.headers).toEqual({ 'Content-Type': 'application/json' });
|
|
24
|
-
expect(
|
|
29
|
+
expect(exampleAction).not.toHaveBeenCalled();
|
|
25
30
|
});
|
|
26
31
|
});
|
|
27
|
-
it('
|
|
28
|
-
await usingAsync(
|
|
29
|
-
const
|
|
30
|
-
i.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const authorized = Authenticate()(
|
|
32
|
+
it('returns 401 with WWW-Authenticate: Basic when a basic-auth provider is registered', async () => {
|
|
33
|
+
await usingAsync(createInjector(), async (i) => {
|
|
34
|
+
const isAuthenticated = vi.fn(async () => false);
|
|
35
|
+
i.bind(IdentityContext, () => ({
|
|
36
|
+
isAuthenticated,
|
|
37
|
+
getCurrentUser: () => Promise.reject(new Error(':(')),
|
|
38
|
+
isAuthorized: () => Promise.resolve(false),
|
|
39
|
+
}));
|
|
40
|
+
i.bind(HttpUserContextToken, () => makeHttpUserContextStub([{ name: 'basic-auth' }]));
|
|
41
|
+
const exampleAction = vi.fn(async () => EmptyResult());
|
|
42
|
+
const authorized = Authenticate()(exampleAction);
|
|
38
43
|
const result = await authorized({ injector: i, request, response });
|
|
39
44
|
expect(result.statusCode).toBe(401);
|
|
40
45
|
expect(result.chunk).toEqual({ error: 'unauthorized' });
|
|
41
46
|
expect(result.headers).toEqual({ 'Content-Type': 'application/json', 'WWW-Authenticate': 'Basic' });
|
|
42
|
-
expect(
|
|
47
|
+
expect(exampleAction).not.toHaveBeenCalled();
|
|
43
48
|
});
|
|
44
49
|
});
|
|
45
|
-
it('
|
|
46
|
-
await usingAsync(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
it('invokes the wrapped action when the caller is authenticated', async () => {
|
|
51
|
+
await usingAsync(createInjector(), async (i) => {
|
|
52
|
+
i.bind(IdentityContext, () => ({
|
|
53
|
+
isAuthenticated: () => Promise.resolve(true),
|
|
54
|
+
getCurrentUser: () => Promise.reject(new Error(':(')),
|
|
55
|
+
isAuthorized: () => Promise.resolve(true),
|
|
56
|
+
}));
|
|
57
|
+
const exampleAction = vi.fn(async () => EmptyResult());
|
|
58
|
+
const authorized = Authenticate()(exampleAction);
|
|
59
|
+
const params = { injector: i, request, response };
|
|
52
60
|
const result = await authorized(params);
|
|
53
61
|
expect(result.statusCode).toBe(200);
|
|
54
62
|
expect(result.chunk).toBe(undefined);
|
|
55
|
-
expect(
|
|
63
|
+
expect(exampleAction).toHaveBeenCalledWith(params);
|
|
56
64
|
});
|
|
57
65
|
});
|
|
58
66
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../src/authenticate.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../src/authenticate.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,5 +21,22 @@ export type AuthenticationProvider = {
|
|
|
21
21
|
*/
|
|
22
22
|
readonly name: string;
|
|
23
23
|
authenticate: (request: Pick<IncomingMessage, 'headers'>) => Promise<User | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Optional cache-key resolver consulted by the user-resolution cache before
|
|
26
|
+
* the provider chain is walked.
|
|
27
|
+
*
|
|
28
|
+
* Returns a stable, opaque string identifying the authenticated principal
|
|
29
|
+
* for the given request, or `null` when this provider does not apply to
|
|
30
|
+
* the request (or refuses to participate in caching — e.g. Basic Auth,
|
|
31
|
+
* which must verify the password on every request).
|
|
32
|
+
*
|
|
33
|
+
* The first non-null key returned by the configured providers is used as
|
|
34
|
+
* the cache key. Keys returned by different providers must not collide;
|
|
35
|
+
* built-in providers prefix their keys (`cookie:`, `jwt:`).
|
|
36
|
+
*
|
|
37
|
+
* If no provider returns a key, the request bypasses the cache entirely
|
|
38
|
+
* and the provider chain is walked on every call.
|
|
39
|
+
*/
|
|
40
|
+
readonly getCacheKey?: (request: Pick<IncomingMessage, 'headers'>) => string | null;
|
|
24
41
|
};
|
|
25
42
|
//# sourceMappingURL=authentication-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authentication-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/authentication-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"authentication-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/authentication-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACjF;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;CACpF,CAAA"}
|
|
@@ -2,6 +2,13 @@ import type { User } from '@furystack/core';
|
|
|
2
2
|
import type { AuthenticationProvider } from './authentication-provider.js';
|
|
3
3
|
/**
|
|
4
4
|
* Creates an authentication provider for HTTP Basic Authentication.
|
|
5
|
+
*
|
|
6
|
+
* **Caching note:** this provider intentionally does **not** implement
|
|
7
|
+
* `getCacheKey`. Caching authenticated users by username would bypass
|
|
8
|
+
* password verification on every cache hit — the cache cannot revalidate the
|
|
9
|
+
* password without re-running the authenticator. Basic Auth requests
|
|
10
|
+
* therefore always walk the provider chain, which is also where the password
|
|
11
|
+
* is verified.
|
|
5
12
|
* @param authenticateUser Callback that verifies credentials and returns a User or throws
|
|
6
13
|
*/
|
|
7
14
|
export declare const createBasicAuthProvider: (authenticateUser: (username: string, password: string) => Promise<User>) => AuthenticationProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE1E
|
|
1
|
+
{"version":3,"file":"basic-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE1E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,GAClC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACtE,sBAWD,CAAA"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Creates an authentication provider for HTTP Basic Authentication.
|
|
3
|
+
*
|
|
4
|
+
* **Caching note:** this provider intentionally does **not** implement
|
|
5
|
+
* `getCacheKey`. Caching authenticated users by username would bypass
|
|
6
|
+
* password verification on every cache hit — the cache cannot revalidate the
|
|
7
|
+
* password without re-running the authenticator. Basic Auth requests
|
|
8
|
+
* therefore always walk the provider chain, which is also where the password
|
|
9
|
+
* is verified.
|
|
3
10
|
* @param authenticateUser Callback that verifies credentials and returns a User or throws
|
|
4
11
|
*/
|
|
5
12
|
export const createBasicAuthProvider = (authenticateUser) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"basic-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,gBAAuE,EAC/C,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,YAAY;IAClB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAA;QAChD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC1E,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;QAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;QAC9C,OAAO,MAAM,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"cookie-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAG1E;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GACnC,YAAY,MAAM,EAClB,gBAAgB,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,EACrE,eAAe,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACjD,sBAgBD,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { UnauthenticatedError } from '@furystack/security';
|
|
2
|
+
import { sessionCacheKey } from '../identity-cache-keys.js';
|
|
2
3
|
import { extractSessionIdFromCookies } from './helpers.js';
|
|
3
4
|
/**
|
|
4
5
|
* Creates an authentication provider for cookie-based session authentication.
|
|
@@ -17,5 +18,12 @@ export const createCookieAuthProvider = (cookieName, getSessionById, getUserByNa
|
|
|
17
18
|
throw new UnauthenticatedError();
|
|
18
19
|
return await getUserByName(session.username);
|
|
19
20
|
},
|
|
21
|
+
// The session id alone uniquely identifies the principal — caching by it is
|
|
22
|
+
// safe because session invalidation (logout, expiry) drops the session row,
|
|
23
|
+
// and the TTL on the user-resolution cache bounds staleness across nodes.
|
|
24
|
+
getCacheKey: (request) => {
|
|
25
|
+
const sessionId = extractSessionIdFromCookies(request, cookieName);
|
|
26
|
+
return sessionId ? sessionCacheKey(sessionId) : null;
|
|
27
|
+
},
|
|
20
28
|
});
|
|
21
29
|
//# sourceMappingURL=cookie-auth-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"cookie-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAwB,MAAM,2BAA2B,CAAA;AAGjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,UAAkB,EAClB,cAAqE,EACrE,aAAkD,EAC1B,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,aAAa;IACnB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAClE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAC3B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,oBAAoB,EAAE,CAAA;QAC9C,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9C,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,WAAW,EAAE,CAAC,OAAO,EAA0B,EAAE;QAC/C,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAClE,OAAO,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtD,CAAC;CACF,CAAC,CAAA"}
|
package/esm/authorize.d.ts
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
import type { RequestAction } from './request-action-implementation.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @returns A function that wraps the provided action with authorization check
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* // Require 'admin' role
|
|
12
|
-
* const adminEndpoint = Authorize('admin')(myEndpoint)
|
|
13
|
-
*
|
|
14
|
-
* // Require multiple roles (user must have ALL specified roles)
|
|
15
|
-
* const superAdminEndpoint = Authorize('admin', 'superuser')(myEndpoint)
|
|
16
|
-
*
|
|
17
|
-
* // Chain with Authenticate for authentication + authorization
|
|
18
|
-
* const protectedEndpoint = Authenticate()(Authorize('admin')(myEndpoint))
|
|
19
|
-
* ```
|
|
3
|
+
* Wraps a {@link RequestAction} to require **all** specified roles. Throws
|
|
4
|
+
* {@link AuthorizationError} (translated to 403 by `ErrorAction`) when any
|
|
5
|
+
* role is missing. Adds a 0–1 s random delay on rejection to mitigate
|
|
6
|
+
* timing attacks. Compose with {@link Authenticate} to require both:
|
|
7
|
+
* `Authenticate()(Authorize('admin')(myEndpoint))`.
|
|
20
8
|
*/
|
|
21
9
|
export declare const Authorize: (...roles: string[]) => <T extends {
|
|
22
10
|
result: unknown;
|
package/esm/authorize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAE3G;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACnB,GAAG,OAAO,MAAM,EAAE,MAClB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAazE,CAAA"}
|
package/esm/authorize.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import { AuthorizationError, isAuthorized } from '@furystack/core';
|
|
2
2
|
import { sleepAsync } from '@furystack/utils';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @returns A function that wraps the provided action with authorization check
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* // Require 'admin' role
|
|
13
|
-
* const adminEndpoint = Authorize('admin')(myEndpoint)
|
|
14
|
-
*
|
|
15
|
-
* // Require multiple roles (user must have ALL specified roles)
|
|
16
|
-
* const superAdminEndpoint = Authorize('admin', 'superuser')(myEndpoint)
|
|
17
|
-
*
|
|
18
|
-
* // Chain with Authenticate for authentication + authorization
|
|
19
|
-
* const protectedEndpoint = Authenticate()(Authorize('admin')(myEndpoint))
|
|
20
|
-
* ```
|
|
4
|
+
* Wraps a {@link RequestAction} to require **all** specified roles. Throws
|
|
5
|
+
* {@link AuthorizationError} (translated to 403 by `ErrorAction`) when any
|
|
6
|
+
* role is missing. Adds a 0–1 s random delay on rejection to mitigate
|
|
7
|
+
* timing attacks. Compose with {@link Authenticate} to require both:
|
|
8
|
+
* `Authenticate()(Authorize('admin')(myEndpoint))`.
|
|
21
9
|
*/
|
|
22
10
|
export const Authorize = (...roles) => (action) => {
|
|
23
11
|
return async (options) => {
|
package/esm/authorize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAI7C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GACpB,CAAC,GAAG,KAAe,EAAE,EAAE,CACvB,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,OAAO,KAAK,EAAE,OAAgC,EAA4B,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAA;YACjE,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;gBACtC,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAoB,CAAA;IACnD,CAAC,CAAA;AACH,CAAC,CAAA"}
|