@fluojs/passport 1.0.0-beta.1

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +179 -0
  3. package/README.md +179 -0
  4. package/dist/account/account-linking.d.ts +91 -0
  5. package/dist/account/account-linking.d.ts.map +1 -0
  6. package/dist/account/account-linking.js +145 -0
  7. package/dist/adapters/passport-js.d.ts +77 -0
  8. package/dist/adapters/passport-js.d.ts.map +1 -0
  9. package/dist/adapters/passport-js.js +230 -0
  10. package/dist/cookie/cookie-auth-module.d.ts +65 -0
  11. package/dist/cookie/cookie-auth-module.d.ts.map +1 -0
  12. package/dist/cookie/cookie-auth-module.js +84 -0
  13. package/dist/cookie/cookie-auth.d.ts +40 -0
  14. package/dist/cookie/cookie-auth.d.ts.map +1 -0
  15. package/dist/cookie/cookie-auth.js +101 -0
  16. package/dist/cookie/cookie-manager.d.ts +34 -0
  17. package/dist/cookie/cookie-manager.d.ts.map +1 -0
  18. package/dist/cookie/cookie-manager.js +93 -0
  19. package/dist/decorators.d.ts +42 -0
  20. package/dist/decorators.d.ts.map +1 -0
  21. package/dist/decorators.js +95 -0
  22. package/dist/errors.d.ts +26 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +48 -0
  25. package/dist/guard.d.ts +39 -0
  26. package/dist/guard.d.ts.map +1 -0
  27. package/dist/guard.js +124 -0
  28. package/dist/index.d.ts +15 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +14 -0
  31. package/dist/internal-tokens.d.ts +3 -0
  32. package/dist/internal-tokens.d.ts.map +1 -0
  33. package/dist/internal-tokens.js +4 -0
  34. package/dist/metadata.d.ts +6 -0
  35. package/dist/metadata.d.ts.map +1 -0
  36. package/dist/metadata.js +105 -0
  37. package/dist/module.d.ts +36 -0
  38. package/dist/module.d.ts.map +1 -0
  39. package/dist/module.js +63 -0
  40. package/dist/refresh/jwt-refresh-token-adapter.d.ts +30 -0
  41. package/dist/refresh/jwt-refresh-token-adapter.d.ts.map +1 -0
  42. package/dist/refresh/jwt-refresh-token-adapter.js +103 -0
  43. package/dist/refresh/refresh-token.d.ts +96 -0
  44. package/dist/refresh/refresh-token.d.ts.map +1 -0
  45. package/dist/refresh/refresh-token.js +178 -0
  46. package/dist/scope.d.ts +5 -0
  47. package/dist/scope.d.ts.map +1 -0
  48. package/dist/scope.js +44 -0
  49. package/dist/status.d.ts +36 -0
  50. package/dist/status.d.ts.map +1 -0
  51. package/dist/status.js +173 -0
  52. package/dist/types.d.ts +36 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +1 -0
  55. package/package.json +55 -0
