quidproquo-webserver 0.1.8 → 0.1.10

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 (61) hide show
  1. package/lib/commonjs/actions/api/ApiActionType.d.ts +3 -0
  2. package/lib/commonjs/actions/api/ApiActionType.js +8 -0
  3. package/lib/commonjs/actions/api/ApiActionType.js.map +1 -0
  4. package/lib/commonjs/actions/api/ApiRequestActionRequester.d.ts +3 -0
  5. package/lib/commonjs/actions/api/ApiRequestActionRequester.js +19 -0
  6. package/lib/commonjs/actions/api/ApiRequestActionRequester.js.map +1 -0
  7. package/lib/commonjs/actions/api/ApiRequestActionRequesterTypes.d.ts +18 -0
  8. package/lib/commonjs/actions/api/ApiRequestActionRequesterTypes.js +3 -0
  9. package/lib/commonjs/actions/api/ApiRequestActionRequesterTypes.js.map +1 -0
  10. package/lib/commonjs/actions/api/index.d.ts +3 -0
  11. package/lib/commonjs/actions/api/index.js +20 -0
  12. package/lib/commonjs/actions/api/index.js.map +1 -0
  13. package/lib/commonjs/actions/index.d.ts +1 -0
  14. package/lib/commonjs/actions/index.js +1 -0
  15. package/lib/commonjs/actions/index.js.map +1 -1
  16. package/lib/commonjs/config/settings/defineAuthSystem/defineAuthSystem.d.ts +1 -0
  17. package/lib/commonjs/config/settings/defineAuthSystem/defineAuthSystem.js +7 -0
  18. package/lib/commonjs/config/settings/defineAuthSystem/defineAuthSystem.js.map +1 -1
  19. package/lib/commonjs/services/auth/entry/controller/authController.d.ts +2 -0
  20. package/lib/commonjs/services/auth/entry/controller/authController.js +23 -0
  21. package/lib/commonjs/services/auth/entry/controller/authController.js.map +1 -1
  22. package/lib/commonjs/services/auth/logic/auth/askRevokeSession.d.ts +2 -0
  23. package/lib/commonjs/services/auth/logic/auth/askRevokeSession.js +13 -0
  24. package/lib/commonjs/services/auth/logic/auth/askRevokeSession.js.map +1 -0
  25. package/lib/commonjs/services/auth/logic/auth/askSignOut.d.ts +2 -0
  26. package/lib/commonjs/services/auth/logic/auth/askSignOut.js +11 -0
  27. package/lib/commonjs/services/auth/logic/auth/askSignOut.js.map +1 -0
  28. package/lib/commonjs/services/auth/logic/auth/index.d.ts +2 -0
  29. package/lib/commonjs/services/auth/logic/auth/index.js +2 -0
  30. package/lib/commonjs/services/auth/logic/auth/index.js.map +1 -1
  31. package/lib/esm/actions/api/ApiActionType.d.ts +3 -0
  32. package/lib/esm/actions/api/ApiActionType.js +5 -0
  33. package/lib/esm/actions/api/ApiActionType.js.map +1 -0
  34. package/lib/esm/actions/api/ApiRequestActionRequester.d.ts +3 -0
  35. package/lib/esm/actions/api/ApiRequestActionRequester.js +16 -0
  36. package/lib/esm/actions/api/ApiRequestActionRequester.js.map +1 -0
  37. package/lib/esm/actions/api/ApiRequestActionRequesterTypes.d.ts +18 -0
  38. package/lib/esm/actions/api/ApiRequestActionRequesterTypes.js +2 -0
  39. package/lib/esm/actions/api/ApiRequestActionRequesterTypes.js.map +1 -0
  40. package/lib/esm/actions/api/index.d.ts +3 -0
  41. package/lib/esm/actions/api/index.js +4 -0
  42. package/lib/esm/actions/api/index.js.map +1 -0
  43. package/lib/esm/actions/index.d.ts +1 -0
  44. package/lib/esm/actions/index.js +1 -0
  45. package/lib/esm/actions/index.js.map +1 -1
  46. package/lib/esm/config/settings/defineAuthSystem/defineAuthSystem.d.ts +1 -0
  47. package/lib/esm/config/settings/defineAuthSystem/defineAuthSystem.js +7 -0
  48. package/lib/esm/config/settings/defineAuthSystem/defineAuthSystem.js.map +1 -1
  49. package/lib/esm/services/auth/entry/controller/authController.d.ts +2 -0
  50. package/lib/esm/services/auth/entry/controller/authController.js +22 -1
  51. package/lib/esm/services/auth/entry/controller/authController.js.map +1 -1
  52. package/lib/esm/services/auth/logic/auth/askRevokeSession.d.ts +2 -0
  53. package/lib/esm/services/auth/logic/auth/askRevokeSession.js +10 -0
  54. package/lib/esm/services/auth/logic/auth/askRevokeSession.js.map +1 -0
  55. package/lib/esm/services/auth/logic/auth/askSignOut.d.ts +2 -0
  56. package/lib/esm/services/auth/logic/auth/askSignOut.js +8 -0
  57. package/lib/esm/services/auth/logic/auth/askSignOut.js.map +1 -0
  58. package/lib/esm/services/auth/logic/auth/index.d.ts +2 -0
  59. package/lib/esm/services/auth/logic/auth/index.js +2 -0
  60. package/lib/esm/services/auth/logic/auth/index.js.map +1 -1
  61. package/package.json +3 -3
