@feathersjs/authentication-local 5.0.0-pre.22 → 5.0.0-pre.23
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.
- package/CHANGELOG.md +8 -0
- package/lib/hooks/hash-password.js +3 -2
- package/lib/hooks/hash-password.js.map +1 -1
- package/lib/hooks/protect.js +1 -2
- package/lib/hooks/protect.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/strategy.js +5 -3
- package/lib/strategy.js.map +1 -1
- package/package.json +10 -10
- package/src/hooks/hash-password.ts +28 -27
- package/src/hooks/protect.ts +14 -15
- package/src/index.ts +4 -4
- package/src/strategy.ts +67 -64
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [5.0.0-pre.23](https://github.com/feathersjs/feathers/compare/v5.0.0-pre.22...v5.0.0-pre.23) (2022-06-06)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @feathersjs/authentication-local
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# [5.0.0-pre.22](https://github.com/feathersjs/feathers/compare/v5.0.0-pre.21...v5.0.0-pre.22) (2022-05-24)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @feathersjs/authentication-local
|
|
@@ -34,8 +34,9 @@ function hashPassword(field, options = {}) {
|
|
|
34
34
|
const hashedPassword = await localStrategy.hashPassword(password, params);
|
|
35
35
|
return (0, set_1.default)((0, cloneDeep_1.default)(data), field, hashedPassword);
|
|
36
36
|
};
|
|
37
|
-
context.data = Array.isArray(data)
|
|
38
|
-
await
|
|
37
|
+
context.data = Array.isArray(data)
|
|
38
|
+
? await Promise.all(data.map(addHashedPassword))
|
|
39
|
+
: await addHashedPassword(data);
|
|
39
40
|
}
|
|
40
41
|
if (typeof next === 'function') {
|
|
41
42
|
return next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash-password.js","sourceRoot":"","sources":["../../src/hooks/hash-password.ts"],"names":[],"mappings":";;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"hash-password.js","sourceRoot":"","sources":["../../src/hooks/hash-password.ts"],"names":[],"mappings":";;;;;AAAA,qDAA4B;AAC5B,qDAA4B;AAC5B,iEAAwC;AACxC,+CAA+C;AAC/C,iDAAiD;AAIjD,MAAM,KAAK,GAAG,IAAA,qBAAW,EAAC,sDAAsD,CAAC,CAAA;AAOjF,SAAwB,YAAY,CAAC,KAAa,EAAE,UAA+B,EAAE;IACnF,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;KACtE;IAED,OAAO,KAAK,EAAE,OAAoB,EAAE,IAAmB,EAAE,EAAE;QACzD,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;QAErC,IAAI,IAAI,KAAK,SAAS,EAAE;YACtB,MAAM,WAAW,GAAG,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;YACrE,MAAM,EAAE,QAAQ,GAAG,OAAO,EAAE,GAAG,OAAO,CAAA;YAEtC,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,CAAC,aAAa,KAAK,UAAU,EAAE;gBACnE,MAAM,IAAI,mBAAU,CAAC,2DAA2D,CAAC,CAAA;aAClF;YAED,MAAM,CAAC,aAAa,CAAC,GAAG,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAoB,CAAA;YAE9E,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,CAAC,YAAY,KAAK,UAAU,EAAE;gBACtE,MAAM,IAAI,mBAAU,CAAC,mBAAmB,QAAQ,6BAA6B,CAAC,CAAA;aAC/E;YAED,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAS,EAAE,EAAE;gBAC5C,MAAM,QAAQ,GAAG,IAAA,aAAG,EAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAEjC,IAAI,QAAQ,KAAK,SAAS,EAAE;oBAC1B,KAAK,CAAC,aAAa,KAAK,qCAAqC,CAAC,CAAA;oBAC9D,OAAO,IAAI,CAAA;iBACZ;gBAED,MAAM,cAAc,GAAW,MAAM,aAAa,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAEjF,OAAO,IAAA,aAAG,EAAC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;YACpD,CAAC,CAAA;YAED,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBAChC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAChD,CAAC,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAA;SAClC;QAED,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE;YAC9B,OAAO,IAAI,EAAE,CAAA;SACd;IACH,CAAC,CAAA;AACH,CAAC;AA5CD,+BA4CC"}
|
package/lib/hooks/protect.js
CHANGED
|
@@ -7,8 +7,7 @@ const omit_1 = __importDefault(require("lodash/omit"));
|
|
|
7
7
|
exports.default = (...fields) => {
|
|
8
8
|
const o = (current) => {
|
|
9
9
|
if (typeof current === 'object' && !Array.isArray(current)) {
|
|
10
|
-
const data = typeof current.toJSON === 'function'
|
|
11
|
-
? current.toJSON() : current;
|
|
10
|
+
const data = typeof current.toJSON === 'function' ? current.toJSON() : current;
|
|
12
11
|
return (0, omit_1.default)(data, fields);
|
|
13
12
|
}
|
|
14
13
|
return current;
|
package/lib/hooks/protect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protect.js","sourceRoot":"","sources":["../../src/hooks/protect.ts"],"names":[],"mappings":";;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"protect.js","sourceRoot":"","sources":["../../src/hooks/protect.ts"],"names":[],"mappings":";;;;;AAAA,uDAA8B;AAG9B,kBAAe,CAAC,GAAG,MAAgB,EAAE,EAAE;IACrC,MAAM,CAAC,GAAG,CAAC,OAAY,EAAE,EAAE;QACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;YAC1D,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;YAE9E,OAAO,IAAA,cAAI,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;SAC1B;QAED,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA;IAED,OAAO,KAAK,EAAE,OAAoB,EAAE,IAAmB,EAAE,EAAE;QACzD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE;YAC9B,MAAM,IAAI,EAAE,CAAA;SACb;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAA;QAEjD,IAAI,MAAM,EAAE;YACV,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBACzB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;aACjC;iBAAM,IAAI,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;gBACnD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE;oBAC3C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;iBACzB,CAAC,CAAA;aACH;iBAAM;gBACL,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,CAAA;aAC7B;YAED,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE;gBAC7C,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAA;aAClC;SACF;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,0EAAgD;AAChD,8DAAqC;AAExB,QAAA,KAAK,GAAG,EAAE,YAAY,EAAZ,uBAAY,EAAE,OAAO,EAAP,iBAAO,EAAE,CAAA;AAC9C,uCAA0C;AAAjC,yGAAA,aAAa,OAAA"}
|
package/lib/strategy.js
CHANGED
|
@@ -15,7 +15,7 @@ const debug = (0, commons_1.createDebug)('@feathersjs/authentication-local/strat
|
|
|
15
15
|
class LocalStrategy extends authentication_1.AuthenticationBaseStrategy {
|
|
16
16
|
verifyConfiguration() {
|
|
17
17
|
const config = this.configuration;
|
|
18
|
-
['usernameField', 'passwordField'].forEach(prop => {
|
|
18
|
+
['usernameField', 'passwordField'].forEach((prop) => {
|
|
19
19
|
if (typeof config[prop] !== 'string') {
|
|
20
20
|
throw new Error(`'${this.name}' authentication strategy requires a '${prop}' setting`);
|
|
21
21
|
}
|
|
@@ -43,7 +43,8 @@ class LocalStrategy extends authentication_1.AuthenticationBaseStrategy {
|
|
|
43
43
|
}
|
|
44
44
|
async findEntity(username, params) {
|
|
45
45
|
const { entityUsernameField, errorMessage } = this.configuration;
|
|
46
|
-
if (!username) {
|
|
46
|
+
if (!username) {
|
|
47
|
+
// don't query for users without any condition set.
|
|
47
48
|
throw new errors_1.NotAuthenticated(errorMessage);
|
|
48
49
|
}
|
|
49
50
|
const query = await this.getEntityQuery({
|
|
@@ -97,7 +98,8 @@ class LocalStrategy extends authentication_1.AuthenticationBaseStrategy {
|
|
|
97
98
|
const { passwordField, usernameField, entity, errorMessage } = this.configuration;
|
|
98
99
|
const username = data[usernameField];
|
|
99
100
|
const password = data[passwordField];
|
|
100
|
-
if (!password) {
|
|
101
|
+
if (!password) {
|
|
102
|
+
// exit early if there is no password
|
|
101
103
|
throw new errors_1.NotAuthenticated(errorMessage);
|
|
102
104
|
}
|
|
103
105
|
const result = await this.findEntity(username, (0, omit_1.default)(params, 'provider'));
|
package/lib/strategy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAsD;AACtD,
|
|
1
|
+
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feathersjs/authentication-local",
|
|
3
3
|
"description": "Local authentication strategy for @feathers/authentication",
|
|
4
|
-
"version": "5.0.0-pre.
|
|
4
|
+
"version": "5.0.0-pre.23",
|
|
5
5
|
"homepage": "https://feathersjs.com",
|
|
6
6
|
"main": "lib/",
|
|
7
7
|
"types": "lib/",
|
|
@@ -52,23 +52,23 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@feathersjs/authentication": "^5.0.0-pre.
|
|
56
|
-
"@feathersjs/commons": "^5.0.0-pre.
|
|
57
|
-
"@feathersjs/errors": "^5.0.0-pre.
|
|
58
|
-
"@feathersjs/feathers": "^5.0.0-pre.
|
|
55
|
+
"@feathersjs/authentication": "^5.0.0-pre.23",
|
|
56
|
+
"@feathersjs/commons": "^5.0.0-pre.23",
|
|
57
|
+
"@feathersjs/errors": "^5.0.0-pre.23",
|
|
58
|
+
"@feathersjs/feathers": "^5.0.0-pre.23",
|
|
59
59
|
"bcryptjs": "^2.4.3",
|
|
60
60
|
"lodash": "^4.17.21"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@feathersjs/memory": "^5.0.0-pre.
|
|
63
|
+
"@feathersjs/memory": "^5.0.0-pre.23",
|
|
64
64
|
"@types/bcryptjs": "^2.4.2",
|
|
65
65
|
"@types/lodash": "^4.14.182",
|
|
66
66
|
"@types/mocha": "^9.1.1",
|
|
67
|
-
"@types/node": "^17.0.
|
|
67
|
+
"@types/node": "^17.0.40",
|
|
68
68
|
"mocha": "^10.0.0",
|
|
69
69
|
"shx": "^0.3.4",
|
|
70
|
-
"ts-node": "^10.
|
|
71
|
-
"typescript": "^4.
|
|
70
|
+
"ts-node": "^10.8.1",
|
|
71
|
+
"typescript": "^4.7.3"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "a60910bd730b88053ca6648337095f1ca1e3b39f"
|
|
74
74
|
}
|
|
@@ -1,59 +1,60 @@
|
|
|
1
|
-
import get from 'lodash/get'
|
|
2
|
-
import set from 'lodash/set'
|
|
3
|
-
import cloneDeep from 'lodash/cloneDeep'
|
|
4
|
-
import { BadRequest } from '@feathersjs/errors'
|
|
5
|
-
import { createDebug } from '@feathersjs/commons'
|
|
6
|
-
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
7
|
-
import { LocalStrategy } from '../strategy'
|
|
1
|
+
import get from 'lodash/get'
|
|
2
|
+
import set from 'lodash/set'
|
|
3
|
+
import cloneDeep from 'lodash/cloneDeep'
|
|
4
|
+
import { BadRequest } from '@feathersjs/errors'
|
|
5
|
+
import { createDebug } from '@feathersjs/commons'
|
|
6
|
+
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
7
|
+
import { LocalStrategy } from '../strategy'
|
|
8
8
|
|
|
9
|
-
const debug = createDebug('@feathersjs/authentication-local/hooks/hash-password')
|
|
9
|
+
const debug = createDebug('@feathersjs/authentication-local/hooks/hash-password')
|
|
10
10
|
|
|
11
11
|
export interface HashPasswordOptions {
|
|
12
|
-
authentication?: string
|
|
13
|
-
strategy?: string
|
|
12
|
+
authentication?: string
|
|
13
|
+
strategy?: string
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export default function hashPassword
|
|
16
|
+
export default function hashPassword(field: string, options: HashPasswordOptions = {}) {
|
|
17
17
|
if (!field) {
|
|
18
|
-
throw new Error('The hashPassword hook requires a field name option')
|
|
18
|
+
throw new Error('The hashPassword hook requires a field name option')
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
return async (context: HookContext, next?: NextFunction) => {
|
|
22
|
-
const { app, data, params } = context
|
|
22
|
+
const { app, data, params } = context
|
|
23
23
|
|
|
24
24
|
if (data !== undefined) {
|
|
25
|
-
const authService = app.defaultAuthentication(options.authentication)
|
|
26
|
-
const { strategy = 'local' } = options
|
|
25
|
+
const authService = app.defaultAuthentication(options.authentication)
|
|
26
|
+
const { strategy = 'local' } = options
|
|
27
27
|
|
|
28
28
|
if (!authService || typeof authService.getStrategies !== 'function') {
|
|
29
|
-
throw new BadRequest('Could not find an authentication service to hash password')
|
|
29
|
+
throw new BadRequest('Could not find an authentication service to hash password')
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const [
|
|
32
|
+
const [localStrategy] = authService.getStrategies(strategy) as LocalStrategy[]
|
|
33
33
|
|
|
34
34
|
if (!localStrategy || typeof localStrategy.hashPassword !== 'function') {
|
|
35
|
-
throw new BadRequest(`Could not find '${strategy}' strategy to hash password`)
|
|
35
|
+
throw new BadRequest(`Could not find '${strategy}' strategy to hash password`)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const addHashedPassword = async (data: any) => {
|
|
39
|
-
const password = get(data, field)
|
|
39
|
+
const password = get(data, field)
|
|
40
40
|
|
|
41
41
|
if (password === undefined) {
|
|
42
|
-
debug(`hook.data.${field} is undefined, not hashing password`)
|
|
43
|
-
return data
|
|
42
|
+
debug(`hook.data.${field} is undefined, not hashing password`)
|
|
43
|
+
return data
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const hashedPassword: string = await localStrategy.hashPassword(password, params)
|
|
46
|
+
const hashedPassword: string = await localStrategy.hashPassword(password, params)
|
|
47
47
|
|
|
48
|
-
return set(cloneDeep(data), field, hashedPassword)
|
|
48
|
+
return set(cloneDeep(data), field, hashedPassword)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
context.data = Array.isArray(data)
|
|
52
|
-
await
|
|
51
|
+
context.data = Array.isArray(data)
|
|
52
|
+
? await Promise.all(data.map(addHashedPassword))
|
|
53
|
+
: await addHashedPassword(data)
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
if (typeof next === 'function') {
|
|
56
|
-
return next()
|
|
57
|
+
return next()
|
|
57
58
|
}
|
|
58
|
-
}
|
|
59
|
+
}
|
|
59
60
|
}
|
package/src/hooks/protect.ts
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
|
-
import omit from 'lodash/omit'
|
|
2
|
-
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
1
|
+
import omit from 'lodash/omit'
|
|
2
|
+
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
3
3
|
|
|
4
4
|
export default (...fields: string[]) => {
|
|
5
5
|
const o = (current: any) => {
|
|
6
6
|
if (typeof current === 'object' && !Array.isArray(current)) {
|
|
7
|
-
const data = typeof current.toJSON === 'function'
|
|
8
|
-
? current.toJSON() : current;
|
|
7
|
+
const data = typeof current.toJSON === 'function' ? current.toJSON() : current
|
|
9
8
|
|
|
10
|
-
return omit(data, fields)
|
|
9
|
+
return omit(data, fields)
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
return current
|
|
14
|
-
}
|
|
12
|
+
return current
|
|
13
|
+
}
|
|
15
14
|
|
|
16
15
|
return async (context: HookContext, next?: NextFunction) => {
|
|
17
16
|
if (typeof next === 'function') {
|
|
18
|
-
await next()
|
|
17
|
+
await next()
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
const result = context.dispatch || context.result
|
|
20
|
+
const result = context.dispatch || context.result
|
|
22
21
|
|
|
23
22
|
if (result) {
|
|
24
23
|
if (Array.isArray(result)) {
|
|
25
|
-
context.dispatch = result.map(o)
|
|
24
|
+
context.dispatch = result.map(o)
|
|
26
25
|
} else if (result.data && context.method === 'find') {
|
|
27
26
|
context.dispatch = Object.assign({}, result, {
|
|
28
27
|
data: result.data.map(o)
|
|
29
|
-
})
|
|
28
|
+
})
|
|
30
29
|
} else {
|
|
31
|
-
context.dispatch = o(result)
|
|
30
|
+
context.dispatch = o(result)
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
if (context.params && context.params.provider) {
|
|
35
|
-
context.result = context.dispatch
|
|
34
|
+
context.result = context.dispatch
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import hashPassword from './hooks/hash-password'
|
|
2
|
-
import protect from './hooks/protect'
|
|
1
|
+
import hashPassword from './hooks/hash-password'
|
|
2
|
+
import protect from './hooks/protect'
|
|
3
3
|
|
|
4
|
-
export const hooks = { hashPassword, protect }
|
|
5
|
-
export { LocalStrategy } from './strategy'
|
|
4
|
+
export const hooks = { hashPassword, protect }
|
|
5
|
+
export { LocalStrategy } from './strategy'
|
package/src/strategy.ts
CHANGED
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import bcrypt from 'bcryptjs'
|
|
3
|
-
import get from 'lodash/get'
|
|
4
|
-
import omit from 'lodash/omit'
|
|
5
|
-
import { NotAuthenticated } from '@feathersjs/errors'
|
|
6
|
-
import { Query, Params } from '@feathersjs/feathers'
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const debug = createDebug('@feathersjs/authentication-local/strategy');
|
|
2
|
+
import bcrypt from 'bcryptjs'
|
|
3
|
+
import get from 'lodash/get'
|
|
4
|
+
import omit from 'lodash/omit'
|
|
5
|
+
import { NotAuthenticated } from '@feathersjs/errors'
|
|
6
|
+
import { Query, Params } from '@feathersjs/feathers'
|
|
7
|
+
import { AuthenticationRequest, AuthenticationBaseStrategy } from '@feathersjs/authentication'
|
|
8
|
+
import { createDebug } from '@feathersjs/commons'
|
|
9
|
+
|
|
10
|
+
const debug = createDebug('@feathersjs/authentication-local/strategy')
|
|
13
11
|
|
|
14
12
|
export class LocalStrategy extends AuthenticationBaseStrategy {
|
|
15
|
-
verifyConfiguration
|
|
16
|
-
const config = this.configuration
|
|
13
|
+
verifyConfiguration() {
|
|
14
|
+
const config = this.configuration
|
|
17
15
|
|
|
18
|
-
[
|
|
16
|
+
;['usernameField', 'passwordField'].forEach((prop) => {
|
|
19
17
|
if (typeof config[prop] !== 'string') {
|
|
20
|
-
throw new Error(`'${this.name}' authentication strategy requires a '${prop}' setting`)
|
|
18
|
+
throw new Error(`'${this.name}' authentication strategy requires a '${prop}' setting`)
|
|
21
19
|
}
|
|
22
|
-
})
|
|
20
|
+
})
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
get configuration
|
|
26
|
-
const authConfig = this.authentication.configuration
|
|
27
|
-
const config = super.configuration || {}
|
|
23
|
+
get configuration() {
|
|
24
|
+
const authConfig = this.authentication.configuration
|
|
25
|
+
const config = super.configuration || {}
|
|
28
26
|
|
|
29
27
|
return {
|
|
30
28
|
hashSize: 10,
|
|
@@ -35,105 +33,110 @@ export class LocalStrategy extends AuthenticationBaseStrategy {
|
|
|
35
33
|
entityPasswordField: config.passwordField,
|
|
36
34
|
entityUsernameField: config.usernameField,
|
|
37
35
|
...config
|
|
38
|
-
}
|
|
36
|
+
}
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
async getEntityQuery
|
|
39
|
+
async getEntityQuery(query: Query, _params: Params) {
|
|
42
40
|
return {
|
|
43
41
|
$limit: 1,
|
|
44
42
|
...query
|
|
45
|
-
}
|
|
43
|
+
}
|
|
46
44
|
}
|
|
47
45
|
|
|
48
|
-
async findEntity
|
|
49
|
-
const { entityUsernameField, errorMessage } = this.configuration
|
|
50
|
-
if (!username) {
|
|
51
|
-
|
|
46
|
+
async findEntity(username: string, params: Params) {
|
|
47
|
+
const { entityUsernameField, errorMessage } = this.configuration
|
|
48
|
+
if (!username) {
|
|
49
|
+
// don't query for users without any condition set.
|
|
50
|
+
throw new NotAuthenticated(errorMessage)
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
const query = await this.getEntityQuery(
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const query = await this.getEntityQuery(
|
|
54
|
+
{
|
|
55
|
+
[entityUsernameField]: username
|
|
56
|
+
},
|
|
57
|
+
params
|
|
58
|
+
)
|
|
57
59
|
|
|
58
|
-
const findParams = Object.assign({}, params, { query })
|
|
59
|
-
const entityService = this.entityService
|
|
60
|
+
const findParams = Object.assign({}, params, { query })
|
|
61
|
+
const entityService = this.entityService
|
|
60
62
|
|
|
61
|
-
debug('Finding entity with query', params.query)
|
|
63
|
+
debug('Finding entity with query', params.query)
|
|
62
64
|
|
|
63
|
-
const result = await entityService.find(findParams)
|
|
64
|
-
const list = Array.isArray(result) ? result : result.data
|
|
65
|
+
const result = await entityService.find(findParams)
|
|
66
|
+
const list = Array.isArray(result) ? result : result.data
|
|
65
67
|
|
|
66
68
|
if (!Array.isArray(list) || list.length === 0) {
|
|
67
|
-
debug('No entity found')
|
|
69
|
+
debug('No entity found')
|
|
68
70
|
|
|
69
|
-
throw new NotAuthenticated(errorMessage)
|
|
71
|
+
throw new NotAuthenticated(errorMessage)
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
const [
|
|
74
|
+
const [entity] = list
|
|
73
75
|
|
|
74
|
-
return entity
|
|
76
|
+
return entity
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
async getEntity
|
|
78
|
-
const entityService = this.entityService
|
|
79
|
-
const { entityId = (entityService as any).id, entity } = this.configuration
|
|
79
|
+
async getEntity(result: any, params: Params) {
|
|
80
|
+
const entityService = this.entityService
|
|
81
|
+
const { entityId = (entityService as any).id, entity } = this.configuration
|
|
80
82
|
|
|
81
83
|
if (!entityId || result[entityId] === undefined) {
|
|
82
|
-
throw new NotAuthenticated('Could not get local entity')
|
|
84
|
+
throw new NotAuthenticated('Could not get local entity')
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
if (!params.provider) {
|
|
86
|
-
return result
|
|
88
|
+
return result
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
return entityService.get(result[entityId], {
|
|
90
92
|
...params,
|
|
91
93
|
[entity]: result
|
|
92
|
-
})
|
|
94
|
+
})
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
async comparePassword
|
|
96
|
-
const { entityPasswordField, errorMessage } = this.configuration
|
|
97
|
+
async comparePassword(entity: any, password: string) {
|
|
98
|
+
const { entityPasswordField, errorMessage } = this.configuration
|
|
97
99
|
// find password in entity, this allows for dot notation
|
|
98
|
-
const hash = get(entity, entityPasswordField)
|
|
100
|
+
const hash = get(entity, entityPasswordField)
|
|
99
101
|
|
|
100
102
|
if (!hash) {
|
|
101
|
-
debug(`Record is missing the '${entityPasswordField}' password field`)
|
|
103
|
+
debug(`Record is missing the '${entityPasswordField}' password field`)
|
|
102
104
|
|
|
103
|
-
throw new NotAuthenticated(errorMessage)
|
|
105
|
+
throw new NotAuthenticated(errorMessage)
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
debug('Verifying password')
|
|
108
|
+
debug('Verifying password')
|
|
107
109
|
|
|
108
|
-
const result = await bcrypt.compare(password, hash)
|
|
110
|
+
const result = await bcrypt.compare(password, hash)
|
|
109
111
|
|
|
110
112
|
if (result) {
|
|
111
|
-
return entity
|
|
113
|
+
return entity
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
throw new NotAuthenticated(errorMessage)
|
|
116
|
+
throw new NotAuthenticated(errorMessage)
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
async hashPassword
|
|
118
|
-
return bcrypt.hash(password, this.configuration.hashSize)
|
|
119
|
+
async hashPassword(password: string, _params: Params) {
|
|
120
|
+
return bcrypt.hash(password, this.configuration.hashSize)
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
async authenticate
|
|
122
|
-
const { passwordField, usernameField, entity, errorMessage } = this.configuration
|
|
123
|
-
const username = data[usernameField]
|
|
124
|
-
const password = data[passwordField]
|
|
123
|
+
async authenticate(data: AuthenticationRequest, params: Params) {
|
|
124
|
+
const { passwordField, usernameField, entity, errorMessage } = this.configuration
|
|
125
|
+
const username = data[usernameField]
|
|
126
|
+
const password = data[passwordField]
|
|
125
127
|
|
|
126
|
-
if (!password) {
|
|
127
|
-
|
|
128
|
+
if (!password) {
|
|
129
|
+
// exit early if there is no password
|
|
130
|
+
throw new NotAuthenticated(errorMessage)
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
const result = await this.findEntity(username, omit(params, 'provider'))
|
|
133
|
+
const result = await this.findEntity(username, omit(params, 'provider'))
|
|
131
134
|
|
|
132
|
-
await this.comparePassword(result, password)
|
|
135
|
+
await this.comparePassword(result, password)
|
|
133
136
|
|
|
134
137
|
return {
|
|
135
138
|
authentication: { strategy: this.name },
|
|
136
139
|
[entity]: await this.getEntity(result, params)
|
|
137
|
-
}
|
|
140
|
+
}
|
|
138
141
|
}
|
|
139
142
|
}
|