@@ -0,0 +1,77 @@
1
+ import type { Token } from '@fluojs/core';
2
+ import type { GuardContext, Principal } from '@fluojs/http';
3
+ import type { Provider } from '@fluojs/di';
4
+ import type { AuthHandledResult, AuthStrategy, AuthStrategyRegistration } from '../types.js';
5
+ /**
6
+ * Represents a Passport.js strategy-like object that implements
7
+ * the `authenticate` method.
8
+ */
9
+ export interface PassportJsStrategyLike {
10
+ /**
11
+ * Performs authentication for the given request and options.
12
+ *
13
+ * @param request - The raw request object from the underlying framework.
14
+ * @param options - Strategy-specific authentication options.
15
+ * @returns An execution result or a promise resolving to one.
16
+ */
17
+ authenticate(request: unknown, options?: unknown): unknown;
18
+ }
19
+ /**
20
+ * Input for the principal mapper that converts Passport.js user data
21
+ * into a fluo {@link Principal}.
22
+ */
23
+ export interface PassportJsPrincipalMapperInput {
24
+ /** The guard context for the current request. */
25
+ context: GuardContext;
26
+ /** Optional information returned by the Passport strategy. */
27
+ info?: unknown;
28
+ /** The user object returned by the Passport strategy. */
29
+ user: unknown;
30
+ }
31
+ /**
32
+ * A function type that maps Passport.js user data to a fluo {@link Principal}.
33
+ */
34
+ export type PassportJsPrincipalMapper = (input: PassportJsPrincipalMapperInput) => Principal;
35
+ /**
36
+ * Configuration options for the Passport.js authentication strategy.
37
+ */
38
+ export interface PassportJsAuthStrategyOptions {
39
+ /** Optional options to pass to the Passport strategy's `authenticate` method. */
40
+ authenticateOptions?: Readonly<Record<string, unknown>>;
41
+ /** Optional custom mapper for converting user data to a principal. */
42
+ mapPrincipal?: PassportJsPrincipalMapper;
43
+ }
44
+ /**
45
+ * Bridge interface containing DI providers and strategy registration for Passport.js.
46
+ */
47
+ export interface PassportJsStrategyBridge {
48
+ /** DI providers required for the adapter and its configuration. */
49
+ providers: Provider[];
50
+ /** Canonical strategy registration for the fluo auth guard. */
51
+ strategy: AuthStrategyRegistration;
52
+ }
53
+ /**
54
+ * A bridge strategy that allows using Passport.js strategies within the fluo
55
+ * authentication framework.
56
+ */
57
+ export declare class PassportJsAuthStrategy implements AuthStrategy {
58
+ private readonly strategyTemplate;
59
+ private readonly options;
60
+ private readonly requestState;
61
+ constructor(strategyTemplate: PassportJsStrategyLike, options?: PassportJsAuthStrategyOptions);
62
+ authenticate(context: GuardContext): Promise<Principal | AuthHandledResult>;
63
+ private createExecutableStrategy;
64
+ private settle;
65
+ private bindStrategyActions;
66
+ private createFailureError;
67
+ }
68
+ /**
69
+ * Creates a DI-aware bridge for a Passport.js strategy.
70
+ *
71
+ * @param name Unique name for the strategy.
72
+ * @param strategyToken Token representing the Passport.js strategy implementation.
73
+ * @param options Configuration for principal mapping and authentication options.
74
+ * @returns A bridge object containing providers and the strategy registration.
75
+ */
76
+ export declare function createPassportJsStrategyBridge(name: string, strategyToken: Token<PassportJsStrategyLike>, options?: PassportJsAuthStrategyOptions): PassportJsStrategyBridge;
77
+ //# sourceMappingURL=passport-js.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passport-js.d.ts","sourceRoot":"","sources":["../../src/adapters/passport-js.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAU7F;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAC5D;AAaD;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,iDAAiD;IACjD,OAAO,EAAE,YAAY,CAAC;IACtB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yDAAyD;IACzD,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE,8BAA8B,KAAK,SAAS,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,sEAAsE;IACtE,YAAY,CAAC,EAAE,yBAAyB,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AA2FD;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,YAAY;IAIvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuE;gBAGjF,gBAAgB,EAAE,sBAAsB,EACxC,OAAO,GAAE,6BAAkC;IAG9D,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,iBAAiB,CAAC;IA0B3E,OAAO,CAAC,wBAAwB;IAmBhC,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,mBAAmB;IAqC3B,OAAO,CAAC,kBAAkB;CAS3B;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,KAAK,CAAC,sBAAsB,CAAC,EAC5C,OAAO,GAAE,6BAAkC,GAC1C,wBAAwB,CAwB1B"}
@@ -0,0 +1,230 @@
1
+ import { AuthenticationFailedError, AuthenticationRequiredError } from '../errors.js';
2
+ import { normalizePrincipalScopes } from '../scope.js';
3
+
4
+ /**
5
+ * Represents a Passport.js strategy-like object that implements
6
+ * the `authenticate` method.
7
+ */
8
+
9
+ /**
10
+ * Input for the principal mapper that converts Passport.js user data
11
+ * into a fluo {@link Principal}.
12
+ */
13
+
14
+ /**
15
+ * A function type that maps Passport.js user data to a fluo {@link Principal}.
16
+ */
17
+
18
+ /**
19
+ * Configuration options for the Passport.js authentication strategy.
20
+ */
21
+
22
+ /**
23
+ * Bridge interface containing DI providers and strategy registration for Passport.js.
24
+ */
25
+
26
+ function toStringArray(value) {
27
+ if (!Array.isArray(value)) {
28
+ return undefined;
29
+ }
30
+ const items = value.filter(item => typeof item === 'string');
31
+ return items.length > 0 ? items : undefined;
32
+ }
33
+ function extractSubject(user) {
34
+ if (typeof user.sub === 'string' && user.sub.length > 0) {
35
+ return user.sub;
36
+ }
37
+ if (typeof user.id === 'string' && user.id.length > 0) {
38
+ return user.id;
39
+ }
40
+ if (typeof user.id === 'number') {
41
+ return String(user.id);
42
+ }
43
+ if (typeof user.userId === 'string' && user.userId.length > 0) {
44
+ return user.userId;
45
+ }
46
+ return undefined;
47
+ }
48
+ function defaultPrincipalMapper(input) {
49
+ if (typeof input.user !== 'object' || input.user === null) {
50
+ throw new AuthenticationFailedError('Passport strategy returned an invalid user payload.');
51
+ }
52
+ const claims = {
53
+ ...input.user
54
+ };
55
+ const subject = extractSubject(claims);
56
+ if (!subject) {
57
+ throw new AuthenticationFailedError('Passport strategy returned a user payload without a subject or id.');
58
+ }
59
+ const issuer = typeof claims.iss === 'string' ? claims.iss : undefined;
60
+ const audience = typeof claims.aud === 'string' || Array.isArray(claims.aud) ? claims.aud : undefined;
61
+ return {
62
+ audience,
63
+ claims,
64
+ issuer,
65
+ roles: toStringArray(claims.roles),
66
+ scopes: normalizePrincipalScopes(claims),
67
+ subject
68
+ };
69
+ }
70
+ function extractChallengeMessage(challenge) {
71
+ if (typeof challenge === 'string' && challenge.length > 0) {
72
+ return challenge;
73
+ }
74
+ if (typeof challenge === 'object' && challenge !== null) {
75
+ const message = challenge.message;
76
+ if (typeof message === 'string' && message.length > 0) {
77
+ return message;
78
+ }
79
+ }
80
+ return undefined;
81
+ }
82
+ function cloneStrategyStateValue(value) {
83
+ if (Array.isArray(value)) {
84
+ return value.slice();
85
+ }
86
+ if (value && typeof value === 'object') {
87
+ try {
88
+ return structuredClone(value);
89
+ } catch {
90
+ return value;
91
+ }
92
+ }
93
+ return value;
94
+ }
95
+
96
+ /**
97
+ * A bridge strategy that allows using Passport.js strategies within the fluo
98
+ * authentication framework.
99
+ */
100
+ export class PassportJsAuthStrategy {
101
+ requestState = new WeakMap();
102
+ constructor(strategyTemplate, options = {}) {
103
+ this.strategyTemplate = strategyTemplate;
104
+ this.options = options;
105
+ }
106
+ authenticate(context) {
107
+ const response = context.requestContext.response;
108
+ const request = context.requestContext.request.raw ?? context.requestContext.request;
109
+ const strategy = this.createExecutableStrategy();
110
+ const mapPrincipal = this.options.mapPrincipal ?? defaultPrincipalMapper;
111
+ return new Promise((resolve, reject) => {
112
+ this.requestState.set(strategy, {
113
+ context,
114
+ mapPrincipal,
115
+ reject,
116
+ resolve,
117
+ response,
118
+ settled: false
119
+ });
120
+ this.bindStrategyActions(strategy);
121
+ try {
122
+ strategy.authenticate(request, this.options.authenticateOptions);
123
+ } catch (error) {
124
+ this.settle(strategy, () => reject(error));
125
+ }
126
+ });
127
+ }
128
+ createExecutableStrategy() {
129
+ const template = this.strategyTemplate;
130
+ const strategy = Object.create(Object.getPrototypeOf(this.strategyTemplate));
131
+ for (const key of Reflect.ownKeys(template)) {
132
+ const value = Reflect.get(template, key);
133
+ if (typeof value === 'function') {
134
+ strategy[key] = value.bind(strategy);
135
+ continue;
136
+ }
137
+ strategy[key] = cloneStrategyStateValue(value);
138
+ }
139
+ return strategy;
140
+ }
141
+ settle(strategy, handler) {
142
+ const state = this.requestState.get(strategy);
143
+ if (!state || state.settled) {
144
+ return;
145
+ }
146
+ state.settled = true;
147
+ try {
148
+ handler(state);
149
+ } finally {
150
+ this.requestState.delete(strategy);
151
+ }
152
+ }
153
+ bindStrategyActions(strategy) {
154
+ strategy.success = (user, info) => {
155
+ this.settle(strategy, state => {
156
+ try {
157
+ state.resolve(state.mapPrincipal({
158
+ context: state.context,
159
+ info,
160
+ user
161
+ }));
162
+ } catch (error) {
163
+ state.reject(error);
164
+ }
165
+ });
166
+ };
167
+ strategy.fail = (challenge, status) => {
168
+ this.settle(strategy, state => {
169
+ state.reject(this.createFailureError(challenge, status));
170
+ });
171
+ };
172
+ strategy.redirect = (url, status = 302) => {
173
+ this.settle(strategy, state => {
174
+ state.response.redirect(status, url);
175
+ state.resolve({
176
+ handled: true
177
+ });
178
+ });
179
+ };
180
+ strategy.pass = () => {
181
+ this.settle(strategy, state => {
182
+ state.reject(new AuthenticationRequiredError());
183
+ });
184
+ };
185
+ strategy.error = error => {
186
+ this.settle(strategy, state => {
187
+ state.reject(error);
188
+ });
189
+ };
190
+ }
191
+ createFailureError(challenge, status) {
192
+ const message = extractChallengeMessage(challenge) ?? 'Authentication required.';
193
+ if (status === 401 || status === undefined) {
194
+ return new AuthenticationRequiredError(message);
195
+ }
196
+ return new AuthenticationFailedError(message);
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Creates a DI-aware bridge for a Passport.js strategy.
202
+ *
203
+ * @param name Unique name for the strategy.
204
+ * @param strategyToken Token representing the Passport.js strategy implementation.
205
+ * @param options Configuration for principal mapping and authentication options.
206
+ * @returns A bridge object containing providers and the strategy registration.
207
+ */
208
+ export function createPassportJsStrategyBridge(name, strategyToken, options = {}) {
209
+ const adapterToken = Symbol.for(`fluo.passport.passport-js.adapter.${name}`);
210
+ const optionsToken = Symbol.for(`fluo.passport.passport-js.options.${name}`);
211
+ return {
212
+ providers: [{
213
+ provide: optionsToken,
214
+ useValue: {
215
+ ...options
216
+ }
217
+ }, {
218
+ provide: adapterToken,
219
+ inject: [strategyToken, optionsToken],
220
+ useFactory: (...deps) => {
221
+ const [strategy, resolvedOptions] = deps;
222
+ return new PassportJsAuthStrategy(strategy, resolvedOptions);
223
+ }
224
+ }],
225
+ strategy: {
226
+ name,
227
+ token: adapterToken
228
+ }
229
+ };
230
+ }
@@ -0,0 +1,65 @@
1
+ import type { Provider } from '@fluojs/di';
2
+ import { type ModuleType } from '@fluojs/runtime';
3
+ import { type CookieAuthOptions } from './cookie-auth.js';
4
+ import { type CookieManagerConfig } from './cookie-manager.js';
5
+ import type { AuthStrategyRegistration } from '../types.js';
6
+ type CookieAuthModuleType = ModuleType;
7
+ /**
8
+ * Configures the built-in cookie-auth strategy and cookie manager preset.
9
+ */
10
+ export interface CookieAuthPresetConfig {
11
+ cookieAuth?: CookieAuthOptions;
12
+ cookieManager?: CookieManagerConfig;
13
+ }
14
+ /**
15
+ * Creates the passport strategy registration for the built-in cookie preset.
16
+ *
17
+ * @returns The named strategy registration consumed by `PassportModule.forRoot(...)`.
18
+ */
19
+ export declare function createCookieAuthStrategyRegistration(): AuthStrategyRegistration;
20
+ /**
21
+ * Creates a compatibility preset bundle for manual provider composition.
22
+ *
23
+ * @param config Optional cookie strategy and cookie manager configuration.
24
+ * @returns The preset providers plus the matching cookie strategy registration.
25
+ */
26
+ export declare function createCookieAuthPreset(config?: CookieAuthPresetConfig): {
27
+ providers: Provider[];
28
+ strategy: AuthStrategyRegistration;
29
+ };
30
+ /**
31
+ * Canonical module-first entrypoint for the built-in cookie-auth preset.
32
+ */
33
+ export declare class CookieAuthModule {
34
+ /**
35
+ * Registers the cookie-auth strategy and `CookieManager` preset as a module.
36
+ *
37
+ * @param config Optional cookie strategy and cookie manager configuration.
38
+ * @returns A module definition that exports `CookieAuthStrategy` and `CookieManager`.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { Module } from '@fluojs/core';
43
+ * import {
44
+ * CookieAuthModule,
45
+ * CookieAuthStrategy,
46
+ * COOKIE_AUTH_STRATEGY_NAME,
47
+ * PassportModule,
48
+ * } from '@fluojs/passport';
49
+ *
50
+ * @Module({
51
+ * imports: [
52
+ * CookieAuthModule.forRoot(),
53
+ * PassportModule.forRoot(
54
+ * { defaultStrategy: COOKIE_AUTH_STRATEGY_NAME },
55
+ * [{ name: COOKIE_AUTH_STRATEGY_NAME, token: CookieAuthStrategy }],
56
+ * ),
57
+ * ],
58
+ * })
59
+ * export class AuthModule {}
60
+ * ```
61
+ */
62
+ static forRoot(config?: CookieAuthPresetConfig): CookieAuthModuleType;
63
+ }
64
+ export {};
65
+ //# sourceMappingURL=cookie-auth-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-auth-module.d.ts","sourceRoot":"","sources":["../../src/cookie/cookie-auth-module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,KAAK,oBAAoB,GAAG,UAAU,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAiBD;;;;GAIG;AACH,wBAAgB,oCAAoC,IAAI,wBAAwB,CAK/E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG;IACvE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,EAAE,wBAAwB,CAAC;CACpC,CAKA;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,oBAAoB;CAQtE"}
@@ -0,0 +1,84 @@
1
+ import { defineModule } from '@fluojs/runtime';
2
+ import { COOKIE_AUTH_OPTIONS, COOKIE_AUTH_STRATEGY_NAME, CookieAuthStrategy } from './cookie-auth.js';
3
+ import { CookieManager } from './cookie-manager.js';
4
+
5
+ /**
6
+ * Configures the built-in cookie-auth strategy and cookie manager preset.
7
+ */
8
+
9
+ function createCookieAuthPresetProviders(config) {
10
+ return [{
11
+ provide: COOKIE_AUTH_OPTIONS,
12
+ useValue: config?.cookieAuth ?? {}
13
+ }, CookieAuthStrategy, {
14
+ inject: [],
15
+ provide: CookieManager,
16
+ useFactory: () => new CookieManager(config?.cookieManager)
17
+ }];
18
+ }
19
+
20
+ /**
21
+ * Creates the passport strategy registration for the built-in cookie preset.
22
+ *
23
+ * @returns The named strategy registration consumed by `PassportModule.forRoot(...)`.
24
+ */
25
+ export function createCookieAuthStrategyRegistration() {
26
+ return {
27
+ name: COOKIE_AUTH_STRATEGY_NAME,
28
+ token: CookieAuthStrategy
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Creates a compatibility preset bundle for manual provider composition.
34
+ *
35
+ * @param config Optional cookie strategy and cookie manager configuration.
36
+ * @returns The preset providers plus the matching cookie strategy registration.
37
+ */
38
+ export function createCookieAuthPreset(config) {
39
+ return {
40
+ providers: createCookieAuthPresetProviders(config),
41
+ strategy: createCookieAuthStrategyRegistration()
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Canonical module-first entrypoint for the built-in cookie-auth preset.
47
+ */
48
+ export class CookieAuthModule {
49
+ /**
50
+ * Registers the cookie-auth strategy and `CookieManager` preset as a module.
51
+ *
52
+ * @param config Optional cookie strategy and cookie manager configuration.
53
+ * @returns A module definition that exports `CookieAuthStrategy` and `CookieManager`.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { Module } from '@fluojs/core';
58
+ * import {
59
+ * CookieAuthModule,
60
+ * CookieAuthStrategy,
61
+ * COOKIE_AUTH_STRATEGY_NAME,
62
+ * PassportModule,
63
+ * } from '@fluojs/passport';
64
+ *
65
+ * @Module({
66
+ * imports: [
67
+ * CookieAuthModule.forRoot(),
68
+ * PassportModule.forRoot(
69
+ * { defaultStrategy: COOKIE_AUTH_STRATEGY_NAME },
70
+ * [{ name: COOKIE_AUTH_STRATEGY_NAME, token: CookieAuthStrategy }],
71
+ * ),
72
+ * ],
73
+ * })
74
+ * export class AuthModule {}
75
+ * ```
76
+ */
77
+ static forRoot(config) {
78
+ class CookieAuthRuntimeModule extends CookieAuthModule {}
79
+ return defineModule(CookieAuthRuntimeModule, {
80
+ exports: [CookieAuthStrategy, CookieManager],
81
+ providers: createCookieAuthPresetProviders(config)
82
+ });
83
+ }
84
+ }
@@ -0,0 +1,40 @@
1
+ import type { GuardContext } from '@fluojs/http';
2
+ import { DefaultJwtVerifier } from '@fluojs/jwt';
3
+ import type { AuthStrategy, AuthStrategyResult } from '../types.js';
4
+ /**
5
+ * Provides cookie-auth strategy options through dependency injection.
6
+ */
7
+ export declare const COOKIE_AUTH_OPTIONS: unique symbol;
8
+ /**
9
+ * Configures cookie names and fallback behavior for cookie-based authentication.
10
+ */
11
+ export interface CookieAuthOptions {
12
+ accessTokenCookieName?: string;
13
+ refreshTokenCookieName?: string;
14
+ requireAccessToken?: boolean;
15
+ }
16
+ /**
17
+ * Supplies the default cookie names and access-token requirement for cookie auth.
18
+ */
19
+ export declare const DEFAULT_COOKIE_AUTH_OPTIONS: Required<CookieAuthOptions>;
20
+ /**
21
+ * Normalizes optional cookie-auth settings into a fully populated options object.
22
+ *
23
+ * @param options Partial cookie-auth configuration supplied by the caller.
24
+ * @returns Cookie-auth options with defaults applied.
25
+ */
26
+ export declare function normalizeCookieAuthOptions(options?: CookieAuthOptions): Required<CookieAuthOptions>;
27
+ /**
28
+ * Authenticates requests by reading and verifying JWTs from HTTP cookies.
29
+ */
30
+ export declare class CookieAuthStrategy implements AuthStrategy {
31
+ private readonly verifier;
32
+ private readonly options;
33
+ constructor(verifier: DefaultJwtVerifier, options?: CookieAuthOptions);
34
+ authenticate(context: GuardContext): Promise<AuthStrategyResult>;
35
+ }
36
+ /**
37
+ * Identifies the built-in cookie authentication strategy.
38
+ */
39
+ export declare const COOKIE_AUTH_STRATEGY_NAME = "cookie";
40
+ //# sourceMappingURL=cookie-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-auth.d.ts","sourceRoot":"","sources":["../../src/cookie/cookie-auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAAkD,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,iBAAiB,CAInE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAMnG;AAED;;GAEG;AACH,qBACa,kBAAmB,YAAW,YAAY;IAInD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAH3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;gBAGnC,QAAQ,EAAE,kBAAkB,EAC7C,OAAO,CAAC,EAAE,iBAAiB;IAKvB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA6CvE;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,WAAW,CAAC"}
@@ -0,0 +1,101 @@
1
+ let _initClass;
2
+ function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
+ function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
+ import { Inject } from '@fluojs/core';
8
+ import { DefaultJwtVerifier } from '@fluojs/jwt';
9
+ import { AuthenticationRequiredError } from '../errors.js';
10
+ /**
11
+ * Provides cookie-auth strategy options through dependency injection.
12
+ */
13
+ export const COOKIE_AUTH_OPTIONS = Symbol.for('fluo.passport.cookie-auth-options');
14
+
15
+ /**
16
+ * Configures cookie names and fallback behavior for cookie-based authentication.
17
+ */
18
+
19
+ /**
20
+ * Supplies the default cookie names and access-token requirement for cookie auth.
21
+ */
22
+ export const DEFAULT_COOKIE_AUTH_OPTIONS = {
23
+ accessTokenCookieName: 'access_token',
24
+ refreshTokenCookieName: 'refresh_token',
25
+ requireAccessToken: true
26
+ };
27
+
28
+ /**
29
+ * Normalizes optional cookie-auth settings into a fully populated options object.
30
+ *
31
+ * @param options Partial cookie-auth configuration supplied by the caller.
32
+ * @returns Cookie-auth options with defaults applied.
33
+ */
34
+ export function normalizeCookieAuthOptions(options) {
35
+ return {
36
+ accessTokenCookieName: options?.accessTokenCookieName ?? DEFAULT_COOKIE_AUTH_OPTIONS.accessTokenCookieName,
37
+ refreshTokenCookieName: options?.refreshTokenCookieName ?? DEFAULT_COOKIE_AUTH_OPTIONS.refreshTokenCookieName,
38
+ requireAccessToken: options?.requireAccessToken ?? DEFAULT_COOKIE_AUTH_OPTIONS.requireAccessToken
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Authenticates requests by reading and verifying JWTs from HTTP cookies.
44
+ */
45
+ let _CookieAuthStrategy;
46
+ class CookieAuthStrategy {
47
+ static {
48
+ [_CookieAuthStrategy, _initClass] = _applyDecs(this, [Inject(DefaultJwtVerifier, COOKIE_AUTH_OPTIONS)], []).c;
49
+ }
50
+ options;
51
+ constructor(verifier, options) {
52
+ this.verifier = verifier;
53
+ this.options = normalizeCookieAuthOptions(options);
54
+ }
55
+ async authenticate(context) {
56
+ const request = context.requestContext.request;
57
+ const cookies = request.cookies;
58
+ if (!cookies || typeof cookies !== 'object') {
59
+ if (this.options.requireAccessToken) {
60
+ throw new AuthenticationRequiredError('Access token cookie is required.');
61
+ }
62
+ return {
63
+ claims: {},
64
+ subject: 'anonymous'
65
+ };
66
+ }
67
+ const accessToken = cookies[this.options.accessTokenCookieName];
68
+ if (!accessToken) {
69
+ if (this.options.requireAccessToken) {
70
+ throw new AuthenticationRequiredError('Access token cookie is required.');
71
+ }
72
+ return {
73
+ claims: {},
74
+ subject: 'anonymous'
75
+ };
76
+ }
77
+ try {
78
+ const principal = await this.verifier.verifyAccessToken(accessToken);
79
+ return {
80
+ claims: principal.claims,
81
+ roles: principal.roles,
82
+ scopes: principal.scopes,
83
+ subject: principal.subject
84
+ };
85
+ } catch (error) {
86
+ if (error instanceof Error) {
87
+ throw new AuthenticationRequiredError(error.message);
88
+ }
89
+ throw new AuthenticationRequiredError('Access token verification failed.');
90
+ }
91
+ }
92
+ static {
93
+ _initClass();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Identifies the built-in cookie authentication strategy.
99
+ */
100
+ export { _CookieAuthStrategy as CookieAuthStrategy };
101
+ export const COOKIE_AUTH_STRATEGY_NAME = 'cookie';
@@ -0,0 +1,34 @@
1
+ import type { FrameworkResponse } from '@fluojs/http';
2
+ import { type CookieAuthOptions } from './cookie-auth.js';
3
+ export interface CookieOptions {
4
+ httpOnly?: boolean;
5
+ secure?: boolean;
6
+ sameSite?: 'strict' | 'lax' | 'none';
7
+ path?: string;
8
+ domain?: string;
9
+ maxAge?: number;
10
+ }
11
+ export interface SetCookieOptions extends CookieOptions {
12
+ accessTokenTtlSeconds?: number;
13
+ refreshTokenTtlSeconds?: number;
14
+ }
15
+ export interface CookieManagerConfig extends CookieAuthOptions {
16
+ cookieOptions?: CookieOptions;
17
+ }
18
+ type NormalizedCookieOptions = Omit<Required<CookieOptions>, 'domain' | 'maxAge'> & Pick<CookieOptions, 'domain' | 'maxAge'>;
19
+ export declare const DEFAULT_COOKIE_OPTIONS: NormalizedCookieOptions;
20
+ export declare class CookieManager {
21
+ private readonly options;
22
+ private readonly cookieOptions;
23
+ constructor(config?: CookieManagerConfig);
24
+ setAccessTokenCookie(response: FrameworkResponse, token: string, ttlSeconds?: number): void;
25
+ setRefreshTokenCookie(response: FrameworkResponse, token: string, ttlSeconds?: number): void;
26
+ clearAccessTokenCookie(response: FrameworkResponse): void;
27
+ clearRefreshTokenCookie(response: FrameworkResponse): void;
28
+ clearAllCookies(response: FrameworkResponse): void;
29
+ setAuthCookies(response: FrameworkResponse, accessToken: string, accessTokenTtlSeconds?: number, refreshToken?: string, refreshTokenTtlSeconds?: number): void;
30
+ private appendSetCookie;
31
+ }
32
+ export declare function createCookieManager(config?: CookieManagerConfig): CookieManager;
33
+ export {};
34
+ //# sourceMappingURL=cookie-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-manager.d.ts","sourceRoot":"","sources":["../../src/cookie/cookie-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAA+B,KAAK,iBAAiB,EAA8B,MAAM,kBAAkB,CAAC;AAEnH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,KAAK,uBAAuB,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAC/E,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC;AAE3C,eAAO,MAAM,sBAAsB,EAAE,uBAOpC,CAAC;AAuCF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;gBAE5C,MAAM,CAAC,EAAE,mBAAmB;IAYxC,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAa3F,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAa5F,sBAAsB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IASzD,uBAAuB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAS1D,eAAe,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKlD,cAAc,CACZ,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,MAAM,EACnB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,YAAY,CAAC,EAAE,MAAM,EACrB,sBAAsB,CAAC,EAAE,MAAM,GAC9B,IAAI;IAQP,OAAO,CAAC,eAAe;CAWxB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,aAAa,CAE/E"}