@@ -0,0 +1,3 @@
1
+ export declare enum ApiActionType {
2
+ Request = "@quidproquo-webserver/Api/Request"
3
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiActionType = void 0;
4
+ var ApiActionType;
5
+ (function (ApiActionType) {
6
+ ApiActionType["Request"] = "@quidproquo-webserver/Api/Request";
7
+ })(ApiActionType || (exports.ApiActionType = ApiActionType = {}));
8
+ //# sourceMappingURL=ApiActionType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiActionType.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiActionType.ts"],"names":[],"mappings":";;;AAAA,IAAY,aAEX;AAFD,WAAY,aAAa;IACvB,8DAA6C,CAAA;AAC/C,CAAC,EAFW,aAAa,6BAAb,aAAa,QAExB","sourcesContent":["export enum ApiActionType {\n Request = '@quidproquo-webserver/Api/Request',\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { HTTPMethod } from 'quidproquo-core';
2
+ import { ApiRequestActionRequester, ApiRequestOptions } from './ApiRequestActionRequesterTypes';
3
+ export declare function askApiRequest<T, R>(service: string, method: HTTPMethod, endpoint: string, options?: ApiRequestOptions<T>): ApiRequestActionRequester<T, R>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.askApiRequest = askApiRequest;
4
+ const ApiActionType_1 = require("./ApiActionType");
5
+ function* askApiRequest(service, method, endpoint, options) {
6
+ return yield {
7
+ type: ApiActionType_1.ApiActionType.Request,
8
+ payload: {
9
+ service,
10
+ endpoint,
11
+ method,
12
+ body: options === null || options === void 0 ? void 0 : options.body,
13
+ headers: options === null || options === void 0 ? void 0 : options.headers,
14
+ params: options === null || options === void 0 ? void 0 : options.params,
15
+ responseType: (options === null || options === void 0 ? void 0 : options.responseType) || 'json',
16
+ },
17
+ };
18
+ }
19
+ //# sourceMappingURL=ApiRequestActionRequester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiRequestActionRequester.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiRequestActionRequester.ts"],"names":[],"mappings":";;AAKA,sCAkBC;AArBD,mDAAgD;AAGhD,QAAe,CAAC,CAAC,aAAa,CAC5B,OAAe,EACf,MAAkB,EAClB,QAAgB,EAChB,OAA8B;IAE9B,OAAO,MAAM;QACX,IAAI,EAAE,6BAAa,CAAC,OAAO;QAC3B,OAAO,EAAE;YACP,OAAO;YACP,QAAQ;YACR,MAAM;YACN,IAAI,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI;YACnB,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO;YACzB,MAAM,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM;YACvB,YAAY,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,KAAI,MAAM;SAC9C;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { HTTPMethod } from 'quidproquo-core';\n\nimport { ApiActionType } from './ApiActionType';\nimport { ApiRequestActionRequester, ApiRequestOptions } from './ApiRequestActionRequesterTypes';\n\nexport function* askApiRequest<T, R>(\n service: string,\n method: HTTPMethod,\n endpoint: string,\n options?: ApiRequestOptions<T>,\n): ApiRequestActionRequester<T, R> {\n return yield {\n type: ApiActionType.Request,\n payload: {\n service,\n endpoint,\n method,\n body: options?.body,\n headers: options?.headers,\n params: options?.params,\n responseType: options?.responseType || 'json',\n },\n };\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { Action, ActionProcessor, ActionRequester, HTTPMethod, HTTPNetworkResponse, HTTPRequestOptions, ResponseType } from 'quidproquo-core';
2
+ import { ApiActionType } from './ApiActionType';
3
+ export type ApiRequestOptions<T> = Omit<HTTPRequestOptions<T>, 'basePath'>;
4
+ export interface ApiRequestActionPayload<T> {
5
+ service: string;
6
+ endpoint: string;
7
+ method: HTTPMethod;
8
+ body?: T;
9
+ params?: Record<string, string>;
10
+ headers?: Record<string, string>;
11
+ responseType: ResponseType;
12
+ }
13
+ export interface ApiRequestAction<T> extends Action<ApiRequestActionPayload<T>> {
14
+ type: ApiActionType.Request;
15
+ payload: ApiRequestActionPayload<T>;
16
+ }
17
+ export type ApiRequestActionProcessor<T, R> = ActionProcessor<ApiRequestAction<T>, HTTPNetworkResponse<R>>;
18
+ export type ApiRequestActionRequester<T, R> = ActionRequester<ApiRequestAction<T>, HTTPNetworkResponse<R>>;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ApiRequestActionRequesterTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiRequestActionRequesterTypes.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiRequestActionRequesterTypes.ts"],"names":[],"mappings":"","sourcesContent":["import { Action, ActionProcessor, ActionRequester, HTTPMethod, HTTPNetworkResponse, HTTPRequestOptions, ResponseType } from 'quidproquo-core';\n\nimport { ApiActionType } from './ApiActionType';\n\n// basePath is resolved by the processor, so it is omitted from the caller options\nexport type ApiRequestOptions<T> = Omit<HTTPRequestOptions<T>, 'basePath'>;\n\n// Payload\nexport interface ApiRequestActionPayload<T> {\n service: string;\n endpoint: string;\n method: HTTPMethod;\n body?: T;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n responseType: ResponseType;\n}\n\n// Action\nexport interface ApiRequestAction<T> extends Action<ApiRequestActionPayload<T>> {\n type: ApiActionType.Request;\n payload: ApiRequestActionPayload<T>;\n}\n\n// Function Types\nexport type ApiRequestActionProcessor<T, R> = ActionProcessor<ApiRequestAction<T>, HTTPNetworkResponse<R>>;\nexport type ApiRequestActionRequester<T, R> = ActionRequester<ApiRequestAction<T>, HTTPNetworkResponse<R>>;\n"]}
@@ -0,0 +1,3 @@
1
+ export * from './ApiActionType';
2
+ export * from './ApiRequestActionRequester';
3
+ export * from './ApiRequestActionRequesterTypes';
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./ApiActionType"), exports);
18
+ __exportStar(require("./ApiRequestActionRequester"), exports);
19
+ __exportStar(require("./ApiRequestActionRequesterTypes"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/actions/api/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,8DAA4C;AAC5C,mEAAiD","sourcesContent":["export * from './ApiActionType';\nexport * from './ApiRequestActionRequester';\nexport * from './ApiRequestActionRequesterTypes';\n"]}
@@ -1,4 +1,5 @@
1
1
  export * from './admin';
2
+ export * from './api';
2
3
  export * from './apiKeyValidation';
3
4
  export * from './dns';
4
5
  export * from './genericDataResource';
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./admin"), exports);
18
+ __exportStar(require("./api"), exports);
18
19
  __exportStar(require("./apiKeyValidation"), exports);
19
20
  __exportStar(require("./dns"), exports);
20
21
  __exportStar(require("./genericDataResource"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/actions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,qDAAmC;AACnC,wCAAsB;AACtB,wDAAsC;AACtC,gDAA8B;AAC9B,wDAAsC;AACtC,oDAAkC;AAClC,6CAA2B;AAC3B,8CAA4B","sourcesContent":["export * from './admin';\nexport * from './apiKeyValidation';\nexport * from './dns';\nexport * from './genericDataResource';\nexport * from './openApiSpec';\nexport * from './routeAuthValidation';\nexport * from './serviceFunction';\nexport * from './webEntry';\nexport * from './websocket';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/actions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,wCAAsB;AACtB,qDAAmC;AACnC,wCAAsB;AACtB,wDAAsC;AACtC,gDAA8B;AAC9B,wDAAsC;AACtC,oDAAkC;AAClC,6CAA2B;AAC3B,8CAA4B","sourcesContent":["export * from './admin';\nexport * from './api';\nexport * from './apiKeyValidation';\nexport * from './dns';\nexport * from './genericDataResource';\nexport * from './openApiSpec';\nexport * from './routeAuthValidation';\nexport * from './serviceFunction';\nexport * from './webEntry';\nexport * from './websocket';\n"]}
@@ -6,5 +6,6 @@ export interface AuthSystemOptions {
6
6
  mfa?: UserDirectoryMfaSettings;
7
7
  basePath?: string;
8
8
  allowedOrigins?: string[];
9
+ accessTokenValidityMinutes?: number;
9
10
  }
10
11
  export declare const defineAuthSystem: (service: string, directoryName: string, options?: AuthSystemOptions) => QPQConfig;
@@ -23,6 +23,7 @@ const defineAuthSystem = (service, directoryName, options) => {
23
23
  selfSignUpEnabled: options === null || options === void 0 ? void 0 : options.selfSignUpEnabled,
24
24
  emailTemplates: options === null || options === void 0 ? void 0 : options.emailTemplates,
25
25
  mfa: options === null || options === void 0 ? void 0 : options.mfa,
26
+ accessTokenValidityMinutes: options === null || options === void 0 ? void 0 : options.accessTokenValidityMinutes,
26
27
  owner: { module: service },
27
28
  }),
28
29
  // The login endpoints and their handlers only deploy with the owning service.
@@ -31,6 +32,12 @@ const defineAuthSystem = (service, directoryName, options) => {
31
32
  (0, quidproquo_core_1.defineGlobal)(config_1.AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),
32
33
  (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/login`, 'login', routeOptions),
33
34
  (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),
35
+ // Public + best-effort (logout must never fail for the client, so it isn't
36
+ // edge-gated). /logout revokes just the caller's own refresh token (this device);
37
+ // /logoutEverywhere revokes all of the user's sessions (settings "sign out of all
38
+ // devices"). Each is self-authorizing: the refresh token / access token it carries.
39
+ (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/logout`, 'logout', routeOptions),
40
+ (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/logoutEverywhere`, 'logoutEverywhere', routeOptions),
34
41
  (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),
35
42
  (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),
36
43
  (0, defineAuthServiceRoute_1.defineAuthServiceRoute)('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),
@@ -1 +1 @@
1
- {"version":3,"file":"defineAuthSystem.js","sourceRoot":"","sources":["../../../../../src/config/settings/defineAuthSystem/defineAuthSystem.ts"],"names":[],"mappings":";;;AAAA,qDAAgJ;AAEhJ,0DAA+E;AAC/E,iGAA8F;AAiB9F,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,iCAAiC;AAC1B,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,aAAqB,EAAE,OAA2B,EAAa,EAAE;;IACjH,MAAM,QAAQ,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,mCAAI,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG;QACnB,cAAc,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc;KACxC,CAAC;IAEF,OAAO;QACL,qEAAqE;QACrE,0EAA0E;QAC1E,IAAA,qCAAmB,EAAC,aAAa,EAAE;YACjC,aAAa,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa;YACrC,iBAAiB,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,iBAAiB;YAC7C,cAAc,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc;YACvC,GAAG,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG;YACjB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SAC3B,CAAC;QAEF,8EAA8E;QAC9E,IAAA,uCAAqB,EAAC;YACpB,CAAC,OAAO,CAAC,EAAE;gBACT,IAAA,8BAAY,EAAC,uCAA8B,EAAE,aAAa,CAAC;gBAE3D,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC;gBAC1E,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC;gBACxF,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,YAAY,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC/F,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC5G,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,CAAC;gBAC5F,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,uBAAuB,EAAE,YAAY,CAAC;gBAE3G,+DAA+D;gBAC/D,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,kCACxE,YAAY,KACf,iBAAiB,EAAE;wBACjB,iBAAiB,EAAE,aAAa;qBACjC,IACD;aACH;SACF,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAxCW,QAAA,gBAAgB,oBAwC3B","sourcesContent":["import { defineGlobal, defineServiceSettings, defineUserDirectory, EmailTemplates, QPQConfig, UserDirectoryMfaSettings } from 'quidproquo-core';\n\nimport { AUTH_USER_DIRECTORY_GLOBAL_KEY } from '../../../services/auth/config';\nimport { defineAuthServiceRoute } from '../../../services/auth/config/defineAuthServiceRoute';\n\nexport interface AuthSystemOptions {\n phoneRequired?: boolean;\n\n selfSignUpEnabled?: boolean;\n\n emailTemplates?: EmailTemplates;\n\n mfa?: UserDirectoryMfaSettings;\n\n // Path prefix applied to every auth route, e.g. '/auth' => '/auth/login'.\n basePath?: string;\n\n allowedOrigins?: string[];\n}\n\n// Bundles a complete username/password login flow: a user directory plus the\n// endpoints needed to log in, refresh tokens, respond to challenges, recover a\n// forgotten password, and change a password. The handler stories ship inside\n// quidproquo-webserver (services/auth) and resolve `directoryName` at runtime\n// from the global emitted below.\nexport const defineAuthSystem = (service: string, directoryName: string, options?: AuthSystemOptions): QPQConfig => {\n const basePath = options?.basePath ?? '';\n\n const routeOptions = {\n allowedOrigins: options?.allowedOrigins,\n };\n\n return [\n // The user directory is declared at the top level (ungated) so other\n // services in the application can reference it to validate access tokens.\n defineUserDirectory(directoryName, {\n phoneRequired: options?.phoneRequired,\n selfSignUpEnabled: options?.selfSignUpEnabled,\n emailTemplates: options?.emailTemplates,\n mfa: options?.mfa,\n owner: { module: service },\n }),\n\n // The login endpoints and their handlers only deploy with the owning service.\n defineServiceSettings({\n [service]: [\n defineGlobal(AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),\n\n defineAuthServiceRoute('POST', `${basePath}/login`, 'login', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword/confirm`, 'confirmForgotPassword', routeOptions),\n\n // Authenticated: the caller must present a valid access token.\n defineAuthServiceRoute('POST', `${basePath}/changePassword`, 'changePassword', {\n ...routeOptions,\n routeAuthSettings: {\n userDirectoryName: directoryName,\n },\n }),\n ],\n }),\n ];\n};\n"]}
1
+ {"version":3,"file":"defineAuthSystem.js","sourceRoot":"","sources":["../../../../../src/config/settings/defineAuthSystem/defineAuthSystem.ts"],"names":[],"mappings":";;;AAAA,qDAAgJ;AAEhJ,0DAA+E;AAC/E,iGAA8F;AAsB9F,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,iCAAiC;AAC1B,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,aAAqB,EAAE,OAA2B,EAAa,EAAE;;IACjH,MAAM,QAAQ,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,mCAAI,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG;QACnB,cAAc,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc;KACxC,CAAC;IAEF,OAAO;QACL,qEAAqE;QACrE,0EAA0E;QAC1E,IAAA,qCAAmB,EAAC,aAAa,EAAE;YACjC,aAAa,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa;YACrC,iBAAiB,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,iBAAiB;YAC7C,cAAc,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc;YACvC,GAAG,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG;YACjB,0BAA0B,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B;YAC/D,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SAC3B,CAAC;QAEF,8EAA8E;QAC9E,IAAA,uCAAqB,EAAC;YACpB,CAAC,OAAO,CAAC,EAAE;gBACT,IAAA,8BAAY,EAAC,uCAA8B,EAAE,aAAa,CAAC;gBAE3D,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC;gBAC1E,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC;gBACxF,2EAA2E;gBAC3E,kFAAkF;gBAClF,kFAAkF;gBAClF,oFAAoF;gBACpF,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC;gBAC5E,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,CAAC;gBAChG,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,YAAY,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC/F,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC5G,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,CAAC;gBAC5F,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,uBAAuB,EAAE,YAAY,CAAC;gBAE3G,+DAA+D;gBAC/D,IAAA,+CAAsB,EAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,kCACxE,YAAY,KACf,iBAAiB,EAAE;wBACjB,iBAAiB,EAAE,aAAa;qBACjC,IACD;aACH;SACF,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AA/CW,QAAA,gBAAgB,oBA+C3B","sourcesContent":["import { defineGlobal, defineServiceSettings, defineUserDirectory, EmailTemplates, QPQConfig, UserDirectoryMfaSettings } from 'quidproquo-core';\n\nimport { AUTH_USER_DIRECTORY_GLOBAL_KEY } from '../../../services/auth/config';\nimport { defineAuthServiceRoute } from '../../../services/auth/config/defineAuthServiceRoute';\n\nexport interface AuthSystemOptions {\n phoneRequired?: boolean;\n\n selfSignUpEnabled?: boolean;\n\n emailTemplates?: EmailTemplates;\n\n mfa?: UserDirectoryMfaSettings;\n\n // Path prefix applied to every auth route, e.g. '/auth' => '/auth/login'.\n basePath?: string;\n\n allowedOrigins?: string[];\n\n // Access/ID token (JWT) lifetime in minutes (Cognito 5–1440; omitted → default 60).\n // Shorter shrinks the post-revocation window in which a stateless access token still\n // works. Keep comfortably above 10 (the web client refreshes ~10 min before expiry).\n accessTokenValidityMinutes?: number;\n}\n\n// Bundles a complete username/password login flow: a user directory plus the\n// endpoints needed to log in, refresh tokens, respond to challenges, recover a\n// forgotten password, and change a password. The handler stories ship inside\n// quidproquo-webserver (services/auth) and resolve `directoryName` at runtime\n// from the global emitted below.\nexport const defineAuthSystem = (service: string, directoryName: string, options?: AuthSystemOptions): QPQConfig => {\n const basePath = options?.basePath ?? '';\n\n const routeOptions = {\n allowedOrigins: options?.allowedOrigins,\n };\n\n return [\n // The user directory is declared at the top level (ungated) so other\n // services in the application can reference it to validate access tokens.\n defineUserDirectory(directoryName, {\n phoneRequired: options?.phoneRequired,\n selfSignUpEnabled: options?.selfSignUpEnabled,\n emailTemplates: options?.emailTemplates,\n mfa: options?.mfa,\n accessTokenValidityMinutes: options?.accessTokenValidityMinutes,\n owner: { module: service },\n }),\n\n // The login endpoints and their handlers only deploy with the owning service.\n defineServiceSettings({\n [service]: [\n defineGlobal(AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),\n\n defineAuthServiceRoute('POST', `${basePath}/login`, 'login', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),\n // Public + best-effort (logout must never fail for the client, so it isn't\n // edge-gated). /logout revokes just the caller's own refresh token (this device);\n // /logoutEverywhere revokes all of the user's sessions (settings \"sign out of all\n // devices\"). Each is self-authorizing: the refresh token / access token it carries.\n defineAuthServiceRoute('POST', `${basePath}/logout`, 'logout', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/logoutEverywhere`, 'logoutEverywhere', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword/confirm`, 'confirmForgotPassword', routeOptions),\n\n // Authenticated: the caller must present a valid access token.\n defineAuthServiceRoute('POST', `${basePath}/changePassword`, 'changePassword', {\n ...routeOptions,\n routeAuthSettings: {\n userDirectoryName: directoryName,\n },\n }),\n ],\n }),\n ];\n};\n"]}
@@ -2,6 +2,8 @@ import { AskResponse } from 'quidproquo-core';
2
2
  import { HTTPEvent, HTTPEventResponse } from '../../../../types';
3
3
  export declare function login(event: HTTPEvent): AskResponse<HTTPEventResponse>;
4
4
  export declare function refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse>;
5
+ export declare function logout(event: HTTPEvent): AskResponse<HTTPEventResponse>;
6
+ export declare function logoutEverywhere(event: HTTPEvent): AskResponse<HTTPEventResponse>;
5
7
  export declare function respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse>;
6
8
  export declare function associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse>;
7
9
  export declare function forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse>;
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.login = login;
4
4
  exports.refreshToken = refreshToken;
5
+ exports.logout = logout;
6
+ exports.logoutEverywhere = logoutEverywhere;
5
7
  exports.respondToAuthChallenge = respondToAuthChallenge;
6
8
  exports.associateSoftwareToken = associateSoftwareToken;
7
9
  exports.forgotPassword = forgotPassword;
@@ -65,6 +67,27 @@ function* refreshToken(event) {
65
67
  const refreshResponse = yield* logic_1.authLogic.askRefreshToken(refreshToken);
66
68
  return index_1.qpqWebServerUtils.toJsonEventResponse(refreshResponse);
67
69
  }
70
+ function* logout(event) {
71
+ // "Log out this device": revoke ONLY the caller's own refresh token (Cognito RevokeToken),
72
+ // leaving the user's other sessions signed in. The client sends its refresh token in the
73
+ // body. Best-effort — logout must always succeed for the client (it clears local state
74
+ // regardless), so an already-revoked/invalid token is swallowed rather than 4xx'd. Public
75
+ // route: possessing the refresh token is the authorization (you can only revoke your own).
76
+ const { refreshToken } = yield* index_1.qpqWebServerUtils.askFromValidJsonEventRequest(event, requireStringFields('refreshToken'));
77
+ yield* (0, quidproquo_core_1.askCatch)(logic_1.authLogic.askRevokeSession(refreshToken));
78
+ return index_1.qpqWebServerUtils.toJsonEventResponse({ success: true });
79
+ }
80
+ function* logoutEverywhere(event) {
81
+ // "Log out everywhere": revoke EVERY refresh token for the user (Cognito GlobalSignOut),
82
+ // for a user-settings "sign out of all devices" action. Authorized by the access token in
83
+ // the header (GlobalSignOut validates it at Cognito). Best-effort / always 200, same as
84
+ // above — swallow an invalid/expired token rather than failing the client's logout.
85
+ const accessToken = index_1.qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);
86
+ if (accessToken) {
87
+ yield* (0, quidproquo_core_1.askCatch)(logic_1.authLogic.askSignOut(accessToken));
88
+ }
89
+ return index_1.qpqWebServerUtils.toJsonEventResponse({ success: true });
90
+ }
68
91
  function* respondToAuthChallenge(event) {
69
92
  const payload = yield* index_1.qpqWebServerUtils.askFromValidJsonEventRequest(event, requireStringFields('email', 'session', 'challenge'));
70
93
  const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);
@@ -1 +1 @@
1
- {"version":3,"file":"authController.js","sourceRoot":"","sources":["../../../../../../src/services/auth/entry/controller/authController.ts"],"names":[],"mappings":";;AAwEA,sBASC;AAED,oCAMC;AAED,wDAWC;AAED,wDAMC;AAED,wCAMC;AAED,sDASC;AAED,wCAgBC;AAnJD,qDAAyH;AAEzH,+CAA+C;AAC/C,6CAAsD;AAEtD,uCAAwC;AACxC,uCAYqB;AAErB,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,mBAAmB,GACvB,CAAI,GAAG,MAAgB,EAAE,EAAE,CAC3B,CAAC,IAAa,EAAK,EAAE;IACnB,MAAM,MAAM,GAAG,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAA4B,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAEpG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC,CAAC;AAEJ,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,qEAAqE;AACrE,QAAQ,CAAC,CAAC,kCAAkC,CAAC,OAA4B;IACvE,IAAI,IAAA,qCAA6B,EAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,SAAS,EAAE,2CAAyB,CAAC,qBAAqB;YAC1D,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC;IACJ,CAAC;IAED,IAAI,IAAA,6BAAqB,EAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,SAAS,EAAE,2CAAyB,CAAC,kBAAkB;YACvD,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,IAAI,IAAA,kCAA0B,EAAC,OAAO,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,SAAS,EAAE,2CAAyB,CAAC,SAAS;YAC9C,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,IAAA,+BAAa,EAAC,+BAAa,CAAC,UAAU,EAAE,4CAA6C,OAA4B,CAAC,SAAS,EAAE,CAAC,CAAC;AAC/I,CAAC;AAED,QAAe,CAAC,CAAC,KAAK,CAAC,KAAgB;IACrC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CAClF,KAAK,EACL,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAC5C,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEnE,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;AAC7D,CAAC;AAED,QAAe,CAAC,CAAC,YAAY,CAAC,KAAgB;IAC5C,MAAM,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CAAiB,KAAK,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAC;IAE3I,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAEvE,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAChE,CAAC;AAED,QAAe,CAAC,CAAC,sBAAsB,CAAC,KAAgB;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CACnE,KAAK,EACL,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CACrD,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;IAEzE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC;IAE3E,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,QAAe,CAAC,CAAC,sBAAsB,CAAC,KAAgB;IACtD,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CAAgC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhJ,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAErE,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,QAAe,CAAC,CAAC,cAAc,CAAC,KAAgB;IAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CAAwB,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;IAE1I,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAErE,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAChE,CAAC;AAED,QAAe,CAAC,CAAC,qBAAqB,CAAC,KAAgB;IACrD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CACxF,KAAK,EACL,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CACpD,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,iBAAS,CAAC,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAErF,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,QAAe,CAAC,CAAC,cAAc,CAAC,KAAgB;IAC9C,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,yBAAiB,CAAC,4BAA4B,CACxF,KAAK,EACL,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAClD,CAAC;IAEF,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,WAAW,GAAG,yBAAiB,CAAC,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,IAAA,+BAAa,EAAC,+BAAa,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,CAAC,iBAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAE1E,OAAO,yBAAiB,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import { AnyAuthChallenge, AskResponse, askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';\n\n// TODO: Fix this import (name it up the chain)\nimport { qpqWebServerUtils } from '../../../../index';\nimport { HTTPEvent, HTTPEventResponse } from '../../../../types';\nimport { authLogic } from '../../logic';\nimport {\n AnyChallengePayload,\n AssociateSoftwareTokenPayload,\n ChallengePayload,\n ChangePasswordPayload,\n ConfirmForgotPasswordPayload,\n ForgotPasswordPayload,\n isMfaChallengePayload,\n isMfaSetupChallengePayload,\n isNewPasswordChallengePayload,\n LoginPayload,\n RefreshPayload,\n} from '../../types';\n\n// Field-presence validator for askFromValidJsonEventRequest. The payload types\n// are just casts over whatever json the client sent, so each handler checks its\n// required fields are real non-empty strings before anything touches the user\n// directory. A miss comes back as a 422 Invalid instead of a downstream error.\nconst requireStringFields =\n <T>(...fields: string[]) =>\n (data: unknown): T => {\n const record = (data ?? {}) as Record<string, unknown>;\n const missing = fields.filter((field) => typeof record[field] !== 'string' || record[field] === '');\n\n if (missing.length > 0) {\n throw new Error(`Missing or invalid fields: ${missing.join(', ')}`);\n }\n\n return data as T;\n };\n\n// Maps the wire payload (discriminated by `challenge`) onto the core auth\n// challenge shape. The type guards narrow `payload`, so no manual casts are\n// needed. Add a branch here as new challenge types are supported. An unknown\n// or malformed challenge is a client error, so it surfaces as a 400.\nfunction* askChallengePayloadToAuthChallenge(payload: AnyChallengePayload): AskResponse<AnyAuthChallenge> {\n if (isNewPasswordChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED,\n username: payload.email,\n session: payload.session,\n newPassword: payload.newPassword,\n };\n }\n\n if (isMfaChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n if (isMfaSetupChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.MFA_SETUP,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n return yield* askThrowError(ErrorTypeEnum.BadRequest, `Unsupported or malformed auth challenge: ${(payload as ChallengePayload).challenge}`);\n}\n\nexport function* login(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<LoginPayload>(\n event,\n requireStringFields('username', 'password'),\n );\n\n const authResponse = yield* authLogic.askLogin(username, password);\n\n return qpqWebServerUtils.toJsonEventResponse(authResponse);\n}\n\nexport function* refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n const refreshResponse = yield* authLogic.askRefreshToken(refreshToken);\n\n return qpqWebServerUtils.toJsonEventResponse(refreshResponse);\n}\n\nexport function* respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const payload = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AnyChallengePayload>(\n event,\n requireStringFields('email', 'session', 'challenge'),\n );\n\n const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);\n\n const response = yield* authLogic.askRespondToAuthChallenge(authChallenge);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { session } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AssociateSoftwareTokenPayload>(event, requireStringFields('session'));\n\n const response = yield* authLogic.askAssociateSoftwareToken(session);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ForgotPasswordPayload>(event, requireStringFields('username'));\n\n const deliveryDetails = yield* authLogic.askForgotPassword(username);\n\n return qpqWebServerUtils.toJsonEventResponse(deliveryDetails);\n}\n\nexport function* confirmForgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, code, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ConfirmForgotPasswordPayload>(\n event,\n requireStringFields('username', 'code', 'password'),\n );\n\n const response = yield* authLogic.askConfirmForgotPassword(username, code, password);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* changePassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { oldPassword, newPassword } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ChangePasswordPayload>(\n event,\n requireStringFields('oldPassword', 'newPassword'),\n );\n\n // The route is authenticated, so the access token should always be present.\n // Guard anyway so a misconfigured route fails as a 401, not a directory error.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n if (!accessToken) {\n return yield* askThrowError(ErrorTypeEnum.Unauthorized, 'Missing access token.');\n }\n\n yield* authLogic.askChangePassword(oldPassword, newPassword, accessToken);\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n"]}
1
+ {"version":3,"file":"authController.js","sourceRoot":"","sources":["../../../../../../src/services/auth/entry/controller/authController.ts"],"names":[],"mappings":"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","sourcesContent":["import { AnyAuthChallenge, askCatch, AskResponse, askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';\n\n// TODO: Fix this import (name it up the chain)\nimport { qpqWebServerUtils } from '../../../../index';\nimport { HTTPEvent, HTTPEventResponse } from '../../../../types';\nimport { authLogic } from '../../logic';\nimport {\n AnyChallengePayload,\n AssociateSoftwareTokenPayload,\n ChallengePayload,\n ChangePasswordPayload,\n ConfirmForgotPasswordPayload,\n ForgotPasswordPayload,\n isMfaChallengePayload,\n isMfaSetupChallengePayload,\n isNewPasswordChallengePayload,\n LoginPayload,\n RefreshPayload,\n} from '../../types';\n\n// Field-presence validator for askFromValidJsonEventRequest. The payload types\n// are just casts over whatever json the client sent, so each handler checks its\n// required fields are real non-empty strings before anything touches the user\n// directory. A miss comes back as a 422 Invalid instead of a downstream error.\nconst requireStringFields =\n <T>(...fields: string[]) =>\n (data: unknown): T => {\n const record = (data ?? {}) as Record<string, unknown>;\n const missing = fields.filter((field) => typeof record[field] !== 'string' || record[field] === '');\n\n if (missing.length > 0) {\n throw new Error(`Missing or invalid fields: ${missing.join(', ')}`);\n }\n\n return data as T;\n };\n\n// Maps the wire payload (discriminated by `challenge`) onto the core auth\n// challenge shape. The type guards narrow `payload`, so no manual casts are\n// needed. Add a branch here as new challenge types are supported. An unknown\n// or malformed challenge is a client error, so it surfaces as a 400.\nfunction* askChallengePayloadToAuthChallenge(payload: AnyChallengePayload): AskResponse<AnyAuthChallenge> {\n if (isNewPasswordChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED,\n username: payload.email,\n session: payload.session,\n newPassword: payload.newPassword,\n };\n }\n\n if (isMfaChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n if (isMfaSetupChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.MFA_SETUP,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n return yield* askThrowError(ErrorTypeEnum.BadRequest, `Unsupported or malformed auth challenge: ${(payload as ChallengePayload).challenge}`);\n}\n\nexport function* login(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<LoginPayload>(\n event,\n requireStringFields('username', 'password'),\n );\n\n const authResponse = yield* authLogic.askLogin(username, password);\n\n return qpqWebServerUtils.toJsonEventResponse(authResponse);\n}\n\nexport function* refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n const refreshResponse = yield* authLogic.askRefreshToken(refreshToken);\n\n return qpqWebServerUtils.toJsonEventResponse(refreshResponse);\n}\n\nexport function* logout(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n // \"Log out this device\": revoke ONLY the caller's own refresh token (Cognito RevokeToken),\n // leaving the user's other sessions signed in. The client sends its refresh token in the\n // body. Best-effort — logout must always succeed for the client (it clears local state\n // regardless), so an already-revoked/invalid token is swallowed rather than 4xx'd. Public\n // route: possessing the refresh token is the authorization (you can only revoke your own).\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n yield* askCatch(authLogic.askRevokeSession(refreshToken));\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n\nexport function* logoutEverywhere(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n // \"Log out everywhere\": revoke EVERY refresh token for the user (Cognito GlobalSignOut),\n // for a user-settings \"sign out of all devices\" action. Authorized by the access token in\n // the header (GlobalSignOut validates it at Cognito). Best-effort / always 200, same as\n // above — swallow an invalid/expired token rather than failing the client's logout.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n\n if (accessToken) {\n yield* askCatch(authLogic.askSignOut(accessToken));\n }\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n\nexport function* respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const payload = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AnyChallengePayload>(\n event,\n requireStringFields('email', 'session', 'challenge'),\n );\n\n const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);\n\n const response = yield* authLogic.askRespondToAuthChallenge(authChallenge);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { session } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AssociateSoftwareTokenPayload>(event, requireStringFields('session'));\n\n const response = yield* authLogic.askAssociateSoftwareToken(session);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ForgotPasswordPayload>(event, requireStringFields('username'));\n\n const deliveryDetails = yield* authLogic.askForgotPassword(username);\n\n return qpqWebServerUtils.toJsonEventResponse(deliveryDetails);\n}\n\nexport function* confirmForgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, code, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ConfirmForgotPasswordPayload>(\n event,\n requireStringFields('username', 'code', 'password'),\n );\n\n const response = yield* authLogic.askConfirmForgotPassword(username, code, password);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* changePassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { oldPassword, newPassword } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ChangePasswordPayload>(\n event,\n requireStringFields('oldPassword', 'newPassword'),\n );\n\n // The route is authenticated, so the access token should always be present.\n // Guard anyway so a misconfigured route fails as a 401, not a directory error.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n if (!accessToken) {\n return yield* askThrowError(ErrorTypeEnum.Unauthorized, 'Missing access token.');\n }\n\n yield* authLogic.askChangePassword(oldPassword, newPassword, accessToken);\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { AskResponse } from 'quidproquo-core';
2
+ export declare function askRevokeSession(refreshToken: string): AskResponse<void>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.askRevokeSession = askRevokeSession;
4
+ const quidproquo_core_1 = require("quidproquo-core");
5
+ const askGetAuthUserDirectoryName_1 = require("./askGetAuthUserDirectoryName");
6
+ // Revokes a single session by its refresh token (Cognito RevokeToken) — "log out this
7
+ // device". Other sessions for the same user are unaffected (contrast askSignOut, which is
8
+ // a global sign-out of every session).
9
+ function* askRevokeSession(refreshToken) {
10
+ const userDirectoryName = yield* (0, askGetAuthUserDirectoryName_1.askGetAuthUserDirectoryName)();
11
+ yield* (0, quidproquo_core_1.askUserDirectoryRevokeRefreshToken)(userDirectoryName, refreshToken);
12
+ }
13
+ //# sourceMappingURL=askRevokeSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askRevokeSession.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/askRevokeSession.ts"],"names":[],"mappings":";;AAOA,4CAIC;AAXD,qDAAkF;AAElF,+EAA4E;AAE5E,sFAAsF;AACtF,0FAA0F;AAC1F,uCAAuC;AACvC,QAAe,CAAC,CAAC,gBAAgB,CAAC,YAAoB;IACpD,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,IAAA,yDAA2B,GAAE,CAAC;IAE/D,KAAK,CAAC,CAAC,IAAA,oDAAkC,EAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { AskResponse, askUserDirectoryRevokeRefreshToken } from 'quidproquo-core';\n\nimport { askGetAuthUserDirectoryName } from './askGetAuthUserDirectoryName';\n\n// Revokes a single session by its refresh token (Cognito RevokeToken) — \"log out this\n// device\". Other sessions for the same user are unaffected (contrast askSignOut, which is\n// a global sign-out of every session).\nexport function* askRevokeSession(refreshToken: string): AskResponse<void> {\n const userDirectoryName = yield* askGetAuthUserDirectoryName();\n\n yield* askUserDirectoryRevokeRefreshToken(userDirectoryName, refreshToken);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { AskResponse } from 'quidproquo-core';
2
+ export declare function askSignOut(accessToken: string): AskResponse<void>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.askSignOut = askSignOut;
4
+ const quidproquo_core_1 = require("quidproquo-core");
5
+ // Revokes every refresh token for the owner of this access token (server-side session
6
+ // kill). Cognito's GlobalSignOut is authorized by the access token itself, so no user
7
+ // directory name is needed here.
8
+ function* askSignOut(accessToken) {
9
+ yield* (0, quidproquo_core_1.askUserDirectorySignOutUser)(accessToken);
10
+ }
11
+ //# sourceMappingURL=askSignOut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askSignOut.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/askSignOut.ts"],"names":[],"mappings":";;AAKA,gCAEC;AAPD,qDAA2E;AAE3E,sFAAsF;AACtF,sFAAsF;AACtF,iCAAiC;AACjC,QAAe,CAAC,CAAC,UAAU,CAAC,WAAmB;IAC7C,KAAK,CAAC,CAAC,IAAA,6CAA2B,EAAC,WAAW,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { AskResponse, askUserDirectorySignOutUser } from 'quidproquo-core';\n\n// Revokes every refresh token for the owner of this access token (server-side session\n// kill). Cognito's GlobalSignOut is authorized by the access token itself, so no user\n// directory name is needed here.\nexport function* askSignOut(accessToken: string): AskResponse<void> {\n yield* askUserDirectorySignOutUser(accessToken);\n}\n"]}
@@ -6,3 +6,5 @@ export * from './askGetAuthUserDirectoryName';
6
6
  export * from './askLogin';
7
7
  export * from './askRefreshToken';
8
8
  export * from './askRespondToAuthChallenge';
9
+ export * from './askRevokeSession';
10
+ export * from './askSignOut';
@@ -22,4 +22,6 @@ __exportStar(require("./askGetAuthUserDirectoryName"), exports);
22
22
  __exportStar(require("./askLogin"), exports);
23
23
  __exportStar(require("./askRefreshToken"), exports);
24
24
  __exportStar(require("./askRespondToAuthChallenge"), exports);
25
+ __exportStar(require("./askRevokeSession"), exports);
26
+ __exportStar(require("./askSignOut"), exports);
25
27
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,sDAAoC;AACpC,6DAA2C;AAC3C,sDAAoC;AACpC,gEAA8C;AAC9C,6CAA2B;AAC3B,oDAAkC;AAClC,8DAA4C","sourcesContent":["export * from './askAssociateSoftwareToken';\nexport * from './askChangePassword';\nexport * from './askConfirmForgotPassword';\nexport * from './askForgotPassword';\nexport * from './askGetAuthUserDirectoryName';\nexport * from './askLogin';\nexport * from './askRefreshToken';\nexport * from './askRespondToAuthChallenge';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,sDAAoC;AACpC,6DAA2C;AAC3C,sDAAoC;AACpC,gEAA8C;AAC9C,6CAA2B;AAC3B,oDAAkC;AAClC,8DAA4C;AAC5C,qDAAmC;AACnC,+CAA6B","sourcesContent":["export * from './askAssociateSoftwareToken';\nexport * from './askChangePassword';\nexport * from './askConfirmForgotPassword';\nexport * from './askForgotPassword';\nexport * from './askGetAuthUserDirectoryName';\nexport * from './askLogin';\nexport * from './askRefreshToken';\nexport * from './askRespondToAuthChallenge';\nexport * from './askRevokeSession';\nexport * from './askSignOut';\n"]}
@@ -0,0 +1,3 @@
1
+ export declare enum ApiActionType {
2
+ Request = "@quidproquo-webserver/Api/Request"
3
+ }
@@ -0,0 +1,5 @@
1
+ export var ApiActionType;
2
+ (function (ApiActionType) {
3
+ ApiActionType["Request"] = "@quidproquo-webserver/Api/Request";
4
+ })(ApiActionType || (ApiActionType = {}));
5
+ //# sourceMappingURL=ApiActionType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiActionType.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiActionType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,aAEX;AAFD,WAAY,aAAa;IACvB,8DAA6C,CAAA;AAC/C,CAAC,EAFW,aAAa,KAAb,aAAa,QAExB","sourcesContent":["export enum ApiActionType {\n Request = '@quidproquo-webserver/Api/Request',\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { HTTPMethod } from 'quidproquo-core';
2
+ import { ApiRequestActionRequester, ApiRequestOptions } from './ApiRequestActionRequesterTypes';
3
+ export declare function askApiRequest<T, R>(service: string, method: HTTPMethod, endpoint: string, options?: ApiRequestOptions<T>): ApiRequestActionRequester<T, R>;
@@ -0,0 +1,16 @@
1
+ import { ApiActionType } from './ApiActionType';
2
+ export function* askApiRequest(service, method, endpoint, options) {
3
+ return yield {
4
+ type: ApiActionType.Request,
5
+ payload: {
6
+ service,
7
+ endpoint,
8
+ method,
9
+ body: options?.body,
10
+ headers: options?.headers,
11
+ params: options?.params,
12
+ responseType: options?.responseType || 'json',
13
+ },
14
+ };
15
+ }
16
+ //# sourceMappingURL=ApiRequestActionRequester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiRequestActionRequester.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiRequestActionRequester.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,MAAM,SAAS,CAAC,CAAC,aAAa,CAC5B,OAAe,EACf,MAAkB,EAClB,QAAgB,EAChB,OAA8B;IAE9B,OAAO,MAAM;QACX,IAAI,EAAE,aAAa,CAAC,OAAO;QAC3B,OAAO,EAAE;YACP,OAAO;YACP,QAAQ;YACR,MAAM;YACN,IAAI,EAAE,OAAO,EAAE,IAAI;YACnB,OAAO,EAAE,OAAO,EAAE,OAAO;YACzB,MAAM,EAAE,OAAO,EAAE,MAAM;YACvB,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,MAAM;SAC9C;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { HTTPMethod } from 'quidproquo-core';\n\nimport { ApiActionType } from './ApiActionType';\nimport { ApiRequestActionRequester, ApiRequestOptions } from './ApiRequestActionRequesterTypes';\n\nexport function* askApiRequest<T, R>(\n service: string,\n method: HTTPMethod,\n endpoint: string,\n options?: ApiRequestOptions<T>,\n): ApiRequestActionRequester<T, R> {\n return yield {\n type: ApiActionType.Request,\n payload: {\n service,\n endpoint,\n method,\n body: options?.body,\n headers: options?.headers,\n params: options?.params,\n responseType: options?.responseType || 'json',\n },\n };\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { Action, ActionProcessor, ActionRequester, HTTPMethod, HTTPNetworkResponse, HTTPRequestOptions, ResponseType } from 'quidproquo-core';
2
+ import { ApiActionType } from './ApiActionType';
3
+ export type ApiRequestOptions<T> = Omit<HTTPRequestOptions<T>, 'basePath'>;
4
+ export interface ApiRequestActionPayload<T> {
5
+ service: string;
6
+ endpoint: string;
7
+ method: HTTPMethod;
8
+ body?: T;
9
+ params?: Record<string, string>;
10
+ headers?: Record<string, string>;
11
+ responseType: ResponseType;
12
+ }
13
+ export interface ApiRequestAction<T> extends Action<ApiRequestActionPayload<T>> {
14
+ type: ApiActionType.Request;
15
+ payload: ApiRequestActionPayload<T>;
16
+ }
17
+ export type ApiRequestActionProcessor<T, R> = ActionProcessor<ApiRequestAction<T>, HTTPNetworkResponse<R>>;
18
+ export type ApiRequestActionRequester<T, R> = ActionRequester<ApiRequestAction<T>, HTTPNetworkResponse<R>>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ApiRequestActionRequesterTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiRequestActionRequesterTypes.js","sourceRoot":"","sources":["../../../../src/actions/api/ApiRequestActionRequesterTypes.ts"],"names":[],"mappings":"","sourcesContent":["import { Action, ActionProcessor, ActionRequester, HTTPMethod, HTTPNetworkResponse, HTTPRequestOptions, ResponseType } from 'quidproquo-core';\n\nimport { ApiActionType } from './ApiActionType';\n\n// basePath is resolved by the processor, so it is omitted from the caller options\nexport type ApiRequestOptions<T> = Omit<HTTPRequestOptions<T>, 'basePath'>;\n\n// Payload\nexport interface ApiRequestActionPayload<T> {\n service: string;\n endpoint: string;\n method: HTTPMethod;\n body?: T;\n params?: Record<string, string>;\n headers?: Record<string, string>;\n responseType: ResponseType;\n}\n\n// Action\nexport interface ApiRequestAction<T> extends Action<ApiRequestActionPayload<T>> {\n type: ApiActionType.Request;\n payload: ApiRequestActionPayload<T>;\n}\n\n// Function Types\nexport type ApiRequestActionProcessor<T, R> = ActionProcessor<ApiRequestAction<T>, HTTPNetworkResponse<R>>;\nexport type ApiRequestActionRequester<T, R> = ActionRequester<ApiRequestAction<T>, HTTPNetworkResponse<R>>;\n"]}
@@ -0,0 +1,3 @@
1
+ export * from './ApiActionType';
2
+ export * from './ApiRequestActionRequester';
3
+ export * from './ApiRequestActionRequesterTypes';
@@ -0,0 +1,4 @@
1
+ export * from './ApiActionType';
2
+ export * from './ApiRequestActionRequester';
3
+ export * from './ApiRequestActionRequesterTypes';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/actions/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC","sourcesContent":["export * from './ApiActionType';\nexport * from './ApiRequestActionRequester';\nexport * from './ApiRequestActionRequesterTypes';\n"]}
@@ -1,4 +1,5 @@
1
1
  export * from './admin';
2
+ export * from './api';
2
3
  export * from './apiKeyValidation';
3
4
  export * from './dns';
4
5
  export * from './genericDataResource';
@@ -1,4 +1,5 @@
1
1
  export * from './admin';
2
+ export * from './api';
2
3
  export * from './apiKeyValidation';
3
4
  export * from './dns';
4
5
  export * from './genericDataResource';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/actions/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,OAAO,CAAC;AACtB,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC","sourcesContent":["export * from './admin';\nexport * from './apiKeyValidation';\nexport * from './dns';\nexport * from './genericDataResource';\nexport * from './openApiSpec';\nexport * from './routeAuthValidation';\nexport * from './serviceFunction';\nexport * from './webEntry';\nexport * from './websocket';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/actions/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,oBAAoB,CAAC;AACnC,cAAc,OAAO,CAAC;AACtB,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC","sourcesContent":["export * from './admin';\nexport * from './api';\nexport * from './apiKeyValidation';\nexport * from './dns';\nexport * from './genericDataResource';\nexport * from './openApiSpec';\nexport * from './routeAuthValidation';\nexport * from './serviceFunction';\nexport * from './webEntry';\nexport * from './websocket';\n"]}
@@ -6,5 +6,6 @@ export interface AuthSystemOptions {
6
6
  mfa?: UserDirectoryMfaSettings;
7
7
  basePath?: string;
8
8
  allowedOrigins?: string[];
9
+ accessTokenValidityMinutes?: number;
9
10
  }
10
11
  export declare const defineAuthSystem: (service: string, directoryName: string, options?: AuthSystemOptions) => QPQConfig;
@@ -19,6 +19,7 @@ export const defineAuthSystem = (service, directoryName, options) => {
19
19
  selfSignUpEnabled: options?.selfSignUpEnabled,
20
20
  emailTemplates: options?.emailTemplates,
21
21
  mfa: options?.mfa,
22
+ accessTokenValidityMinutes: options?.accessTokenValidityMinutes,
22
23
  owner: { module: service },
23
24
  }),
24
25
  // The login endpoints and their handlers only deploy with the owning service.
@@ -27,6 +28,12 @@ export const defineAuthSystem = (service, directoryName, options) => {
27
28
  defineGlobal(AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),
28
29
  defineAuthServiceRoute('POST', `${basePath}/login`, 'login', routeOptions),
29
30
  defineAuthServiceRoute('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),
31
+ // Public + best-effort (logout must never fail for the client, so it isn't
32
+ // edge-gated). /logout revokes just the caller's own refresh token (this device);
33
+ // /logoutEverywhere revokes all of the user's sessions (settings "sign out of all
34
+ // devices"). Each is self-authorizing: the refresh token / access token it carries.
35
+ defineAuthServiceRoute('POST', `${basePath}/logout`, 'logout', routeOptions),
36
+ defineAuthServiceRoute('POST', `${basePath}/logoutEverywhere`, 'logoutEverywhere', routeOptions),
30
37
  defineAuthServiceRoute('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),
31
38
  defineAuthServiceRoute('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),
32
39
  defineAuthServiceRoute('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),
@@ -1 +1 @@
1
- {"version":3,"file":"defineAuthSystem.js","sourceRoot":"","sources":["../../../../../src/config/settings/defineAuthSystem/defineAuthSystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAuD,MAAM,iBAAiB,CAAC;AAEhJ,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAiB9F,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,iCAAiC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,aAAqB,EAAE,OAA2B,EAAa,EAAE;IACjH,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG;QACnB,cAAc,EAAE,OAAO,EAAE,cAAc;KACxC,CAAC;IAEF,OAAO;QACL,qEAAqE;QACrE,0EAA0E;QAC1E,mBAAmB,CAAC,aAAa,EAAE;YACjC,aAAa,EAAE,OAAO,EAAE,aAAa;YACrC,iBAAiB,EAAE,OAAO,EAAE,iBAAiB;YAC7C,cAAc,EAAE,OAAO,EAAE,cAAc;YACvC,GAAG,EAAE,OAAO,EAAE,GAAG;YACjB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SAC3B,CAAC;QAEF,8EAA8E;QAC9E,qBAAqB,CAAC;YACpB,CAAC,OAAO,CAAC,EAAE;gBACT,YAAY,CAAC,8BAA8B,EAAE,aAAa,CAAC;gBAE3D,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC;gBAC1E,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC;gBACxF,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,YAAY,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC/F,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC5G,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,CAAC;gBAC5F,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,uBAAuB,EAAE,YAAY,CAAC;gBAE3G,+DAA+D;gBAC/D,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE;oBAC7E,GAAG,YAAY;oBACf,iBAAiB,EAAE;wBACjB,iBAAiB,EAAE,aAAa;qBACjC;iBACF,CAAC;aACH;SACF,CAAC;KACH,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { defineGlobal, defineServiceSettings, defineUserDirectory, EmailTemplates, QPQConfig, UserDirectoryMfaSettings } from 'quidproquo-core';\n\nimport { AUTH_USER_DIRECTORY_GLOBAL_KEY } from '../../../services/auth/config';\nimport { defineAuthServiceRoute } from '../../../services/auth/config/defineAuthServiceRoute';\n\nexport interface AuthSystemOptions {\n phoneRequired?: boolean;\n\n selfSignUpEnabled?: boolean;\n\n emailTemplates?: EmailTemplates;\n\n mfa?: UserDirectoryMfaSettings;\n\n // Path prefix applied to every auth route, e.g. '/auth' => '/auth/login'.\n basePath?: string;\n\n allowedOrigins?: string[];\n}\n\n// Bundles a complete username/password login flow: a user directory plus the\n// endpoints needed to log in, refresh tokens, respond to challenges, recover a\n// forgotten password, and change a password. The handler stories ship inside\n// quidproquo-webserver (services/auth) and resolve `directoryName` at runtime\n// from the global emitted below.\nexport const defineAuthSystem = (service: string, directoryName: string, options?: AuthSystemOptions): QPQConfig => {\n const basePath = options?.basePath ?? '';\n\n const routeOptions = {\n allowedOrigins: options?.allowedOrigins,\n };\n\n return [\n // The user directory is declared at the top level (ungated) so other\n // services in the application can reference it to validate access tokens.\n defineUserDirectory(directoryName, {\n phoneRequired: options?.phoneRequired,\n selfSignUpEnabled: options?.selfSignUpEnabled,\n emailTemplates: options?.emailTemplates,\n mfa: options?.mfa,\n owner: { module: service },\n }),\n\n // The login endpoints and their handlers only deploy with the owning service.\n defineServiceSettings({\n [service]: [\n defineGlobal(AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),\n\n defineAuthServiceRoute('POST', `${basePath}/login`, 'login', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword/confirm`, 'confirmForgotPassword', routeOptions),\n\n // Authenticated: the caller must present a valid access token.\n defineAuthServiceRoute('POST', `${basePath}/changePassword`, 'changePassword', {\n ...routeOptions,\n routeAuthSettings: {\n userDirectoryName: directoryName,\n },\n }),\n ],\n }),\n ];\n};\n"]}
1
+ {"version":3,"file":"defineAuthSystem.js","sourceRoot":"","sources":["../../../../../src/config/settings/defineAuthSystem/defineAuthSystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAuD,MAAM,iBAAiB,CAAC;AAEhJ,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAsB9F,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,iCAAiC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,aAAqB,EAAE,OAA2B,EAAa,EAAE;IACjH,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG;QACnB,cAAc,EAAE,OAAO,EAAE,cAAc;KACxC,CAAC;IAEF,OAAO;QACL,qEAAqE;QACrE,0EAA0E;QAC1E,mBAAmB,CAAC,aAAa,EAAE;YACjC,aAAa,EAAE,OAAO,EAAE,aAAa;YACrC,iBAAiB,EAAE,OAAO,EAAE,iBAAiB;YAC7C,cAAc,EAAE,OAAO,EAAE,cAAc;YACvC,GAAG,EAAE,OAAO,EAAE,GAAG;YACjB,0BAA0B,EAAE,OAAO,EAAE,0BAA0B;YAC/D,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SAC3B,CAAC;QAEF,8EAA8E;QAC9E,qBAAqB,CAAC;YACpB,CAAC,OAAO,CAAC,EAAE;gBACT,YAAY,CAAC,8BAA8B,EAAE,aAAa,CAAC;gBAE3D,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC;gBAC1E,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC;gBACxF,2EAA2E;gBAC3E,kFAAkF;gBAClF,kFAAkF;gBAClF,oFAAoF;gBACpF,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC;gBAC5E,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,CAAC;gBAChG,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,YAAY,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC/F,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,wBAAwB,EAAE,YAAY,CAAC;gBAC5G,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,CAAC;gBAC5F,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,yBAAyB,EAAE,uBAAuB,EAAE,YAAY,CAAC;gBAE3G,+DAA+D;gBAC/D,sBAAsB,CAAC,MAAM,EAAE,GAAG,QAAQ,iBAAiB,EAAE,gBAAgB,EAAE;oBAC7E,GAAG,YAAY;oBACf,iBAAiB,EAAE;wBACjB,iBAAiB,EAAE,aAAa;qBACjC;iBACF,CAAC;aACH;SACF,CAAC;KACH,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { defineGlobal, defineServiceSettings, defineUserDirectory, EmailTemplates, QPQConfig, UserDirectoryMfaSettings } from 'quidproquo-core';\n\nimport { AUTH_USER_DIRECTORY_GLOBAL_KEY } from '../../../services/auth/config';\nimport { defineAuthServiceRoute } from '../../../services/auth/config/defineAuthServiceRoute';\n\nexport interface AuthSystemOptions {\n phoneRequired?: boolean;\n\n selfSignUpEnabled?: boolean;\n\n emailTemplates?: EmailTemplates;\n\n mfa?: UserDirectoryMfaSettings;\n\n // Path prefix applied to every auth route, e.g. '/auth' => '/auth/login'.\n basePath?: string;\n\n allowedOrigins?: string[];\n\n // Access/ID token (JWT) lifetime in minutes (Cognito 5–1440; omitted → default 60).\n // Shorter shrinks the post-revocation window in which a stateless access token still\n // works. Keep comfortably above 10 (the web client refreshes ~10 min before expiry).\n accessTokenValidityMinutes?: number;\n}\n\n// Bundles a complete username/password login flow: a user directory plus the\n// endpoints needed to log in, refresh tokens, respond to challenges, recover a\n// forgotten password, and change a password. The handler stories ship inside\n// quidproquo-webserver (services/auth) and resolve `directoryName` at runtime\n// from the global emitted below.\nexport const defineAuthSystem = (service: string, directoryName: string, options?: AuthSystemOptions): QPQConfig => {\n const basePath = options?.basePath ?? '';\n\n const routeOptions = {\n allowedOrigins: options?.allowedOrigins,\n };\n\n return [\n // The user directory is declared at the top level (ungated) so other\n // services in the application can reference it to validate access tokens.\n defineUserDirectory(directoryName, {\n phoneRequired: options?.phoneRequired,\n selfSignUpEnabled: options?.selfSignUpEnabled,\n emailTemplates: options?.emailTemplates,\n mfa: options?.mfa,\n accessTokenValidityMinutes: options?.accessTokenValidityMinutes,\n owner: { module: service },\n }),\n\n // The login endpoints and their handlers only deploy with the owning service.\n defineServiceSettings({\n [service]: [\n defineGlobal(AUTH_USER_DIRECTORY_GLOBAL_KEY, directoryName),\n\n defineAuthServiceRoute('POST', `${basePath}/login`, 'login', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/refreshToken`, 'refreshToken', routeOptions),\n // Public + best-effort (logout must never fail for the client, so it isn't\n // edge-gated). /logout revokes just the caller's own refresh token (this device);\n // /logoutEverywhere revokes all of the user's sessions (settings \"sign out of all\n // devices\"). Each is self-authorizing: the refresh token / access token it carries.\n defineAuthServiceRoute('POST', `${basePath}/logout`, 'logout', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/logoutEverywhere`, 'logoutEverywhere', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/challenge`, 'respondToAuthChallenge', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/associateSoftwareToken`, 'associateSoftwareToken', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword`, 'forgotPassword', routeOptions),\n defineAuthServiceRoute('POST', `${basePath}/forgotPassword/confirm`, 'confirmForgotPassword', routeOptions),\n\n // Authenticated: the caller must present a valid access token.\n defineAuthServiceRoute('POST', `${basePath}/changePassword`, 'changePassword', {\n ...routeOptions,\n routeAuthSettings: {\n userDirectoryName: directoryName,\n },\n }),\n ],\n }),\n ];\n};\n"]}
@@ -2,6 +2,8 @@ import { AskResponse } from 'quidproquo-core';
2
2
  import { HTTPEvent, HTTPEventResponse } from '../../../../types';
3
3
  export declare function login(event: HTTPEvent): AskResponse<HTTPEventResponse>;
4
4
  export declare function refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse>;
5
+ export declare function logout(event: HTTPEvent): AskResponse<HTTPEventResponse>;
6
+ export declare function logoutEverywhere(event: HTTPEvent): AskResponse<HTTPEventResponse>;
5
7
  export declare function respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse>;
6
8
  export declare function associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse>;
7
9
  export declare function forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse>;
@@ -1,4 +1,4 @@
1
- import { askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';
1
+ import { askCatch, askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';
2
2
  // TODO: Fix this import (name it up the chain)
3
3
  import { qpqWebServerUtils } from '../../../../index';
4
4
  import { authLogic } from '../../logic';
@@ -56,6 +56,27 @@ export function* refreshToken(event) {
56
56
  const refreshResponse = yield* authLogic.askRefreshToken(refreshToken);
57
57
  return qpqWebServerUtils.toJsonEventResponse(refreshResponse);
58
58
  }
59
+ export function* logout(event) {
60
+ // "Log out this device": revoke ONLY the caller's own refresh token (Cognito RevokeToken),
61
+ // leaving the user's other sessions signed in. The client sends its refresh token in the
62
+ // body. Best-effort — logout must always succeed for the client (it clears local state
63
+ // regardless), so an already-revoked/invalid token is swallowed rather than 4xx'd. Public
64
+ // route: possessing the refresh token is the authorization (you can only revoke your own).
65
+ const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest(event, requireStringFields('refreshToken'));
66
+ yield* askCatch(authLogic.askRevokeSession(refreshToken));
67
+ return qpqWebServerUtils.toJsonEventResponse({ success: true });
68
+ }
69
+ export function* logoutEverywhere(event) {
70
+ // "Log out everywhere": revoke EVERY refresh token for the user (Cognito GlobalSignOut),
71
+ // for a user-settings "sign out of all devices" action. Authorized by the access token in
72
+ // the header (GlobalSignOut validates it at Cognito). Best-effort / always 200, same as
73
+ // above — swallow an invalid/expired token rather than failing the client's logout.
74
+ const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);
75
+ if (accessToken) {
76
+ yield* askCatch(authLogic.askSignOut(accessToken));
77
+ }
78
+ return qpqWebServerUtils.toJsonEventResponse({ success: true });
79
+ }
59
80
  export function* respondToAuthChallenge(event) {
60
81
  const payload = yield* qpqWebServerUtils.askFromValidJsonEventRequest(event, requireStringFields('email', 'session', 'challenge'));
61
82
  const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);
@@ -1 +1 @@
1
- {"version":3,"file":"authController.js","sourceRoot":"","sources":["../../../../../../src/services/auth/entry/controller/authController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,aAAa,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEzH,+CAA+C;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAOL,qBAAqB,EACrB,0BAA0B,EAC1B,6BAA6B,GAG9B,MAAM,aAAa,CAAC;AAErB,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,mBAAmB,GACvB,CAAI,GAAG,MAAgB,EAAE,EAAE,CAC3B,CAAC,IAAa,EAAK,EAAE;IACnB,MAAM,MAAM,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAEpG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC,CAAC;AAEJ,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,qEAAqE;AACrE,QAAQ,CAAC,CAAC,kCAAkC,CAAC,OAA4B;IACvE,IAAI,6BAA6B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,SAAS,EAAE,yBAAyB,CAAC,qBAAqB;YAC1D,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC;IACJ,CAAC;IAED,IAAI,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,SAAS,EAAE,yBAAyB,CAAC,kBAAkB;YACvD,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,IAAI,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,SAAS,EAAE,yBAAyB,CAAC,SAAS;YAC9C,QAAQ,EAAE,OAAO,CAAC,KAAK;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,EAAE,4CAA6C,OAA4B,CAAC,SAAS,EAAE,CAAC,CAAC;AAC/I,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,KAAK,CAAC,KAAgB;IACrC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CAClF,KAAK,EACL,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAC5C,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEnE,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,YAAY,CAAC,KAAgB;IAC5C,MAAM,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CAAiB,KAAK,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAC;IAE3I,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAEvE,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,sBAAsB,CAAC,KAAgB;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CACnE,KAAK,EACL,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CACrD,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;IAEzE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC;IAE3E,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,sBAAsB,CAAC,KAAgB;IACtD,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CAAgC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhJ,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAErE,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,cAAc,CAAC,KAAgB;IAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CAAwB,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;IAE1I,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAErE,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,qBAAqB,CAAC,KAAgB;IACrD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CACxF,KAAK,EACL,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CACpD,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAErF,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,cAAc,CAAC,KAAgB;IAC9C,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,4BAA4B,CACxF,KAAK,EACL,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAClD,CAAC;IAEF,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,WAAW,GAAG,iBAAiB,CAAC,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAE1E,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import { AnyAuthChallenge, AskResponse, askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';\n\n// TODO: Fix this import (name it up the chain)\nimport { qpqWebServerUtils } from '../../../../index';\nimport { HTTPEvent, HTTPEventResponse } from '../../../../types';\nimport { authLogic } from '../../logic';\nimport {\n AnyChallengePayload,\n AssociateSoftwareTokenPayload,\n ChallengePayload,\n ChangePasswordPayload,\n ConfirmForgotPasswordPayload,\n ForgotPasswordPayload,\n isMfaChallengePayload,\n isMfaSetupChallengePayload,\n isNewPasswordChallengePayload,\n LoginPayload,\n RefreshPayload,\n} from '../../types';\n\n// Field-presence validator for askFromValidJsonEventRequest. The payload types\n// are just casts over whatever json the client sent, so each handler checks its\n// required fields are real non-empty strings before anything touches the user\n// directory. A miss comes back as a 422 Invalid instead of a downstream error.\nconst requireStringFields =\n <T>(...fields: string[]) =>\n (data: unknown): T => {\n const record = (data ?? {}) as Record<string, unknown>;\n const missing = fields.filter((field) => typeof record[field] !== 'string' || record[field] === '');\n\n if (missing.length > 0) {\n throw new Error(`Missing or invalid fields: ${missing.join(', ')}`);\n }\n\n return data as T;\n };\n\n// Maps the wire payload (discriminated by `challenge`) onto the core auth\n// challenge shape. The type guards narrow `payload`, so no manual casts are\n// needed. Add a branch here as new challenge types are supported. An unknown\n// or malformed challenge is a client error, so it surfaces as a 400.\nfunction* askChallengePayloadToAuthChallenge(payload: AnyChallengePayload): AskResponse<AnyAuthChallenge> {\n if (isNewPasswordChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED,\n username: payload.email,\n session: payload.session,\n newPassword: payload.newPassword,\n };\n }\n\n if (isMfaChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n if (isMfaSetupChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.MFA_SETUP,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n return yield* askThrowError(ErrorTypeEnum.BadRequest, `Unsupported or malformed auth challenge: ${(payload as ChallengePayload).challenge}`);\n}\n\nexport function* login(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<LoginPayload>(\n event,\n requireStringFields('username', 'password'),\n );\n\n const authResponse = yield* authLogic.askLogin(username, password);\n\n return qpqWebServerUtils.toJsonEventResponse(authResponse);\n}\n\nexport function* refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n const refreshResponse = yield* authLogic.askRefreshToken(refreshToken);\n\n return qpqWebServerUtils.toJsonEventResponse(refreshResponse);\n}\n\nexport function* respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const payload = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AnyChallengePayload>(\n event,\n requireStringFields('email', 'session', 'challenge'),\n );\n\n const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);\n\n const response = yield* authLogic.askRespondToAuthChallenge(authChallenge);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { session } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AssociateSoftwareTokenPayload>(event, requireStringFields('session'));\n\n const response = yield* authLogic.askAssociateSoftwareToken(session);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ForgotPasswordPayload>(event, requireStringFields('username'));\n\n const deliveryDetails = yield* authLogic.askForgotPassword(username);\n\n return qpqWebServerUtils.toJsonEventResponse(deliveryDetails);\n}\n\nexport function* confirmForgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, code, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ConfirmForgotPasswordPayload>(\n event,\n requireStringFields('username', 'code', 'password'),\n );\n\n const response = yield* authLogic.askConfirmForgotPassword(username, code, password);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* changePassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { oldPassword, newPassword } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ChangePasswordPayload>(\n event,\n requireStringFields('oldPassword', 'newPassword'),\n );\n\n // The route is authenticated, so the access token should always be present.\n // Guard anyway so a misconfigured route fails as a 401, not a directory error.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n if (!accessToken) {\n return yield* askThrowError(ErrorTypeEnum.Unauthorized, 'Missing access token.');\n }\n\n yield* authLogic.askChangePassword(oldPassword, newPassword, accessToken);\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n"]}
1
+ {"version":3,"file":"authController.js","sourceRoot":"","sources":["../../../../../../src/services/auth/entry/controller/authController.ts"],"names":[],"mappings":"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","sourcesContent":["import { AnyAuthChallenge, askCatch, AskResponse, askThrowError, AuthenticateUserChallenge, ErrorTypeEnum } from 'quidproquo-core';\n\n// TODO: Fix this import (name it up the chain)\nimport { qpqWebServerUtils } from '../../../../index';\nimport { HTTPEvent, HTTPEventResponse } from '../../../../types';\nimport { authLogic } from '../../logic';\nimport {\n AnyChallengePayload,\n AssociateSoftwareTokenPayload,\n ChallengePayload,\n ChangePasswordPayload,\n ConfirmForgotPasswordPayload,\n ForgotPasswordPayload,\n isMfaChallengePayload,\n isMfaSetupChallengePayload,\n isNewPasswordChallengePayload,\n LoginPayload,\n RefreshPayload,\n} from '../../types';\n\n// Field-presence validator for askFromValidJsonEventRequest. The payload types\n// are just casts over whatever json the client sent, so each handler checks its\n// required fields are real non-empty strings before anything touches the user\n// directory. A miss comes back as a 422 Invalid instead of a downstream error.\nconst requireStringFields =\n <T>(...fields: string[]) =>\n (data: unknown): T => {\n const record = (data ?? {}) as Record<string, unknown>;\n const missing = fields.filter((field) => typeof record[field] !== 'string' || record[field] === '');\n\n if (missing.length > 0) {\n throw new Error(`Missing or invalid fields: ${missing.join(', ')}`);\n }\n\n return data as T;\n };\n\n// Maps the wire payload (discriminated by `challenge`) onto the core auth\n// challenge shape. The type guards narrow `payload`, so no manual casts are\n// needed. Add a branch here as new challenge types are supported. An unknown\n// or malformed challenge is a client error, so it surfaces as a 400.\nfunction* askChallengePayloadToAuthChallenge(payload: AnyChallengePayload): AskResponse<AnyAuthChallenge> {\n if (isNewPasswordChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.NEW_PASSWORD_REQUIRED,\n username: payload.email,\n session: payload.session,\n newPassword: payload.newPassword,\n };\n }\n\n if (isMfaChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.SOFTWARE_TOKEN_MFA,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n if (isMfaSetupChallengePayload(payload)) {\n return {\n challenge: AuthenticateUserChallenge.MFA_SETUP,\n username: payload.email,\n session: payload.session,\n mfaCode: payload.mfaCode,\n };\n }\n\n return yield* askThrowError(ErrorTypeEnum.BadRequest, `Unsupported or malformed auth challenge: ${(payload as ChallengePayload).challenge}`);\n}\n\nexport function* login(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<LoginPayload>(\n event,\n requireStringFields('username', 'password'),\n );\n\n const authResponse = yield* authLogic.askLogin(username, password);\n\n return qpqWebServerUtils.toJsonEventResponse(authResponse);\n}\n\nexport function* refreshToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n const refreshResponse = yield* authLogic.askRefreshToken(refreshToken);\n\n return qpqWebServerUtils.toJsonEventResponse(refreshResponse);\n}\n\nexport function* logout(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n // \"Log out this device\": revoke ONLY the caller's own refresh token (Cognito RevokeToken),\n // leaving the user's other sessions signed in. The client sends its refresh token in the\n // body. Best-effort — logout must always succeed for the client (it clears local state\n // regardless), so an already-revoked/invalid token is swallowed rather than 4xx'd. Public\n // route: possessing the refresh token is the authorization (you can only revoke your own).\n const { refreshToken } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<RefreshPayload>(event, requireStringFields('refreshToken'));\n\n yield* askCatch(authLogic.askRevokeSession(refreshToken));\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n\nexport function* logoutEverywhere(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n // \"Log out everywhere\": revoke EVERY refresh token for the user (Cognito GlobalSignOut),\n // for a user-settings \"sign out of all devices\" action. Authorized by the access token in\n // the header (GlobalSignOut validates it at Cognito). Best-effort / always 200, same as\n // above — swallow an invalid/expired token rather than failing the client's logout.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n\n if (accessToken) {\n yield* askCatch(authLogic.askSignOut(accessToken));\n }\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n\nexport function* respondToAuthChallenge(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const payload = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AnyChallengePayload>(\n event,\n requireStringFields('email', 'session', 'challenge'),\n );\n\n const authChallenge = yield* askChallengePayloadToAuthChallenge(payload);\n\n const response = yield* authLogic.askRespondToAuthChallenge(authChallenge);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* associateSoftwareToken(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { session } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<AssociateSoftwareTokenPayload>(event, requireStringFields('session'));\n\n const response = yield* authLogic.askAssociateSoftwareToken(session);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* forgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ForgotPasswordPayload>(event, requireStringFields('username'));\n\n const deliveryDetails = yield* authLogic.askForgotPassword(username);\n\n return qpqWebServerUtils.toJsonEventResponse(deliveryDetails);\n}\n\nexport function* confirmForgotPassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { username, code, password } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ConfirmForgotPasswordPayload>(\n event,\n requireStringFields('username', 'code', 'password'),\n );\n\n const response = yield* authLogic.askConfirmForgotPassword(username, code, password);\n\n return qpqWebServerUtils.toJsonEventResponse(response);\n}\n\nexport function* changePassword(event: HTTPEvent): AskResponse<HTTPEventResponse> {\n const { oldPassword, newPassword } = yield* qpqWebServerUtils.askFromValidJsonEventRequest<ChangePasswordPayload>(\n event,\n requireStringFields('oldPassword', 'newPassword'),\n );\n\n // The route is authenticated, so the access token should always be present.\n // Guard anyway so a misconfigured route fails as a 401, not a directory error.\n const accessToken = qpqWebServerUtils.getAccessTokenFromHeaders(event.headers);\n if (!accessToken) {\n return yield* askThrowError(ErrorTypeEnum.Unauthorized, 'Missing access token.');\n }\n\n yield* authLogic.askChangePassword(oldPassword, newPassword, accessToken);\n\n return qpqWebServerUtils.toJsonEventResponse({ success: true });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { AskResponse } from 'quidproquo-core';
2
+ export declare function askRevokeSession(refreshToken: string): AskResponse<void>;
@@ -0,0 +1,10 @@
1
+ import { askUserDirectoryRevokeRefreshToken } from 'quidproquo-core';
2
+ import { askGetAuthUserDirectoryName } from './askGetAuthUserDirectoryName';
3
+ // Revokes a single session by its refresh token (Cognito RevokeToken) — "log out this
4
+ // device". Other sessions for the same user are unaffected (contrast askSignOut, which is
5
+ // a global sign-out of every session).
6
+ export function* askRevokeSession(refreshToken) {
7
+ const userDirectoryName = yield* askGetAuthUserDirectoryName();
8
+ yield* askUserDirectoryRevokeRefreshToken(userDirectoryName, refreshToken);
9
+ }
10
+ //# sourceMappingURL=askRevokeSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askRevokeSession.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/askRevokeSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,kCAAkC,EAAE,MAAM,iBAAiB,CAAC;AAElF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,sFAAsF;AACtF,0FAA0F;AAC1F,uCAAuC;AACvC,MAAM,SAAS,CAAC,CAAC,gBAAgB,CAAC,YAAoB;IACpD,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,2BAA2B,EAAE,CAAC;IAE/D,KAAK,CAAC,CAAC,kCAAkC,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { AskResponse, askUserDirectoryRevokeRefreshToken } from 'quidproquo-core';\n\nimport { askGetAuthUserDirectoryName } from './askGetAuthUserDirectoryName';\n\n// Revokes a single session by its refresh token (Cognito RevokeToken) — \"log out this\n// device\". Other sessions for the same user are unaffected (contrast askSignOut, which is\n// a global sign-out of every session).\nexport function* askRevokeSession(refreshToken: string): AskResponse<void> {\n const userDirectoryName = yield* askGetAuthUserDirectoryName();\n\n yield* askUserDirectoryRevokeRefreshToken(userDirectoryName, refreshToken);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { AskResponse } from 'quidproquo-core';
2
+ export declare function askSignOut(accessToken: string): AskResponse<void>;
@@ -0,0 +1,8 @@
1
+ import { askUserDirectorySignOutUser } from 'quidproquo-core';
2
+ // Revokes every refresh token for the owner of this access token (server-side session
3
+ // kill). Cognito's GlobalSignOut is authorized by the access token itself, so no user
4
+ // directory name is needed here.
5
+ export function* askSignOut(accessToken) {
6
+ yield* askUserDirectorySignOutUser(accessToken);
7
+ }
8
+ //# sourceMappingURL=askSignOut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askSignOut.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/askSignOut.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAE3E,sFAAsF;AACtF,sFAAsF;AACtF,iCAAiC;AACjC,MAAM,SAAS,CAAC,CAAC,UAAU,CAAC,WAAmB;IAC7C,KAAK,CAAC,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { AskResponse, askUserDirectorySignOutUser } from 'quidproquo-core';\n\n// Revokes every refresh token for the owner of this access token (server-side session\n// kill). Cognito's GlobalSignOut is authorized by the access token itself, so no user\n// directory name is needed here.\nexport function* askSignOut(accessToken: string): AskResponse<void> {\n yield* askUserDirectorySignOutUser(accessToken);\n}\n"]}
@@ -6,3 +6,5 @@ export * from './askGetAuthUserDirectoryName';
6
6
  export * from './askLogin';
7
7
  export * from './askRefreshToken';
8
8
  export * from './askRespondToAuthChallenge';
9
+ export * from './askRevokeSession';
10
+ export * from './askSignOut';
@@ -6,4 +6,6 @@ export * from './askGetAuthUserDirectoryName';
6
6
  export * from './askLogin';
7
7
  export * from './askRefreshToken';
8
8
  export * from './askRespondToAuthChallenge';
9
+ export * from './askRevokeSession';
10
+ export * from './askSignOut';
9
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC","sourcesContent":["export * from './askAssociateSoftwareToken';\nexport * from './askChangePassword';\nexport * from './askConfirmForgotPassword';\nexport * from './askForgotPassword';\nexport * from './askGetAuthUserDirectoryName';\nexport * from './askLogin';\nexport * from './askRefreshToken';\nexport * from './askRespondToAuthChallenge';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/services/auth/logic/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC","sourcesContent":["export * from './askAssociateSoftwareToken';\nexport * from './askChangePassword';\nexport * from './askConfirmForgotPassword';\nexport * from './askForgotPassword';\nexport * from './askGetAuthUserDirectoryName';\nexport * from './askLogin';\nexport * from './askRefreshToken';\nexport * from './askRespondToAuthChallenge';\nexport * from './askRevokeSession';\nexport * from './askSignOut';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-webserver",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -33,10 +33,10 @@
33
33
  "homepage": "https://github.com/joe-coady/quidproquo#readme",
34
34
  "dependencies": {
35
35
  "@anthropic-ai/sdk": "^0.19.1",
36
- "quidproquo-core": "0.1.8"
36
+ "quidproquo-core": "0.1.10"
37
37
  },
38
38
  "devDependencies": {
39
- "quidproquo-tsconfig": "0.1.8",
39
+ "quidproquo-tsconfig": "0.1.10",
40
40
  "typescript": "^5.8.2"
41
41
  }
42
42
  }