@perseidesjs/auth-otp 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.github/assets/dark_mode.png +0 -0
  2. package/.github/assets/light_mode.png +0 -0
  3. package/.github/assets/preview.gif +0 -0
  4. package/.medusa/server/src/api/auth/[actor_type]/otp/generate/route.js +35 -0
  5. package/.medusa/server/src/api/auth/[actor_type]/otp/generate/validators.js +8 -0
  6. package/.medusa/server/src/api/auth/[actor_type]/otp/pre-register/route.js +35 -0
  7. package/.medusa/server/src/api/auth/[actor_type]/otp/pre-register/validators.js +8 -0
  8. package/.medusa/server/src/api/auth/[actor_type]/otp/verify/route.js +51 -0
  9. package/.medusa/server/src/api/auth/[actor_type]/otp/verify/validators.js +9 -0
  10. package/.medusa/server/src/api/middlewares.js +32 -0
  11. package/.medusa/server/src/providers/otp/index.d.ts +2 -0
  12. package/.medusa/server/src/providers/otp/index.js +12 -0
  13. package/.medusa/server/src/providers/otp/services/otp.d.ts +17 -0
  14. package/.medusa/server/src/providers/otp/services/otp.js +130 -0
  15. package/.medusa/server/src/types/index.d.ts +111 -0
  16. package/.medusa/server/src/types/index.js +9 -0
  17. package/.medusa/server/src/utils/get-plugin-options.d.ts +20 -0
  18. package/.medusa/server/src/utils/get-plugin-options.js +31 -0
  19. package/.medusa/server/src/utils/otp.d.ts +14 -0
  20. package/.medusa/server/src/utils/otp.js +43 -0
  21. package/.medusa/server/src/workflows/generate-otp.d.ts +16 -0
  22. package/.medusa/server/src/workflows/generate-otp.js +43 -0
  23. package/.medusa/server/src/workflows/index.d.ts +20 -0
  24. package/.medusa/server/src/workflows/index.js +15 -0
  25. package/.medusa/server/src/workflows/pre-register-check.js +49 -0
  26. package/.medusa/server/src/workflows/steps/generate-otp-step.d.ts +13 -0
  27. package/.medusa/server/src/workflows/steps/generate-otp-step.js +28 -0
  28. package/.medusa/server/src/workflows/steps/get-actor-step.d.ts +17 -0
  29. package/.medusa/server/src/workflows/steps/get-actor-step.js +39 -0
  30. package/.medusa/server/src/workflows/steps/get-auth-identity-step.d.ts +18 -0
  31. package/.medusa/server/src/workflows/steps/get-auth-identity-step.js +37 -0
  32. package/.medusa/server/src/workflows/steps/get-stored-otp-step.d.ts +13 -0
  33. package/.medusa/server/src/workflows/steps/get-stored-otp-step.js +23 -0
  34. package/.medusa/server/src/workflows/steps/pre-register-check-actor-existence.js +19 -0
  35. package/.medusa/server/src/workflows/steps/validate-otp-step.d.ts +13 -0
  36. package/.medusa/server/src/workflows/steps/validate-otp-step.js +18 -0
  37. package/.medusa/server/src/workflows/verify-otp.d.ts +20 -0
  38. package/.medusa/server/src/workflows/verify-otp.js +43 -0
  39. package/CHANGELOG.md +30 -0
  40. package/LICENSE.md +21 -0
  41. package/README.md +29 -0
  42. package/package.json +84 -0
