@soapjs/soap-auth 0.4.4 → 1.0.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 (32) hide show
  1. package/README.md +286 -125
  2. package/build/index.d.ts +1 -0
  3. package/build/index.js +1 -0
  4. package/build/recipes/auth-config.recipes.d.ts +40 -0
  5. package/build/recipes/auth-config.recipes.js +135 -0
  6. package/build/recipes/http-context.helpers.d.ts +13 -0
  7. package/build/recipes/http-context.helpers.js +64 -0
  8. package/build/recipes/index.d.ts +3 -0
  9. package/build/recipes/index.js +19 -0
  10. package/build/recipes/oauth2-presets.d.ts +20 -0
  11. package/build/recipes/oauth2-presets.js +74 -0
  12. package/build/services/pkce.service.js +8 -6
  13. package/build/soap-auth.js +62 -0
  14. package/build/strategies/jwt/jwt.strategy.d.ts +2 -2
  15. package/build/strategies/jwt/jwt.strategy.js +6 -6
  16. package/build/strategies/oauth2/hybrid.oauth2.strategy.js +2 -2
  17. package/build/strategies/oauth2/oauth2.strategy.d.ts +1 -1
  18. package/build/strategies/oauth2/oauth2.strategy.js +12 -8
  19. package/build/strategies/oauth2/oauth2.types.d.ts +8 -3
  20. package/build/strategies/oauth2/providers/configurable-hybrid-oauth2.strategy.d.ts +19 -0
  21. package/build/strategies/oauth2/providers/configurable-hybrid-oauth2.strategy.js +85 -0
  22. package/build/strategies/oauth2/providers/configurable-oauth2.strategy.d.ts +11 -0
  23. package/build/strategies/oauth2/providers/configurable-oauth2.strategy.js +46 -0
  24. package/build/strategies/oauth2/providers/index.d.ts +2 -0
  25. package/build/strategies/oauth2/providers/index.js +2 -0
  26. package/build/strategies/oauth2/providers/provider.types.d.ts +3 -0
  27. package/build/strategies/token-auth.strategy.d.ts +2 -2
  28. package/build/strategies/token-auth.strategy.js +2 -2
  29. package/build/types.d.ts +22 -12
  30. package/package.json +137 -13
  31. package/.claude/settings.local.json +0 -20
  32. package/jest.config.unit.json +0 -10
package/README.md CHANGED
@@ -1,174 +1,335 @@
1
- # SoapAuth - Modular Authentication Solution
1
+ # SoapAuth
2
2
 
3
- SoapAuth is a flexible library for handling authentication and identity management. It allows you to easily implement various authentication strategies such as JWT, OAuth2, Basic Auth, Local Auth, API Key, and more. As part of the **@soapjs** ecosystem, it can be easily extended with additional components like **soap**, **soap-express**, and **soap-cli**.
3
+ Authentication strategies, session handling, MFA, and token helpers for the SoapJS ecosystem.
4
+
5
+ `@soapjs/soap-auth` provides composable authentication primitives for HTTP and socket applications. It includes JWT, local credentials, basic auth, API key auth, built-in OAuth2 social providers, sessions, roles, rate limiting, account lockout, password helpers, MFA/TOTP, PKCE, and JWKS verification.
6
+
7
+ The package does not depend on Passport or provider SDKs. Built-in and configurable OAuth2 strategies use platform `fetch` plus user-provided mapping callbacks, so applications can start quickly and still replace any part of the auth flow with their own implementation.
4
8
 
5
9
  ## Installation
10
+
6
11
  ```sh
7
- npm install @soapjs/soap-auth
12
+ npm install @soapjs/soap-auth @soapjs/soap
8
13
  ```
9
14
 
