1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4 | return new (P || (P = Promise))(function (resolve, reject) {
|
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9 | });
|
10 | };
|
11 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
12 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
13 | };
|
14 | Object.defineProperty(exports, "__esModule", { value: true });
|
15 | exports.AuthenticationService = void 0;
|
16 | const debug_1 = __importDefault(require("debug"));
|
17 | const merge_1 = __importDefault(require("lodash/merge"));
|
18 | const errors_1 = require("@feathersjs/errors");
|
19 | const core_1 = require("./core");
|
20 | const hooks_1 = require("./hooks");
|
21 | require("@feathersjs/transport-commons");
|
22 | const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
23 | const debug = (0, debug_1.default)('@feathersjs/authentication/service');
|
24 | class AuthenticationService extends core_1.AuthenticationBase {
|
25 | constructor(app, configKey = 'authentication', options = {}) {
|
26 | super(app, configKey, options);
|
27 | if (typeof app.defaultAuthentication !== 'function') {
|
28 | app.defaultAuthentication = function (location) {
|
29 | const configKey = app.get('defaultAuthentication');
|
30 | const path = location || Object.keys(this.services).find(current => this.service(current).configKey === configKey);
|
31 | return path ? this.service(path) : null;
|
32 | };
|
33 | }
|
34 | }
|
35 | |
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | getPayload(_authResult, params) {
|
42 | return __awaiter(this, void 0, void 0, function* () {
|
43 |
|
44 | const { payload = {} } = params;
|
45 | return payload;
|
46 | });
|
47 | }
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | getTokenOptions(authResult, params) {
|
55 | return __awaiter(this, void 0, void 0, function* () {
|
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 | create(data, params) {
|
78 | return __awaiter(this, void 0, void 0, function* () {
|
79 | const authStrategies = params.authStrategies || this.configuration.authStrategies;
|
80 | if (!authStrategies.length) {
|
81 | throw new errors_1.NotAuthenticated('No authentication strategies allowed for creating a JWT (`authStrategies`)');
|
82 | }
|
83 | const authResult = yield this.authenticate(data, params, ...authStrategies);
|
84 | debug('Got authentication result', authResult);
|
85 | if (authResult.accessToken) {
|
86 | return authResult;
|
87 | }
|
88 | const [payload, jwtOptions] = yield Promise.all([
|
89 | this.getPayload(authResult, params),
|
90 | this.getTokenOptions(authResult, params)
|
91 | ]);
|
92 | debug('Creating JWT with', payload, jwtOptions);
|
93 | const accessToken = yield this.createAccessToken(payload, jwtOptions, params.secret);
|
94 | return (0, merge_1.default)({ accessToken }, authResult, {
|
95 | authentication: {
|
96 | accessToken,
|
97 | payload: jsonwebtoken_1.default.decode(accessToken)
|
98 | }
|
99 | });
|
100 | });
|
101 | }
|
102 | |
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 | remove(id, params) {
|
109 | return __awaiter(this, void 0, void 0, function* () {
|
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 |
|
123 | 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 | this.hooks({
|
142 | after: {
|
143 | create: [(0, hooks_1.connection)('login'), (0, hooks_1.event)('login')],
|
144 | remove: [(0, hooks_1.connection)('logout'), (0, hooks_1.event)('logout')]
|
145 | }
|
146 | });
|
147 | this.app.on('disconnect', (connection) => __awaiter(this, void 0, void 0, function* () {
|
148 | yield this.handleConnection('disconnect', connection);
|
149 | }));
|
150 | if (typeof this.publish === 'function') {
|
151 | this.publish(() => null);
|
152 | }
|
153 | }
|
154 | }
|
155 | exports.AuthenticationService = AuthenticationService;
|
156 |
|
\ | No newline at end of file |