UNPKG

@medusajs/auth-emailpass

Version:

Email and password credential authentication provider for Medusa

170 lines • 6.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EmailPassAuthService = void 0; const utils_1 = require("@medusajs/framework/utils"); const scrypt_kdf_1 = __importDefault(require("scrypt-kdf")); const utils_2 = require("@medusajs/utils"); class EmailPassAuthService extends utils_1.AbstractAuthModuleProvider { constructor({ logger }, options) { // @ts-ignore super(...arguments); this.config_ = options; this.logger_ = logger; } async hashPassword(password) { const hashConfig = this.config_.hashConfig ?? { logN: 15, r: 8, p: 1 }; const passwordHash = await scrypt_kdf_1.default.kdf(password, hashConfig); return passwordHash.toString("base64"); } async update(data, authIdentityService) { const { password, entity_id } = data ?? {}; if (!entity_id) { return { success: false, error: `Cannot update ${this.provider} provider identity without entity_id`, }; } if (!password || !(0, utils_1.isString)(password)) { return { success: true }; } let authIdentity; try { const passwordHash = await this.hashPassword(password); authIdentity = await authIdentityService.update(entity_id, { provider_metadata: { password: passwordHash, }, }); } catch (error) { return { success: false, error: error.message }; } return { success: true, authIdentity, }; } async authenticate(userData, authIdentityService) { const { email, password } = userData.body ?? {}; if (!password || !(0, utils_1.isString)(password)) { return { success: false, error: "Password should be a string", }; } if (!email || !(0, utils_1.isString)(email)) { return { success: false, error: "Email should be a string", }; } let authIdentity; try { authIdentity = await authIdentityService.retrieve({ entity_id: email, }); } catch (error) { if (error.type === utils_1.MedusaError.Types.NOT_FOUND) { return { success: false, error: "Invalid email or password", }; } return { success: false, error: error.message }; } const providerIdentity = authIdentity.provider_identities?.find((pi) => pi.provider === this.provider); const passwordHash = providerIdentity.provider_metadata?.password; if ((0, utils_1.isString)(passwordHash)) { const buf = Buffer.from(passwordHash, "base64"); const success = await scrypt_kdf_1.default.verify(buf, password); if (success) { const copy = JSON.parse(JSON.stringify(authIdentity)); const providerIdentity = copy.provider_identities?.find((pi) => pi.provider === this.provider); delete providerIdentity.provider_metadata?.password; return { success, authIdentity: copy, }; } } return { success: false, error: "Invalid email or password", }; } async register(userData, authIdentityService) { const { email, password } = userData.body ?? {}; if (!password || !(0, utils_1.isString)(password)) { return { success: false, error: "Password should be a string", }; } if (!email || !(0, utils_1.isString)(email)) { return { success: false, error: "Email should be a string", }; } try { const identity = await authIdentityService.retrieve({ entity_id: email, }); // If app_metadata is not defined or empty, it means no actor was assigned to the auth_identity yet (still "claimable") if (!(0, utils_2.isPresent)(identity.app_metadata)) { const updatedAuthIdentity = await this.upsertAuthIdentity('update', { email, password, authIdentityService, }); return { success: true, authIdentity: updatedAuthIdentity, }; } return { success: false, error: "Identity with email already exists", }; } catch (error) { if (error.type === utils_1.MedusaError.Types.NOT_FOUND) { const createdAuthIdentity = await this.upsertAuthIdentity('create', { email, password, authIdentityService, }); return { success: true, authIdentity: createdAuthIdentity, }; } return { success: false, error: error.message }; } } async upsertAuthIdentity(type, { email, password, authIdentityService }) { const passwordHash = await this.hashPassword(password); const authIdentity = type === 'create' ? await authIdentityService.create({ entity_id: email, provider_metadata: { password: passwordHash, }, }) : await authIdentityService.update(email, { provider_metadata: { password: passwordHash, }, }); const copy = JSON.parse(JSON.stringify(authIdentity)); const providerIdentity = copy.provider_identities?.find((pi) => pi.provider === this.provider); delete providerIdentity.provider_metadata?.password; return copy; } } exports.EmailPassAuthService = EmailPassAuthService; EmailPassAuthService.identifier = "emailpass"; EmailPassAuthService.DISPLAY_NAME = "Email/Password Authentication"; //# sourceMappingURL=emailpass.js.map