10
- ## Key Features
11
- - **Supports multiple authentication strategies** (JWT, OAuth2, API Key, Basic, Local, Hybrid OAuth2).
12
- - **Works with both HTTP and WebSocket protocols.**
13
- - **Manages sessions, MFA, roles, account locks, and rate limiting.**
14
- - **Easy configuration and extendability.**
15
- - **Integration with frameworks like Express, NestJS, etc.**
15
+ ## Requirements
16
+
17
+ - Node.js 24.17.0 or newer
18
+ - `@soapjs/soap` 0.14 or newer
19
+
20
+ ## Quick Start
21
+
22
+ ```ts
23
+ import { createJwtAuthConfig, SoapAuth } from "@soapjs/soap-auth";
24
+
25
+ const auth = await SoapAuth.create({
26
+ http: {
27
+ jwt: createJwtAuthConfig({
28
+ accessSecret: process.env.JWT_ACCESS_SECRET!,
29
+ refreshSecret: process.env.JWT_REFRESH_SECRET!,
30
+ user: {
31
+ fetchUser: async (payload) => users.findById((payload as any).id),
32
+ },
33
+ }),
34
+ },
35
+ });
36
+
37
+ const result = await auth.getHttpStrategy("jwt").authenticate(context);
38
+ ```
16
39
 
17
- ---
40
+ ## Recipes
18
41
 
19
- ## Basic Usage
20
- ```typescript
21
- import { SoapAuth, JwtStrategy } from "@soapjs/soap-auth";
42
+ Recipes are framework-neutral config helpers. They return plain SoapAuth config objects and do not import Express, Passport, provider SDKs, or any other adapter library.
22
43
 
23
- const auth = new SoapAuth();
24
- auth.addStrategy(new JwtStrategy({ secret: "super-secret-key" }), "jwt", "http");
25
- // ...
26
- const result = await auth.getHttpStrategy<JwtStrategy>("jwt").authenticate(request);
27
- console.log(result.user);
44
+ ```ts
45
+ import {
46
+ createApiKeyAuthConfig,
47
+ createHybridOAuth2ProviderConfig,
48
+ createJwtAuthConfig,
49
+ createLocalAuthConfig,
50
+ createOAuth2ProviderConfig,
51
+ oauth2ProviderEndpoints,
52
+ } from "@soapjs/soap-auth";
28
53
  ```
29
54
 
30
- ---
55
+ Available recipes:
31
56
 
32
- ## Supported Authentication Strategies
57
+ - `createJwtAuthConfig(...)`
58
+ - `createLocalAuthConfig(...)`
59
+ - `createBasicAuthConfig(...)`
60
+ - `createApiKeyAuthConfig(...)`
61
+ - `createOAuth2ProviderConfig(...)`
62
+ - `createHybridOAuth2ProviderConfig(...)`
63
+ - `oauth2ProviderEndpoints.auth0(...)`
64
+ - `oauth2ProviderEndpoints.keycloak(...)`
65
+ - `oauth2ProviderEndpoints.discord()`
66
+ - `oauth2ProviderEndpoints.google()`
67
+ - `oauth2ProviderEndpoints.github()`
68
+ - `oauth2ProviderEndpoints.facebook()`
33
69
 
34
- SoapAuth supports multiple authentication strategies. Below is a description and example configuration for each.
70
+ Recipes are also available from `@soapjs/soap-auth/recipes`.
35
71
 
36
- ### **JWT Strategy** *(Token-based authentication)*
37
- ```typescript
38
- import { JwtStrategy } from "@soapjs/soap-auth";
72
+ Type-only subpath imports are supported for TypeScript projects using classic
73
+ `moduleResolution: node`:
39
74
 
40
- auth.addStrategy(new JwtStrategy({
41
- secret: "your-secret-key",
42
- accessToken: {
43
- expiresIn: "1h",
44
- },
45
- refreshToken: {
46
- expiresIn: "7d",
47
- },
48
- }), "jwt", "http");
75
+ ```ts
76
+ import type { StorageContext } from "@soapjs/soap-auth/types";
77
+ import type { CookieOptions } from "@soapjs/soap-auth/recipes";
49
78
  ```
50
79
 