Binary file
Binary file
Binary file
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const get_plugin_options_1 = __importDefault(require("../../../../../utils/get-plugin-options"));
9
+ const generate_otp_1 = __importDefault(require("../../../../../workflows/generate-otp"));
10
+ const POST = async (req, res) => {
11
+ const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
12
+ const { identifier } = req.validatedBody;
13
+ const actorType = req.params.actor_type;
14
+ const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
15
+ const pluginOptions = (0, get_plugin_options_1.default)(configModule);
16
+ const accessorsPerActor = pluginOptions.accessorsPerActor[actorType];
17
+ await (0, generate_otp_1.default)(req.scope).run({
18
+ input: {
19
+ identifier,
20
+ actorType,
21
+ accessorsPerActor
22
+ }
23
+ }).catch((error) => {
24
+ if (pluginOptions.http?.alwaysReturnSuccess) {
25
+ if (pluginOptions.http.warnOnError) {
26
+ logger.error(error);
27
+ }
28
+ return;
29
+ }
30
+ throw error;
31
+ });
32
+ res.send({ message: 'If an account exists with this identifier, an OTP will be sent.' });
33
+ };
34
+ exports.POST = POST;
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvW2FjdG9yX3R5cGVdL290cC9nZW5lcmF0ZS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFLQSxxREFBcUU7QUFDckUsaUdBQXNFO0FBQ3RFLHlGQUF1RTtBQUVoRSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQXNELEVBQ3RELEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUVsRSxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQTtJQUN4QyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQTtJQUV2QyxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUMvRSxNQUFNLGFBQWEsR0FBRyxJQUFBLDRCQUFnQixFQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXBELE1BQU0saUJBQWlCLEdBQUcsYUFBYSxDQUFDLGlCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBRXJFLE1BQU0sSUFBQSxzQkFBbUIsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ3ZDLEtBQUssRUFBRTtZQUNMLFVBQVU7WUFDVixTQUFTO1lBQ1QsaUJBQWlCO1NBQ2xCO0tBQ0YsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQ2pCLElBQUksYUFBYSxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1lBQzVDLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNyQixDQUFDO1lBQ0QsT0FBTTtRQUNSLENBQUM7UUFDRCxNQUFNLEtBQUssQ0FBQTtJQUNiLENBQUMsQ0FBQyxDQUFBO0lBRUYsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxpRUFBaUUsRUFBRSxDQUFDLENBQUE7QUFDMUYsQ0FBQyxDQUFBO0FBL0JZLFFBQUEsSUFBSSxRQStCaEIifQ==
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostAuthActorTypeOtpGenerateSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.PostAuthActorTypeOtpGenerateSchema = zod_1.z.object({
6
+ identifier: zod_1.z.string().min(1),
7
+ });
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9bYWN0b3JfdHlwZV0vb3RwL2dlbmVyYXRlL3ZhbGlkYXRvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQXVCO0FBR1YsUUFBQSxrQ0FBa0MsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3pELFVBQVUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztDQUM5QixDQUFDLENBQUEifQ==
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const get_plugin_options_1 = __importDefault(require("../../../../../utils/get-plugin-options"));
9
+ const pre_register_check_1 = __importDefault(require("../../../../../workflows/pre-register-check"));
10
+ const POST = async (req, res) => {
11
+ const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
12
+ const { identifier } = req.validatedBody;
13
+ const actorType = req.params.actor_type;
14
+ const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
15
+ const pluginOptions = (0, get_plugin_options_1.default)(configModule);
16
+ const accessorsPerActor = pluginOptions.accessorsPerActor[actorType];
17
+ await (0, pre_register_check_1.default)(req.scope).run({
18
+ input: {
19
+ identifier,
20
+ actorType,
21
+ accessorsPerActor
22
+ }
23
+ }).catch((error) => {
24
+ if (pluginOptions.http?.alwaysReturnSuccess) {
25
+ if (pluginOptions.http.warnOnError) {
26
+ logger.error(error);
27
+ }
28
+ return;
29
+ }
30
+ throw error;
31
+ });
32
+ res.send({ message: 'Please validate the OTP to continue with the registration process.' });
33
+ };
34
+ exports.POST = POST;
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvW2FjdG9yX3R5cGVdL290cC9wcmUtcmVnaXN0ZXIvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBS0EscURBQXFFO0FBQ3JFLGlHQUFzRTtBQUV0RSxxR0FBa0Y7QUFFM0UsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN2QixHQUF5RCxFQUN6RCxHQUFtQixFQUNuQixFQUFFO0lBQ0YsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFbEUsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxhQUFhLENBQUE7SUFDeEMsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUE7SUFFdkMsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUFDLENBQUE7SUFDL0UsTUFBTSxhQUFhLEdBQUcsSUFBQSw0QkFBZ0IsRUFBQyxZQUFZLENBQUMsQ0FBQTtJQUVwRCxNQUFNLGlCQUFpQixHQUFHLGFBQWEsQ0FBQyxpQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUVyRSxNQUFNLElBQUEsNEJBQXdCLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUM1QyxLQUFLLEVBQUU7WUFDTCxVQUFVO1lBQ1YsU0FBUztZQUNULGlCQUFpQjtTQUNsQjtLQUNGLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNqQixJQUFJLGFBQWEsQ0FBQyxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztZQUM1QyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ25DLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDckIsQ0FBQztZQUNELE9BQU07UUFDUixDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUE7SUFDYixDQUFDLENBQUMsQ0FBQTtJQUVGLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsb0VBQW9FLEVBQUUsQ0FBQyxDQUFBO0FBQzdGLENBQUMsQ0FBQTtBQS9CWSxRQUFBLElBQUksUUErQmhCIn0=
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostAuthActorTypeOtpPreRegisterSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.PostAuthActorTypeOtpPreRegisterSchema = zod_1.z.object({
6
+ identifier: zod_1.z.string().min(1),
7
+ });
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9bYWN0b3JfdHlwZV0vb3RwL3ByZS1yZWdpc3Rlci92YWxpZGF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUF1QjtBQUdWLFFBQUEscUNBQXFDLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUM1RCxVQUFVLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Q0FDOUIsQ0FBQyxDQUFBIn0=
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const get_plugin_options_1 = __importDefault(require("../../../../../utils/get-plugin-options"));
9
+ const verify_otp_1 = __importDefault(require("../../../../../workflows/verify-otp"));
10
+ const generate_jwt_token_1 = require("@medusajs/medusa/api/auth/utils/generate-jwt-token");
11
+ const framework_1 = require("@medusajs/framework");
12
+ const POST = async (req, res) => {
13
+ const { identifier, otp } = req.validatedBody;
14
+ const actorType = req.params.actor_type;
15
+ const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
16
+ const pluginOptions = (0, get_plugin_options_1.default)(configModule);
17
+ try {
18
+ const { result } = await (0, verify_otp_1.default)(req.scope).run({
19
+ input: {
20
+ identifier,
21
+ otp,
22
+ actorType,
23
+ accessorsPerActor: pluginOptions.accessorsPerActor[actorType]
24
+ }
25
+ });
26
+ if (result.isValid) {
27
+ const { http } = configModule.projectConfig;
28
+ const token = (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({ authIdentity: result.authIdentity, actorType }, {
29
+ secret: http.jwtSecret,
30
+ expiresIn: http.jwtExpiresIn
31
+ });
32
+ res.send({
33
+ token
34
+ });
35
+ }
36
+ else {
37
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid OTP`);
38
+ }
39
+ }
40
+ catch (error) {
41
+ if (pluginOptions.http?.alwaysReturnSuccess) {
42
+ if (pluginOptions.http.warnOnError) {
43
+ framework_1.logger.error(error);
44
+ }
45
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid OTP`);
46
+ }
47
+ throw error;
48
+ }
49
+ };
50
+ exports.POST = POST;
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvW2FjdG9yX3R5cGVdL290cC92ZXJpZnkvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBS0EscURBQWtGO0FBQ2xGLGlHQUFzRTtBQUN0RSxxRkFBbUU7QUFDbkUsMkZBQW9HO0FBQ3BHLG1EQUE0QztBQUVyQyxNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQW9ELEVBQ3BELEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxhQUFhLENBQUE7SUFDN0MsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUE7SUFFdkMsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUFDLENBQUE7SUFDL0UsTUFBTSxhQUFhLEdBQUcsSUFBQSw0QkFBZ0IsRUFBQyxZQUFZLENBQUMsQ0FBQTtJQUVwRCxJQUFJLENBQUM7UUFHSCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFBLG9CQUFpQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDeEQsS0FBSyxFQUFFO2dCQUNMLFVBQVU7Z0JBQ1YsR0FBRztnQkFDSCxTQUFTO2dCQUNULGlCQUFpQixFQUFFLGFBQWEsQ0FBQyxpQkFBa0IsQ0FBQyxTQUFTLENBQUM7YUFDL0Q7U0FDRixDQUFDLENBQUE7UUFFRixJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNuQixNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQTtZQUMzQyxNQUFNLEtBQUssR0FBRyxJQUFBLG9EQUErQixFQUFDLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFhLEVBQUUsU0FBUyxFQUFFLEVBQUU7Z0JBQy9GLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUztnQkFDdEIsU0FBUyxFQUFFLElBQUksQ0FBQyxZQUFZO2FBQzdCLENBQUMsQ0FBQTtZQUVGLEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ1AsS0FBSzthQUNOLENBQUMsQ0FBQTtRQUNKLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLG1CQUFXLENBQUMsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFBO1FBQ3RFLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksYUFBYSxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1lBQzVDLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkMsa0JBQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDckIsQ0FBQztZQUNELE1BQU0sSUFBSSxtQkFBVyxDQUFDLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQTtRQUN0RSxDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUE7SUFDYixDQUFDO0FBRUgsQ0FBQyxDQUFBO0FBN0NZLFFBQUEsSUFBSSxRQTZDaEIifQ==
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostAuthActorTypeOtpVerifySchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.PostAuthActorTypeOtpVerifySchema = zod_1.z.object({
6
+ identifier: zod_1.z.string().min(1),
7
+ otp: zod_1.z.string().min(1),
8
+ });
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9bYWN0b3JfdHlwZV0vb3RwL3ZlcmlmeS92YWxpZGF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUF1QjtBQUdWLFFBQUEsZ0NBQWdDLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUN2RCxVQUFVLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDN0IsR0FBRyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0NBQ3ZCLENBQUMsQ0FBQSJ9
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const http_1 = require("@medusajs/framework/http");
4
+ const validators_1 = require("./auth/[actor_type]/otp/generate/validators");
5
+ const validators_2 = require("./auth/[actor_type]/otp/verify/validators");
6
+ const validators_3 = require("./auth/[actor_type]/otp/pre-register/validators");
7
+ exports.default = (0, http_1.defineMiddlewares)({
8
+ routes: [
9
+ {
10
+ matcher: "/auth/:actor_type/otp/generate",
11
+ method: "POST",
12
+ middlewares: [
13
+ (0, http_1.validateAndTransformBody)(validators_1.PostAuthActorTypeOtpGenerateSchema),
14
+ ],
15
+ },
16
+ {
17
+ matcher: "/auth/:actor_type/otp/verify",
18
+ method: "POST",
19
+ middlewares: [
20
+ (0, http_1.validateAndTransformBody)(validators_2.PostAuthActorTypeOtpVerifySchema),
21
+ ],
22
+ },
23
+ {
24
+ matcher: "/auth/:actor_type/otp/pre-register",
25
+ method: "POST",
26
+ middlewares: [
27
+ (0, http_1.validateAndTransformBody)(validators_3.PostAuthActorTypeOtpPreRegisterSchema),
28
+ ],
29
+ },
30
+ ],
31
+ });
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBR2lDO0FBQ2pDLDRFQUFnRztBQUNoRywwRUFBNEY7QUFDNUYsZ0ZBQXVHO0FBRXZHLGtCQUFlLElBQUEsd0JBQWlCLEVBQUM7SUFDL0IsTUFBTSxFQUFFO1FBQ047WUFDRSxPQUFPLEVBQUUsZ0NBQWdDO1lBQ3pDLE1BQU0sRUFBRSxNQUFNO1lBQ2QsV0FBVyxFQUFFO2dCQUNYLElBQUEsK0JBQXdCLEVBQUMsK0NBQWtDLENBQUM7YUFDN0Q7U0FDRjtRQUNEO1lBQ0UsT0FBTyxFQUFFLDhCQUE4QjtZQUN2QyxNQUFNLEVBQUUsTUFBTTtZQUNkLFdBQVcsRUFBRTtnQkFDWCxJQUFBLCtCQUF3QixFQUFDLDZDQUFnQyxDQUFDO2FBQzNEO1NBQ0Y7UUFDRDtZQUNFLE9BQU8sRUFBRSxvQ0FBb0M7WUFDN0MsTUFBTSxFQUFFLE1BQU07WUFDZCxXQUFXLEVBQUU7Z0JBQ1gsSUFBQSwrQkFBd0IsRUFBQyxrREFBcUMsQ0FBQzthQUNoRTtTQUNGO0tBQ0Y7Q0FDRixDQUFDLENBQUEifQ==
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@medusajs/types").ModuleProviderExports;
2
+ export default _default;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const otp_1 = __importDefault(require("./services/otp"));
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const services = [otp_1.default];
9
+ exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.AUTH, {
10
+ services
11
+ });
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL290cC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHlEQUFtRDtBQUNuRCxxREFHa0M7QUFFbEMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxhQUFzQixDQUFDLENBQUE7QUFFekMsa0JBQWUsSUFBQSxzQkFBYyxFQUFDLGVBQU8sQ0FBQyxJQUFJLEVBQUU7SUFDMUMsUUFBUTtDQUNULENBQUMsQ0FBQSJ9
@@ -0,0 +1,17 @@
1
+ import { AuthenticationInput, AuthIdentityProviderService, AuthenticationResponse, ICacheService, Logger } from "@medusajs/framework/types";
2
+ import { AbstractAuthModuleProvider, ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils";
3
+ type InjectedDependencies = {
4
+ [Modules.CACHE]: ICacheService;
5
+ [ContainerRegistrationKeys.LOGGER]: Logger;
6
+ };
7
+ export declare const OTP_RETURN_KEY = "otp_generated";
8
+ export declare const RECENTLY_REGISTERED_KEY = "recently_registered";
9
+ export declare class OtpAuthProviderService extends AbstractAuthModuleProvider {
10
+ static identifier: string;
11
+ protected cacheService_: ICacheService;
12
+ protected logger_: Logger;
13
+ constructor(container: InjectedDependencies);
14
+ authenticate(data: AuthenticationInput, authIdentityProviderService: AuthIdentityProviderService): Promise<AuthenticationResponse>;
15
+ register(data: AuthenticationInput, authIdentityProviderService: AuthIdentityProviderService): Promise<AuthenticationResponse>;
16
+ }
17
+ export default OtpAuthProviderService;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OtpAuthProviderService = exports.RECENTLY_REGISTERED_KEY = exports.OTP_RETURN_KEY = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ exports.OTP_RETURN_KEY = "otp_generated";
6
+ // Special key used to store recently registered identifiers for direct authentication
7
+ exports.RECENTLY_REGISTERED_KEY = "recently_registered";
8
+ class OtpAuthProviderService extends utils_1.AbstractAuthModuleProvider {
9
+ constructor(container) {
10
+ super();
11
+ this.cacheService_ = container[utils_1.Modules.CACHE];
12
+ this.logger_ = container[utils_1.ContainerRegistrationKeys.LOGGER];
13
+ }
14
+ async authenticate(data, authIdentityProviderService) {
15
+ if (!(0, utils_1.isDefined)(data.body?.identifier)) {
16
+ return {
17
+ success: false,
18
+ error: "Identifier is required"
19
+ };
20
+ }
21
+ const identifier = data.body.identifier;
22
+ try {
23
+ // Check if this is a recently registered user (within the TTL window)
24
+ const isRecentlyRegistered = await this.cacheService_.get(`${exports.RECENTLY_REGISTERED_KEY}:${identifier}:${data.body.otp}`);
25
+ if (isRecentlyRegistered === "true") {
26
+ // If recently registered, allow direct authentication without OTP
27
+ try {
28
+ const authIdentity = await authIdentityProviderService.retrieve({
29
+ entity_id: identifier,
30
+ });
31
+ await this.cacheService_.invalidate(`${exports.RECENTLY_REGISTERED_KEY}:${identifier}`);
32
+ return {
33
+ success: true,
34
+ authIdentity
35
+ };
36
+ }
37
+ catch (error) {
38
+ return {
39
+ success: false,
40
+ error: "Authentication failed"
41
+ };
42
+ }
43
+ }
44
+ // If not recently registered and no OTP provided, we need to generate a new OTP
45
+ if (!(0, utils_1.isDefined)(data.body?.otp)) {
46
+ return {
47
+ success: false,
48
+ error: "OTP is required for authentication"
49
+ };
50
+ }
51
+ // Verify the OTP
52
+ const otp = await this.cacheService_.get(`otp:${identifier}`);
53
+ if (otp !== data.body.otp) {
54
+ return {
55
+ success: false,
56
+ error: "Invalid OTP"
57
+ };
58
+ }
59
+ // OTP is valid, retrieve the auth identity
60
+ const authIdentity = await authIdentityProviderService.retrieve({
61
+ entity_id: identifier,
62
+ });
63
+ return {
64
+ success: true,
65
+ authIdentity
66
+ };
67
+ }
68
+ catch (error) {
69
+ this.logger_.error(error);
70
+ return {
71
+ success: false,
72
+ error: "Authentication failed"
73
+ };
74
+ }
75
+ }
76
+ async register(data, authIdentityProviderService) {
77
+ if (!(0, utils_1.isDefined)(data.body?.identifier)) {
78
+ return {
79
+ success: false,
80
+ error: "Identifier is required"
81
+ };
82
+ }
83
+ if (!(0, utils_1.isDefined)(data.body?.otp)) {
84
+ return {
85
+ success: false,
86
+ error: "OTP is required"
87
+ };
88
+ }
89
+ const otp = await this.cacheService_.get(`otp:pre-register:${data.body.identifier}`);
90
+ if (otp !== data.body.otp) {
91
+ return {
92
+ success: false,
93
+ error: "Invalid OTP"
94
+ };
95
+ }
96
+ let authIdentity;
97
+ try {
98
+ authIdentity = await authIdentityProviderService.retrieve({
99
+ entity_id: data.body.identifier,
100
+ });
101
+ }
102
+ catch (error) {
103
+ if (!(error instanceof utils_1.MedusaError))
104
+ return { success: false, error: JSON.stringify(error) };
105
+ if (error.type !== utils_1.MedusaError.Types.NOT_FOUND)
106
+ return { success: false, error: error.message };
107
+ // If the identity is not found, we create it
108
+ authIdentity = await authIdentityProviderService.create({
109
+ entity_id: data.body.identifier
110
+ });
111
+ }
112
+ if (!authIdentity) {
113
+ return {
114
+ success: false,
115
+ error: "Failed to create identity"
116
+ };
117
+ }
118
+ const REGISTER_TTL = 60; // seconds
119
+ // Mark this identifier as recently registered to allow direct one time authentication
120
+ await this.cacheService_.set(`${exports.RECENTLY_REGISTERED_KEY}:${data.body.identifier}:${otp}`, "true", REGISTER_TTL);
121
+ return {
122
+ success: true,
123
+ authIdentity
124
+ };
125
+ }
126
+ }
127
+ exports.OtpAuthProviderService = OtpAuthProviderService;
128
+ OtpAuthProviderService.identifier = "otp";
129
+ exports.default = OtpAuthProviderService;
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9vdHAvc2VydmljZXMvb3RwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUFrSTtBQU9ySCxRQUFBLGNBQWMsR0FBRyxlQUFlLENBQUE7QUFDN0Msc0ZBQXNGO0FBQ3pFLFFBQUEsdUJBQXVCLEdBQUcscUJBQXFCLENBQUE7QUFFNUQsTUFBYSxzQkFBdUIsU0FBUSxrQ0FBMEI7SUFNcEUsWUFBWSxTQUErQjtRQUN6QyxLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDLGVBQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUM3QyxJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUM1RCxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVksQ0FDaEIsSUFBeUIsRUFDekIsMkJBQXdEO1FBRXhELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU87Z0JBQ0wsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsS0FBSyxFQUFFLHdCQUF3QjthQUNoQyxDQUFBO1FBQ0gsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFLLENBQUMsVUFBVSxDQUFBO1FBRXhDLElBQUksQ0FBQztZQUNILHNFQUFzRTtZQUN0RSxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRywrQkFBdUIsSUFBSSxVQUFVLElBQUksSUFBSSxDQUFDLElBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO1lBRXZILElBQUksb0JBQW9CLEtBQUssTUFBTSxFQUFFLENBQUM7Z0JBQ3BDLGtFQUFrRTtnQkFDbEUsSUFBSSxDQUFDO29CQUNI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
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Configuration options for the OTP authentication plugin.
3
+ *
4
+ * @property {number} digits - The number of digits the OTP should have. Default is 6.
5
+ *
6
+ * @property {number} ttl - The time-to-live of the OTP in seconds. Default is 300 (5 minutes).
7
+ *
8
+ * @property {Object} accessorsPerActor - Maps actor types (e.g., 'customer', 'user') to their identifier accessors.
9
+ * This configuration tells the OTP system how to find and identify different types of actors in your system.
10
+ * Only used when `mode` is `secondary`, as the `main` mode will create a new auth identity regardless of the identifier.
11
+ *
12
+ * For example, if you want customers to authenticate using their phone number instead of email:
13
+ * ```
14
+ * {
15
+ * customer: {
16
+ * accessor: 'phone', // Will look up customers by their phone field
17
+ * entityIdAccessor: 'email' // Will look up for an AuthIdentity with the customer's email as the `entity_id`
18
+ * }
19
+ * }
20
+ * ```
21
+ *
22
+ * You can also use an array of accessors to look up an actor by multiple fields.
23
+ * For example, if you want to look up a customer by multiple fields:
24
+ * ```
25
+ * {
26
+ * customer: { accessor: ['phone', 'email'], entityIdAccessor: 'id' }
27
+ * }
28
+ * ```
29
+ *
30
+ * The `accessor` defines which field to use when looking up an actor by the provided identifier.
31
+ * For example, with `accessor: 'phone'`, the system will check `customer.phone` to find matching customers.
32
+ *
33
+ * The `entityIdAccessor` defines which field to use as the entity ID when looking up
34
+ * an AuthIdentity.
35
+ *
36
+ * When using the `emailpass` auth provider for example, the `entityIdAccessor` will be the `email` field.
37
+ * This is because the `emailpass` auth provider uses the `email` field when creating an auth identity.
38
+ *
39
+ * Default is: { customer: { accessor: 'email', entityIdAccessor: 'id' }, user: { accessor: 'email', entityIdAccessor: 'id' } }
40
+ */
41
+ export type OtpOptions = {
42
+ /** The number of digits the OTP should have. @default 6 */
43
+ digits: number;
44
+ /** The time to live of the OTP in seconds. @default 60 * 5 (5 minutes) */
45
+ ttl: number;
46
+ /**
47
+ * Maps actor types to their identifier accessors for authentication.
48
+ * This tells the system which fields to use when looking up actors and creating auth identities.
49
+ *
50
+ * Only used when `mode` is `secondary`, as the `main` mode will create a new auth identity
51
+ * regardless of the identifier value passed.
52
+ *
53
+ * @example
54
+ * // Allow customers to authenticate using phone numbers:
55
+ * {
56
+ * customer: {
57
+ * accessor: 'phone', // Will look up customers by their phone field
58
+ * entityIdAccessor: 'email' // Will look up for an AuthIdentity with the customer's email as the `entity_id`
59
+ * }
60
+ * }
61
+ *
62
+ * @default { customer: { accessor: 'email', entityIdAccessor: 'id' }, user: { accessor: 'email', entityIdAccessor: 'id' } }
63
+ */
64
+ accessorsPerActor?: {
65
+ [actorType: string]: {
66
+ /**
67
+ * The field name used to look up an actor by the provided identifier.
68
+ * For example, with `accessor: 'phone'`, the system will check `customer.phone` to find matching customers.
69
+ *
70
+ * @example
71
+ * accessor: 'phone' // Will use the `phone` column of the actor as the identifier
72
+ * accessor: ['phone', 'email'] // Will use the `phone` or `email` column of the actor as the identifier
73
+ */
74
+ accessor: string | string[];
75
+ /**
76
+ * The field name used to get the entity ID when looking up an AuthIdentity.
77
+ *
78
+ * @example
79
+ * entityIdAccessor: 'email' // Will use the `email` column of the actor as the entity ID in AuthIdentity
80
+ */
81
+ entityIdAccessor: string;
82
+ };
83
+ };
84
+ http?: {
85
+ /**
86
+ * Controls how errors are handled in HTTP responses when generating OTPs.
87
+ *
88
+ * @property {boolean} alwaysReturnSuccess - When true, always returns a success response regardless of errors
89
+ * to prevent data leakage. When false, actual errors will be returned in the response.
90
+ * @default true
91
+ *
92
+ * @property {boolean} throwOnError - When true, throws errors that occur during OTP generation.
93
+ * When false, errors are caught and handled according to alwaysReturnSuccess.
94
+ * @default false
95
+ */
96
+ alwaysReturnSuccess?: boolean;
97
+ /**
98
+ * When true, logs a warning when an error occurs during OTP generation.
99
+ * @default true
100
+ */
101
+ warnOnError?: boolean;
102
+ };
103
+ };
104
+ export declare enum Events {
105
+ OTP_GENERATED = "otp.generated",
106
+ PRE_REGISTER_OTP_GENERATED = "pre-register.otp.generated"
107
+ }
108
+ export type OtpGeneratedEvent = {
109
+ identifier: string;
110
+ otp: string;
111
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Events = void 0;
4
+ var Events;
5
+ (function (Events) {
6
+ Events["OTP_GENERATED"] = "otp.generated";
7
+ Events["PRE_REGISTER_OTP_GENERATED"] = "pre-register.otp.generated";
8
+ })(Events || (exports.Events = Events = {}));
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBMkdBLElBQVksTUFHWDtBQUhELFdBQVksTUFBTTtJQUNoQix5Q0FBK0IsQ0FBQTtJQUMvQixtRUFBeUQsQ0FBQTtBQUMzRCxDQUFDLEVBSFcsTUFBTSxzQkFBTixNQUFNLFFBR2pCIn0=
@@ -0,0 +1,20 @@
1
+ import { type ConfigModule } from "@medusajs/framework";
2
+ /**
3
+ * Get the options for the OTP plugin
4
+ * @param configModule The config module
5
+ * @returns The options for the OTP plugin based on the default options and the options from the plugin
6
+ */
7
+ export default function getPluginOptions(configModule: ConfigModule): {
8
+ accessorsPerActor: {
9
+ [x: string]: {
10
+ accessor: string | string[];
11
+ entityIdAccessor: string;
12
+ };
13
+ };
14
+ http: {
15
+ alwaysReturnSuccess?: boolean;
16
+ warnOnError?: boolean;
17
+ };
18
+ digits: number;
19
+ ttl: number;
20
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getPluginOptions;
7
+ const otp_1 = __importDefault(require("./otp"));
8
+ /**
9
+ * Get the options for the OTP plugin
10
+ * @param configModule The config module
11
+ * @returns The options for the OTP plugin based on the default options and the options from the plugin
12
+ */
13
+ function getPluginOptions(configModule) {
14
+ const isPluginWithOptions = (plugin) => {
15
+ return typeof plugin === 'object' && "resolve" in plugin && "options" in plugin;
16
+ };
17
+ const pluginOptions = configModule.plugins.filter(isPluginWithOptions).find((plugin) => plugin.resolve.includes('@perseidesjs/auth-otp'))?.options;
18
+ return {
19
+ ...otp_1.default.DEFAULT_OPTIONS,
20
+ ...pluginOptions,
21
+ accessorsPerActor: {
22
+ ...otp_1.default.DEFAULT_OPTIONS.accessorsPerActor,
23
+ ...pluginOptions?.accessorsPerActor
24
+ },
25
+ http: {
26
+ ...otp_1.default.DEFAULT_OPTIONS.http,
27
+ ...pluginOptions?.http
28
+ }
29
+ };
30
+ }
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXBsdWdpbi1vcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL2dldC1wbHVnaW4tb3B0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVNBLG1DQW1CQztBQTFCRCxnREFBNkI7QUFFN0I7Ozs7R0FJRztBQUNILFNBQXdCLGdCQUFnQixDQUFDLFlBQTBCO0lBQ2pFLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxNQUFXLEVBQW1FLEVBQUU7UUFDM0csT0FBTyxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksU0FBUyxJQUFJLE1BQU0sSUFBSSxTQUFTLElBQUksTUFBTSxDQUFBO0lBQ2pGLENBQUMsQ0FBQTtJQUVELE1BQU0sYUFBYSxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEVBQUUsT0FBaUMsQ0FBQTtJQUU1SyxPQUFPO1FBQ0wsR0FBRyxhQUFRLENBQUMsZUFBZTtRQUMzQixHQUFHLGFBQWE7UUFDaEIsaUJBQWlCLEVBQUU7WUFDakIsR0FBRyxhQUFRLENBQUMsZUFBZSxDQUFDLGlCQUFpQjtZQUM3QyxHQUFHLGFBQWEsRUFBRSxpQkFBaUI7U0FDcEM7UUFDRCxJQUFJLEVBQUU7WUFDSixHQUFHLGFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSTtZQUNoQyxHQUFHLGFBQWEsRUFBRSxJQUFJO1NBQ3ZCO0tBQ0YsQ0FBQTtBQUNILENBQUMifQ==
@@ -0,0 +1,14 @@
1
+ import { OtpOptions } from '../types';
2
+ /**
3
+ * Static utility class for OTP operations
4
+ */
5
+ export declare class OtpUtils {
6
+ static DEFAULT_OPTIONS: OtpOptions;
7
+ /**
8
+ * Generate a random numeric OTP of specified length
9
+ * @param digits The number of digits the OTP should have
10
+ * @returns {string} The OTP
11
+ */
12
+ static generateRandomOTP(digits: number): string;
13
+ }
14
+ export default OtpUtils;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OtpUtils = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ /**
6
+ * Static utility class for OTP operations
7
+ */
8
+ class OtpUtils {
9
+ /**
10
+ * Generate a random numeric OTP of specified length
11
+ * @param digits The number of digits the OTP should have
12
+ * @returns {string} The OTP
13
+ */
14
+ static generateRandomOTP(digits) {
15
+ const timeStep = 30;
16
+ const secret = (0, node_crypto_1.randomBytes)(32).toString('hex');
17
+ const time = Math.floor(Date.now() / 1000 / timeStep);
18
+ const hmac = (0, node_crypto_1.createHmac)('sha1', Buffer.from(secret, 'hex'));
19
+ hmac.update(Buffer.from(time.toString(), 'utf-8'));
20
+ const hmacResult = hmac.digest();
21
+ const offset = hmacResult[hmacResult.length - 1] & 0xf;
22
+ const binary = ((hmacResult[offset] & 0x7f) << 24) |
23
+ ((hmacResult[offset + 1] & 0xff) << 16) |
24
+ ((hmacResult[offset + 2] & 0xff) << 8) |
25
+ (hmacResult[offset + 3] & 0xff);
26
+ return (binary % Math.pow(10, digits)).toString().padStart(digits, '0');
27
+ }
28
+ }
29
+ exports.OtpUtils = OtpUtils;
30
+ OtpUtils.DEFAULT_OPTIONS = {
31
+ digits: 6, // 6 digits
32
+ ttl: 60 * 5, // 5 minutes
33
+ accessorsPerActor: {
34
+ customer: { accessor: 'email', entityIdAccessor: 'email' },
35
+ user: { accessor: 'email', entityIdAccessor: 'email' }
36
+ },
37
+ http: {
38
+ alwaysReturnSuccess: true, // Always return success to prevent data leakage
39
+ warnOnError: true // Warn when an error occurs during OTP generation
40
+ }
41
+ };
42
+ exports.default = OtpUtils;
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL290cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBcUQ7QUFHckQ7O0dBRUc7QUFDSCxNQUFhLFFBQVE7SUFjbkI7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxNQUFjO1FBQ3JDLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQTtRQUNuQixNQUFNLE1BQU0sR0FBRyxJQUFBLHlCQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzlDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQTtRQUVyRCxNQUFNLElBQUksR0FBRyxJQUFBLHdCQUFVLEVBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUE7UUFDM0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO1FBQ2xELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUVoQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUE7UUFDdEQsTUFBTSxNQUFNLEdBQ1YsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3ZDLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN0QyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUE7UUFFakMsT0FBTyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDekUsQ0FBQzs7QUFwQ0gsNEJBcUNDO0FBcENRLHdCQUFlLEdBQWU7SUFDbkMsTUFBTSxFQUFFLENBQUMsRUFBRSxXQUFXO0lBQ3RCLEdBQUcsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLFlBQVk7SUFDekIsaUJBQWlCLEVBQUU7UUFDakIsUUFBUSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUU7UUFDMUQsSUFBSSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUU7S0FDdkQ7SUFDRCxJQUFJLEVBQUU7UUFDSixtQkFBbUIsRUFBRSxJQUFJLEVBQUUsZ0RBQWdEO1FBQzNFLFdBQVcsRUFBRSxJQUFJLENBQUMsa0RBQWtEO0tBQ3JFO0NBQ0YsQ0FBQTtBQTJCSCxrQkFBZSxRQUFRLENBQUEifQ==
@@ -0,0 +1,16 @@
1
+ import { OtpOptions } from "../types";
2
+ /**
3
+ * Generates an OTP for a given identifier and actor type.
4
+ *
5
+ * @param input - The input for the workflow.
6
+ * @param input.identifier - The identifier of the actor to generate the OTP for.
7
+ * @param input.actorType - The type of actor to generate the OTP for.
8
+ * @param input.accessorsPerActor - The accessors per actor to use for the workflow.
9
+ *
10
+ */
11
+ declare const generateOtpWorkflow: import("@medusajs/framework/workflows-sdk").ReturnWorkflow<{
12
+ identifier: string;
13
+ actorType: string;
14
+ accessorsPerActor: Required<OtpOptions>["accessorsPerActor"][string];
15
+ }, "OK", []>;
16
+ export default generateOtpWorkflow;