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.AuthenticationService = void 0;
|
7 | const merge_1 = __importDefault(require("lodash/merge"));
|
8 | const errors_1 = require("@feathersjs/errors");
|
9 | require("@feathersjs/transport-commons");
|
10 | const commons_1 = require("@feathersjs/commons");
|
11 | const schema_1 = require("@feathersjs/schema");
|
12 | const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
13 | const hooks_1 = require("@feathersjs/hooks");
|
14 | const core_1 = require("./core");
|
15 | const hooks_2 = require("./hooks");
|
16 | const debug = (0, commons_1.createDebug)('@feathersjs/authentication/service');
|
17 | class AuthenticationService extends core_1.AuthenticationBase {
|
18 | constructor(app, configKey = 'authentication', options = {}) {
|
19 | super(app, configKey, options);
|
20 | (0, hooks_1.hooks)(this, {
|
21 | create: [(0, schema_1.resolveDispatch)(), (0, hooks_2.event)('login'), (0, hooks_2.connection)('login')],
|
22 | remove: [(0, schema_1.resolveDispatch)(), (0, hooks_2.event)('logout'), (0, hooks_2.connection)('logout')]
|
23 | });
|
24 | this.app.on('disconnect', async (connection) => {
|
25 | await this.handleConnection('disconnect', connection);
|
26 | });
|
27 | if (typeof app.defaultAuthentication !== 'function') {
|
28 | app.defaultAuthentication = function (location) {
|
29 | const configKey = app.get('defaultAuthentication');
|
30 | const path = location ||
|
31 | Object.keys(this.services).find((current) => this.service(current).configKey === configKey);
|
32 | return path ? this.service(path) : null;
|
33 | };
|
34 | }
|
35 | }
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | async getPayload(_authResult, params) {
|
44 |
|
45 | const { payload = {} } = params;
|
46 | return payload;
|
47 | }
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | async getTokenOptions(authResult, params) {
|
56 | const { service, entity, entityId } = this.configuration;
|
57 | const jwtOptions = (0, merge_1.default)({}, params.jwtOptions, params.jwt);
|
58 | const value = service && entity && authResult[entity];
|
59 |
|
60 | if (value && !jwtOptions.subject) {
|
61 | const idProperty = entityId || this.app.service(service).id;
|
62 | const subject = value[idProperty];
|
63 | if (subject === undefined) {
|
64 | throw new errors_1.NotAuthenticated(`Can not set subject from ${entity}.${idProperty}`);
|
65 | }
|
66 | jwtOptions.subject = `${subject}`;
|
67 | }
|
68 | return jwtOptions;
|
69 | }
|
70 | |
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | async create(data, params) {
|
78 | const authStrategies = params.authStrategies || this.configuration.authStrategies;
|
79 | if (!authStrategies.length) {
|
80 | throw new errors_1.NotAuthenticated('No authentication strategies allowed for creating a JWT (`authStrategies`)');
|
81 | }
|
82 | const authResult = await this.authenticate(data, params, ...authStrategies);
|
83 | debug('Got authentication result', authResult);
|
84 | if (authResult.accessToken) {
|
85 | return authResult;
|
86 | }
|
87 | const [payload, jwtOptions] = await Promise.all([
|
88 | this.getPayload(authResult, params),
|
89 | this.getTokenOptions(authResult, params)
|
90 | ]);
|
91 | debug('Creating JWT with', payload, jwtOptions);
|
92 | const accessToken = await this.createAccessToken(payload, jwtOptions, params.secret);
|
93 | return {
|
94 | accessToken,
|
95 | ...authResult,
|
96 | authentication: {
|
97 | ...authResult.authentication,
|
98 | payload: jsonwebtoken_1.default.decode(accessToken)
|
99 | }
|
100 | };
|
101 | }
|
102 | |
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | async remove(id, params) {
|
110 | const { authentication } = params;
|
111 | const { authStrategies } = this.configuration;
|
112 |
|
113 | if (id !== null && id !== authentication.accessToken) {
|
114 | throw new errors_1.NotAuthenticated('Invalid access token');
|
115 | }
|
116 | debug('Verifying authentication strategy in remove');
|
117 | return this.authenticate(authentication, params, ...authStrategies);
|
118 | }
|
119 | |
120 |
|
121 |
|
122 | async setup() {
|
123 | await super.setup();
|
124 |
|
125 |
|
126 | const { secret, service, entity, entityId } = this.configuration;
|
127 | if (typeof secret !== 'string') {
|
128 | throw new Error("A 'secret' must be provided in your authentication configuration");
|
129 | }
|
130 | if (entity !== null) {
|
131 | if (service === undefined) {
|
132 | throw new Error("The 'service' option is not set in the authentication configuration");
|
133 | }
|
134 | if (this.app.service(service) === undefined) {
|
135 | throw new Error(`The '${service}' entity service does not exist (set to 'null' if it is not required)`);
|
136 | }
|
137 | if (this.app.service(service).id === undefined && entityId === undefined) {
|
138 | throw new Error(`The '${service}' service does not have an 'id' property and no 'entityId' option is set.`);
|
139 | }
|
140 | }
|
141 | const publishable = this;
|
142 | if (typeof publishable.publish === 'function') {
|
143 | publishable.publish(() => null);
|
144 | }
|
145 | }
|
146 | }
|
147 | exports.AuthenticationService = AuthenticationService;
|
148 |
|
\ | No newline at end of file |