51
- ### **OAuth2 Strategy** *(OAuth 2.0 authentication)*
52
- ```typescript
53
- import { OAuth2Strategy } from "@soapjs/soap-auth";
54
-
55
- auth.addStrategy(new OAuth2Strategy({
56
- clientId: "your-client-id",
57
- clientSecret: "your-client-secret",
58
- redirectUri: "https://your-app.com/callback",
59
- endpoints: {
60
- authorizationUrl: "https://auth.server.com/auth",
61
- tokenUrl: "https://auth.server.com/token",
80
+ ## Factory Configuration
81
+
82
+ `SoapAuth.create()` registers built-in strategies from config:
83
+
84
+ - `http.jwt` as `jwt`
85
+ - `http.local` as `local`
86
+ - `http.basic` as `basic`
87
+ - `http.apiKey` as `api-key`
88
+ - `http.oauth2.google` as `google`
89
+ - `http.oauth2.github` as `github`
90
+ - `http.oauth2.facebook` as `facebook`
91
+ - any other `http.oauth2.<name>` with OAuth2 endpoints as `<name>`
92
+ - any `http.hybridOAuth2.<name>` with OAuth2 endpoints as `<name>`
93
+ - `socket.jwt` as `jwt`
94
+ - `socket.apiKey` as `api-key`
95
+
96
+ Custom strategies can be registered through `http.custom`, `socket.custom`, or manually with `addStrategy(strategy, name, category)`.
97
+
98
+ ## Local Credentials
99
+
100
+ ```ts
101
+ import { createLocalAuthConfig } from "@soapjs/soap-auth";
102
+
103
+ const auth = await SoapAuth.create({
104
+ http: {
105
+ local: createLocalAuthConfig({
106
+ credentials: {
107
+ extractCredentials: (ctx: any) => ({
108
+ identifier: ctx.body.email,
109
+ password: ctx.body.password,
110
+ }),
111
+ verifyCredentials: async (identifier, password) =>
112
+ users.verifyPassword(identifier, password),
113
+ },
114
+ user: {
115
+ fetchUser: async (identifier) => users.findByEmail(String(identifier)),
116
+ },
117
+ basePath: "/auth",
118
+ }),
62
119
  },
63
- }), "oauth2", "http");
120
+ });
64
121
  ```
65
122
 
66
- ### **API Key Strategy** *(Key-based authentication)*
67
- ```typescript
68
- import { ApiKeyStrategy } from "@soapjs/soap-auth";
123
+ ## API Key
69
124
 
