UNPKG

4.72 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.LocalStrategy = void 0;
7/* eslint-disable @typescript-eslint/no-unused-vars */
8const bcryptjs_1 = __importDefault(require("bcryptjs"));
9const get_1 = __importDefault(require("lodash/get"));
10const errors_1 = require("@feathersjs/errors");
11const authentication_1 = require("@feathersjs/authentication");
12const commons_1 = require("@feathersjs/commons");
13const debug = (0, commons_1.createDebug)('@feathersjs/authentication-local/strategy');
14class LocalStrategy extends authentication_1.AuthenticationBaseStrategy {
15 verifyConfiguration() {
16 const config = this.configuration;
17 ['usernameField', 'passwordField'].forEach((prop) => {
18 if (typeof config[prop] !== 'string') {
19 throw new Error(`'${this.name}' authentication strategy requires a '${prop}' setting`);
20 }
21 });
22 }
23 get configuration() {
24 const authConfig = this.authentication.configuration;
25 const config = super.configuration || {};
26 return {
27 hashSize: 10,
28 service: authConfig.service,
29 entity: authConfig.entity,
30 entityId: authConfig.entityId,
31 errorMessage: 'Invalid login',
32 entityPasswordField: config.passwordField,
33 entityUsernameField: config.usernameField,
34 ...config
35 };
36 }
37 async getEntityQuery(query, _params) {
38 return {
39 $limit: 1,
40 ...query
41 };
42 }
43 async findEntity(username, params) {
44 const { entityUsernameField, errorMessage } = this.configuration;
45 if (!username) {
46 // don't query for users without any condition set.
47 throw new errors_1.NotAuthenticated(errorMessage);
48 }
49 const query = await this.getEntityQuery({
50 [entityUsernameField]: username
51 }, params);
52 const findParams = Object.assign({}, params, { query });
53 const entityService = this.entityService;
54 debug('Finding entity with query', params.query);
55 const result = await entityService.find(findParams);
56 const list = Array.isArray(result) ? result : result.data;
57 if (!Array.isArray(list) || list.length === 0) {
58 debug('No entity found');
59 throw new errors_1.NotAuthenticated(errorMessage);
60 }
61 const [entity] = list;
62 return entity;
63 }
64 async getEntity(result, params) {
65 const entityService = this.entityService;
66 const { entityId = entityService.id, entity } = this.configuration;
67 if (!entityId || result[entityId] === undefined) {
68 throw new errors_1.NotAuthenticated('Could not get local entity');
69 }
70 if (!params.provider) {
71 return result;
72 }
73 return entityService.get(result[entityId], {
74 ...params,
75 [entity]: result
76 });
77 }
78 async comparePassword(entity, password) {
79 const { entityPasswordField, errorMessage } = this.configuration;
80 // find password in entity, this allows for dot notation
81 const hash = (0, get_1.default)(entity, entityPasswordField);
82 if (!hash) {
83 debug(`Record is missing the '${entityPasswordField}' password field`);
84 throw new errors_1.NotAuthenticated(errorMessage);
85 }
86 debug('Verifying password');
87 const result = await bcryptjs_1.default.compare(password, hash);
88 if (result) {
89 return entity;
90 }
91 throw new errors_1.NotAuthenticated(errorMessage);
92 }
93 async hashPassword(password, _params) {
94 return bcryptjs_1.default.hash(password, this.configuration.hashSize);
95 }
96 async authenticate(data, params) {
97 const { passwordField, usernameField, entity, errorMessage } = this.configuration;
98 const username = (0, get_1.default)(data, usernameField);
99 const password = (0, get_1.default)(data, passwordField);
100 if (!password) {
101 // exit early if there is no password
102 throw new errors_1.NotAuthenticated(errorMessage);
103 }
104 const { provider, ...paramsWithoutProvider } = params;
105 const result = await this.findEntity(username, paramsWithoutProvider);
106 await this.comparePassword(result, password);
107 return {
108 authentication: { strategy: this.name },
109 [entity]: await this.getEntity(result, params)
110 };
111 }
112}
113exports.LocalStrategy = LocalStrategy;
114//# sourceMappingURL=strategy.js.map
\No newline at end of file