70
- auth.addStrategy(new ApiKeyStrategy({
71
- extractApiKey: (ctx) => ctx.headers["x-api-key"],
72
- retrieveUserByApiKey: async (key) => {
73
- return mockDatabase.findUserByApiKey(key);
125
+ ```ts
126
+ import { createApiKeyAuthConfig } from "@soapjs/soap-auth";
127
+
128
+ const auth = await SoapAuth.create({
129
+ http: {
130
+ apiKey: createApiKeyAuthConfig({
131
+ keyType: "long-term",
132
+ extractApiKey: (ctx: any) => ctx.headers["x-api-key"] ?? null,
133
+ retrieveUserByApiKey: async (apiKey) => apiKeys.findUser(apiKey),
134
+ isApiKeyExpired: async (apiKey) => apiKeys.isExpired(apiKey),
135
+ trackApiKeyUsage: async (apiKey) => apiKeys.touch(apiKey),
136
+ }),
74
137
  },
75
- }), "apikey", "http");
138
+ });
76
139
  ```
77
140
 
78
- ### **Basic Auth Strategy** *(Username & Password authentication)*
79
- ```typescript
80
- import { BasicStrategy } from "@soapjs/soap-auth";
141
+ ## Sessions
142
+
143
+ ```ts
144
+ import { MemorySessionStore, SoapAuth } from "@soapjs/soap-auth";
81
145
 
82
- auth.addStrategy(new BasicStrategy({
83
- extractCredentials: (ctx) => {
84
- return { identifier: ctx.body.username, password: ctx.body.password };
146
+ const auth = await SoapAuth.create({
147
+ session: {
148
+ secret: process.env.SESSION_SECRET!,
149
+ store: new MemorySessionStore(),
150
+ getSessionId: (ctx: any) =>
151
+ ctx.cookies?.SESSIONID ?? ctx.headers?.["x-session-id"] ?? null,
85
152
  },
86
- verifyCredentials: async (id, pass) => {
87
- return mockDatabase.verifyUser(id, pass);
153
+ http: {
154
+ local: localConfig,
88
155
  },
89
- }), "basic", "http");
156
+ });
90
157
  ```
91
158
 
92
- ### **Local Strategy** *(Custom authentication logic)*
93
- ```typescript
94
- import { LocalStrategy } from "@soapjs/soap-auth";
159
+ `MemorySessionStore` is useful for tests and local development. Production applications should provide a durable `SessionStore` backed by a database, Redis, or another shared storage system.
160
+
161
+ ## OAuth2 Providers
95
162
 
96
- auth.addStrategy(new LocalStrategy({
97
- extractCredentials: (ctx) => ({ identifier: ctx.query.email, password: ctx.query.pass }),
98
- verifyCredentials: async (id, pass) => {
99
- return mockDatabase.verifyUser(id, pass);
163
+ ```ts
164
+ const auth = await SoapAuth.create({
165
+ http: {
166
+ oauth2: {
167
+ google: {
168
+ clientId: process.env.GOOGLE_CLIENT_ID!,
169
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
170
+ redirectUri: "https://example.com/auth/google/callback",
171
+ },
172
+ github: {
173
+ clientId: process.env.GITHUB_CLIENT_ID!,
174
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
175
+ redirectUri: "https://example.com/auth/github/callback",
176
+ },
177
+ },
100
178
  },
101
- }), "local", "http");
179
+ });
102
180
  ```
103
181
 
104
- ### **Hybrid OAuth2 Strategy** *(Combination of multiple authentication methods)*
105
- ```typescript
106
- import { HybridOAuth2Strategy } from "@soapjs/soap-auth";
107
-
108
- auth.addStrategy(new HybridOAuth2Strategy({
109
- clientId: "your-client-id",
110
- clientSecret: "your-client-secret",
111
- oauth2: {
112
- endpoints: {
113
- authorizationUrl: "https://oauth.provider.com/auth",
114
- tokenUrl: "https://oauth.provider.com/token",
182
+ Providers with standard OAuth2/OIDC endpoints can use configurable OAuth2. Providers with unusual token exchange, user lookup, or redirect requirements can be implemented as a subclass of `OAuth2Strategy` or `HttpOAuth2Strategy` and registered through `http.custom`.
183
+
184
+ ## Configurable OAuth2 Providers
185
+
186
+ Most OAuth2/OIDC providers do not need a custom class. Provide the endpoints and a profile mapper:
187
+
188
+ ```ts
189
+ import { createOAuth2ProviderConfig } from "@soapjs/soap-auth";
190
+
191
+ const auth = await SoapAuth.create({
192
+ http: {
193
+ oauth2: {
194
+ auth0: createOAuth2ProviderConfig({
195
+ provider: "auth0",
196
+ clientId: process.env.AUTH0_CLIENT_ID!,
197
+ clientSecret: process.env.AUTH0_CLIENT_SECRET!,
198
+ redirectUri: "https://example.com/auth/auth0/callback",
199
+ presetOptions: { domain: "tenant.auth0.com" },
200
+ user: {
201
+ fetchUser: async () => null,
202
+ validateUser: async (profile: any) => ({
203
+ id: profile.sub,
204
+ email: profile.email,
205
+ username: profile.nickname ?? profile.name,
206
+ picture: profile.picture,
207
+ }),
208
+ },
209
+ }),
115
210
  },
116
211
  },
117
- }), "hybrid-oauth2", "http");
212
+ });
118
213
  ```
119
214
 
120
- ---
215
+ For providers without a `userinfo` endpoint, implement `user.fetchUser(accessToken)` and return your application user directly.
121
216
 
122
- ## Configuration & Extensions
123
- ### Role Management
124
- ```typescript
125
- role: {
126
- authorizeByRoles: async (user, roles) => roles.includes(user.role),
127
- roles: ["admin", "user"]
128
- }
129
- ```
130
- ### Multi-Factor Authentication (MFA)
131
- ```typescript
132
- mfa: {
133
- isMfaRequired: (user) => user.requiresMfa,
134
- validateMfaCode: async (user, code) => mockDatabase.checkMfaCode(user, code),
217
+ OAuth2 `state.persistence` and `nonce.persistence` callbacks receive the
218
+ current auth context:
219
+
220
+ ```ts
221
+ state: {
222
+ persistence: {
223
+ store: async (state, context, metadata) => {
224
+ await context.storeInCookie?.(state, { name: metadata?.key ?? "state" });
225
+ },
226
+ read: async (context, key) => context.getFromCookie?.(key ?? "state") ?? null,
227
+ remove: async (context, key) => {
228
+ await context.removeFromCookie?.(key ?? "state");
229
+ },
230
+ },
135
231
  }
136
232
  ```
137
- ### Account Locking after Failed Logins
138
- ```typescript
139
- lock: {
140
- isAccountLocked: async (account) => mockDatabase.isLocked(account),
141
- lockAccount: async (account) => mockDatabase.lock(account),
142
- }
233
+
234
+ This lets HTTP adapters such as `soap-express` persist OAuth state and nonce in
235
+ cookies, sessions, or request-scoped storage without global state.
236
+
237
+ ## Configurable Hybrid OAuth2
238
+
239
+ Hybrid OAuth2 tries existing JWT/session auth first, then falls back to OAuth2. This is useful when browser users log in through OAuth2 but API clients can keep using JWT.
240
+
241
+ ```ts
242
+ import { createHybridOAuth2ProviderConfig } from "@soapjs/soap-auth";
243
+
244
+ const auth = await SoapAuth.create({
245
+ session: sessionConfig,
246
+ http: {
247
+ jwt: jwtConfig,
248
+ hybridOAuth2: {
249
+ enterprise: createHybridOAuth2ProviderConfig({
250
+ provider: "enterprise",
251
+ clientId: process.env.IDP_CLIENT_ID!,
252
+ clientSecret: process.env.IDP_CLIENT_SECRET!,
253
+ redirectUri: "https://example.com/auth/enterprise/callback",
254
+ endpoints: {
255
+ authorizationUrl: "https://idp.example.com/authorize",
256
+ tokenUrl: "https://idp.example.com/token",
257
+ userInfoUrl: "https://idp.example.com/userinfo",
258
+ },
259
+ user: {
260
+ fetchUser: async () => null,
261
+ validateUser: async (profile: any) => ({
262
+ id: profile.sub,
263
+ email: profile.email,
264
+ }),
265
+ },
266
+ }),
267
+ },
268
+ },
269
+ });
143
270
  ```
144
- ### Rate Limiting
145
- ```typescript
146
- rateLimit: {
147
- checkRateLimit: async (ctx) => false, // No limits
148
- }
271
+
272
+ ## Custom Strategies
273
+
274
+ When the built-in config is not enough, implement `AuthStrategy` directly:
275
+
276
+ ```ts
277
+ const auth = await SoapAuth.create({
278
+ http: {
279
+ custom: {
280
+ internal: {
281
+ async authenticate(ctx: any) {
282
+ const user = await internalAuth.verify(ctx.headers.authorization);
283
+ return user ? { user } : null;
284
+ },
285
+ },
286
+ },
287
+ },
288
+ });
149
289
  ```
150
290
 
151
- ---
291
+ No external strategy package is required; custom strategies only need an `authenticate(context)` method.
292
+
293
+ ## MFA, Roles, Rate Limits, and Lockout
294
+
295
+ Shared controls can be attached to credential strategies:
296
+
297
+ ```ts
298
+ const localConfig = {
299
+ credentials,
300
+ user,
301
+ routes,
302
+ mfa: {
303
+ isMfaRequired: (user: any) => user.mfaEnabled,
304
+ extractMfaCode: (ctx: any) => ctx.body.mfaCode,
305
+ validateMfaCode: async (user: any, code: string) =>
306
+ mfa.verify(user.id, code),
307
+ },
308
+ role: {
309
+ roles: ["admin"],
310
+ authorizeByRoles: async (user: any, roles: string[]) =>
311
+ roles.includes(user.role),
312
+ },
313
+ rateLimit: {
314
+ checkRateLimit: async (ctx: any) => rateLimiter.isLimited(ctx.ip),
315
+ incrementRequestCount: async (ctx: any) => rateLimiter.increment(ctx.ip),
316
+ },
317
+ };
318
+ ```
152
319
 
153
- ## FAQ
154
- **How to report an issue?**
155
- Open an issue on GitHub.
320
+ ## Release Checks
156
321
 
157
- **How to extend `soap-auth` with custom strategies?**
158
- You can create your own class extending `BaseAuthStrategy` and implementing `authenticate()`.
322
+ Before publishing:
159
323
 
160
- ---
161
- ## Issues
162
- If you encounter any issues, please feel free to report them [here](https://github.com/soapjs/soap/issues/new/choose).
324
+ ```sh
325
+ npm run test:unit
326
+ npm run build
327
+ npm pack --dry-run
328
+ npm audit --omit=dev
329
+ ```
163
330
 
164
- ## Contact
165
- For any questions, collaboration interests, or support needs, you can contact us through the following:
331
+ The package publishes compiled CommonJS output from `build/` and TypeScript declarations.
166
332
 
167
- - Official:
168
- - Website: http://docs.soapjs.com
169
- - Radoslaw Kamysz:
170
- - Email: [radoslaw.kamysz@gmail.com](mailto:radoslaw.kamysz@gmail.com)
171
- - Warpcast: [@k4mr4ad](https://warpcast.com/k4mr4ad)
172
- - Twitter: [@radoslawkamysz](https://x.com/radoslawkamysz)
173
333
  ## License
174
- SoapAuth is licensed under the MIT License.
334
+
335
+ MIT
package/build/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from "./session";
2
2
  export * from "./services";
3
3
  export * from "./strategies";
4
4
  export * from "./tools";
5
+ export * from "./recipes";
5
6
  export * from "./errors";
6
7
  export * from "./types";
7
8
  export * from "./soap-auth";
package/build/index.js CHANGED
@@ -18,6 +18,7 @@ __exportStar(require("./session"), exports);
18
18
  __exportStar(require("./services"), exports);
19
19
  __exportStar(require("./strategies"), exports);
20
20
  __exportStar(require("./tools"), exports);
21
+ __exportStar(require("./recipes"), exports);
21
22
  __exportStar(require("./errors"), exports);
22
23
  __exportStar(require("./types"), exports);
23
24
  __exportStar(require("./soap-auth"), exports);
@@ -0,0 +1,40 @@
1
+ import { ApiKeyStrategyConfig } from "../strategies/api-key/api-key.types";
2
+ import { BasicStrategyConfig } from "../strategies/basic/basic.types";
3
+ import { JwtConfig } from "../strategies/jwt/jwt.types";
4
+ import { LocalStrategyConfig } from "../strategies/local/local.types";
5
+ import { OAuth2ProviderConfig } from "../strategies/oauth2/oauth2.types";
6
+ import { Auth0PresetOptions, FacebookPresetOptions, KeycloakPresetOptions, OAuth2ProviderPreset } from "./oauth2-presets";
7
+ import { AuthRouteConfig, TokenIssuerConfig, UserConfig } from "../types";
8
+ import { OAuth2Endpoints } from "../strategies/oauth2/oauth2.types";
9
+ type RouteOverrides = Partial<Record<string, Partial<AuthRouteConfig>>>;
10
+ export interface JwtAuthRecipeOptions<TContext = unknown, TUser = unknown> extends Omit<Partial<JwtConfig<TContext, TUser>>, "accessToken" | "refreshToken" | "routes"> {
11
+ accessSecret: string;
12
+ refreshSecret?: string;
13
+ accessToken?: Partial<TokenIssuerConfig<TContext>>;
14
+ refreshToken?: Partial<TokenIssuerConfig<TContext>>;
15
+ user?: UserConfig<TUser>;
16
+ routes?: RouteOverrides;
17
+ }
18
+ export declare function createJwtAuthConfig<TContext = unknown, TUser = unknown>(options: JwtAuthRecipeOptions<TContext, TUser>): JwtConfig<TContext, TUser>;
19
+ export interface LocalAuthRecipeOptions<TContext = unknown, TUser = unknown> extends Omit<LocalStrategyConfig<TContext, TUser>, "routes"> {
20
+ basePath?: string;
21
+ routes?: RouteOverrides;
22
+ }
23
+ export declare function createLocalAuthConfig<TContext = unknown, TUser = unknown>(options: LocalAuthRecipeOptions<TContext, TUser>): LocalStrategyConfig<TContext, TUser>;
24
+ export interface BasicAuthRecipeOptions<TContext = unknown, TUser = unknown> extends Omit<BasicStrategyConfig<TContext, TUser>, "routes"> {
25
+ basePath?: string;
26
+ routes?: RouteOverrides;
27
+ }
28
+ export declare function createBasicAuthConfig<TContext = unknown, TUser = unknown>(options: BasicAuthRecipeOptions<TContext, TUser>): BasicStrategyConfig<TContext, TUser>;
29
+ export interface ApiKeyAuthRecipeOptions<TContext = unknown, TUser = unknown> extends ApiKeyStrategyConfig<TContext, TUser> {
30
+ }
31
+ export declare function createApiKeyAuthConfig<TContext = unknown, TUser = unknown>(options: ApiKeyAuthRecipeOptions<TContext, TUser>): ApiKeyStrategyConfig<TContext, TUser>;
32
+ export interface OAuth2AuthRecipeOptions<TUser = unknown> extends Omit<OAuth2ProviderConfig<any, TUser>, "endpoints" | "routes"> {
33
+ provider: OAuth2ProviderPreset | string;
34
+ endpoints?: OAuth2Endpoints;
35
+ presetOptions?: Auth0PresetOptions | KeycloakPresetOptions | FacebookPresetOptions;
36
+ routes?: RouteOverrides;
37
+ }
38
+ export declare function createOAuth2ProviderConfig<TUser = unknown>(options: OAuth2AuthRecipeOptions<TUser>): OAuth2ProviderConfig<any, TUser>;
39
+ export declare function createHybridOAuth2ProviderConfig<TUser = unknown>(options: OAuth2AuthRecipeOptions<TUser>): OAuth2ProviderConfig<any, TUser>;
40
+ export {};
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHybridOAuth2ProviderConfig = exports.createOAuth2ProviderConfig = exports.createApiKeyAuthConfig = exports.createBasicAuthConfig = exports.createLocalAuthConfig = exports.createJwtAuthConfig = void 0;
4
+ const oauth2_presets_1 = require("./oauth2-presets");
5
+ function route(path, method, override) {
6
+ return {
7
+ path: override?.path ?? path,
8
+ method: override?.method ?? method,
9
+ };
10
+ }
11
+ function credentialRoutes(basePath, overrides = {}) {
12
+ return {
13
+ login: route(`${basePath}/login`, "POST", overrides.login),
14
+ logout: route(`${basePath}/logout`, "POST", overrides.logout),
15
+ resetPassword: overrides.resetPassword
16
+ ? route(`${basePath}/password/reset`, "POST", overrides.resetPassword)
17
+ : undefined,
18
+ changePassword: overrides.changePassword
19
+ ? route(`${basePath}/password/change`, "POST", overrides.changePassword)
20
+ : undefined,
21
+ requestPasswordReset: overrides.requestPasswordReset
22
+ ? route(`${basePath}/password/reset/request`, "POST", overrides.requestPasswordReset)
23
+ : undefined,
24
+ };
25
+ }
26
+ function oauthRoutes(basePath, overrides = {}) {
27
+ return {
28
+ login: route(basePath, "GET", overrides.login),
29
+ callback: route(`${basePath}/callback`, "GET", overrides.callback),
30
+ logout: overrides.logout
31
+ ? route(`${basePath}/logout`, "POST", overrides.logout)
32
+ : undefined,
33
+ refresh: overrides.refresh
34
+ ? route(`${basePath}/refresh`, "POST", overrides.refresh)
35
+ : undefined,
36
+ revoke: overrides.revoke
37
+ ? route(`${basePath}/revoke`, "POST", overrides.revoke)
38
+ : undefined,
39
+ };
40
+ }
41
+ function createJwtAuthConfig(options) {
42
+ const { accessSecret, refreshSecret, accessToken, refreshToken, routes, ...config } = options;
43
+ return {
44
+ ...config,
45
+ user: options.user,
46
+ accessToken: {
47
+ issuer: {
48
+ secretKey: accessSecret,
49
+ options: {
50
+ expiresIn: "15m",
51
+ ...(accessToken?.options ?? {}),
52
+ },
53
+ buildPayload: accessToken?.buildPayload,
54
+ },
55
+ verifier: { options: {} },
56
+ },
57
+ refreshToken: refreshSecret
58
+ ? {
59
+ issuer: {
60
+ secretKey: refreshSecret,
61
+ options: {
62
+ expiresIn: "7d",
63
+ ...(refreshToken?.options ?? {}),
64
+ },
65
+ buildPayload: refreshToken?.buildPayload,
66
+ },
67
+ verifier: { options: {} },
68
+ }
69
+ : undefined,
70
+ routes: {
71
+ login: route("/auth/jwt/login", "POST", routes?.login),
72
+ logout: route("/auth/jwt/logout", "POST", routes?.logout),
73
+ refresh: route("/auth/jwt/refresh", "POST", routes?.refresh),
74
+ },
75
+ };
76
+ }
77
+ exports.createJwtAuthConfig = createJwtAuthConfig;
78
+ function createLocalAuthConfig(options) {
79
+ const { basePath, routes, ...config } = options;
80
+ return {
81
+ ...config,
82
+ routes: credentialRoutes(basePath ?? "/auth/local", routes),
83
+ };
84
+ }
85
+ exports.createLocalAuthConfig = createLocalAuthConfig;
86
+ function createBasicAuthConfig(options) {
87
+ const { basePath, routes, ...config } = options;
88
+ return {
89
+ ...config,
90
+ routes: credentialRoutes(basePath ?? "/auth/basic", routes),
91
+ };
92
+ }
93
+ exports.createBasicAuthConfig = createBasicAuthConfig;
94
+ function createApiKeyAuthConfig(options) {
95
+ return {
96
+ keyType: "long-term",
97
+ ...options,
98
+ };
99
+ }
100
+ exports.createApiKeyAuthConfig = createApiKeyAuthConfig;
101
+ function resolveOAuth2Endpoints(options) {
102
+ if (options.endpoints) {
103
+ return options.endpoints;
104
+ }
105
+ switch (options.provider) {
106
+ case "auth0":
107
+ return oauth2_presets_1.oauth2ProviderEndpoints.auth0(options.presetOptions);
108
+ case "keycloak":
109
+ return oauth2_presets_1.oauth2ProviderEndpoints.keycloak(options.presetOptions);
110
+ case "google":
111
+ return oauth2_presets_1.oauth2ProviderEndpoints.google();
112
+ case "github":
113
+ return oauth2_presets_1.oauth2ProviderEndpoints.github();
114
+ case "facebook":
115
+ return oauth2_presets_1.oauth2ProviderEndpoints.facebook(options.presetOptions);
116
+ case "discord":
117
+ return oauth2_presets_1.oauth2ProviderEndpoints.discord();
118
+ default:
119
+ throw new Error(`OAuth2 provider "${options.provider}" requires explicit endpoints.`);
120
+ }
121
+ }
122
+ function createOAuth2ProviderConfig(options) {
123
+ const { provider, endpoints, presetOptions, routes, ...config } = options;
124
+ return {
125
+ ...config,
126
+ grantType: options.grantType ?? "authorization_code",
127
+ endpoints: resolveOAuth2Endpoints(options),
128
+ routes: oauthRoutes(`/auth/${provider}`, routes),
129
+ };
130
+ }
131
+ exports.createOAuth2ProviderConfig = createOAuth2ProviderConfig;
132
+ function createHybridOAuth2ProviderConfig(options) {
133
+ return createOAuth2ProviderConfig(options);
134
+ }
135
+ exports.createHybridOAuth2ProviderConfig = createHybridOAuth2ProviderConfig;
@@ -0,0 +1,13 @@
1
+ export interface CookieOptions {
2
+ httpOnly?: boolean;
3
+ secure?: boolean;
4
+ sameSite?: "strict" | "lax" | "none" | "Strict" | "Lax" | "None";
5
+ maxAge?: number;
6
+ path?: string;
7
+ domain?: string;
8
+ }
9
+ export declare function extractBearerToken(context: any): string | undefined;
10
+ export declare function setBearerToken(context: any, token: string): void;
11
+ export declare function getCookie(context: any, name: string): string | undefined;
12
+ export declare function setCookie(context: any, name: string, value: string, options?: CookieOptions): void;
13
+ export declare function redirect(context: any, url: string, status?: number): void;