UNPKG

7.49 kBJavaScriptView Raw
1"use strict";
2var __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};
11var __importDefault = (this && this.__importDefault) || function (mod) {
12 return (mod && mod.__esModule) ? mod : { "default": mod };
13};
14Object.defineProperty(exports, "__esModule", { value: true });
15exports.AuthenticationService = void 0;
16const debug_1 = __importDefault(require("debug"));
17const merge_1 = __importDefault(require("lodash/merge"));
18const errors_1 = require("@feathersjs/errors");
19const core_1 = require("./core");
20const hooks_1 = require("./hooks");
21require("@feathersjs/transport-commons");
22const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
23const debug = (0, debug_1.default)('@feathersjs/authentication/service');
24class 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 * Return the payload for a JWT based on the authentication result.
37 * Called internally by the `create` method.
38 * @param _authResult The current authentication result
39 * @param params The service call parameters
40 */
41 getPayload(_authResult, params) {
42 return __awaiter(this, void 0, void 0, function* () {
43 // Uses `params.payload` or returns an empty payload
44 const { payload = {} } = params;
45 return payload;
46 });
47 }
48 /**
49 * Returns the JWT options based on an authentication result.
50 * By default sets the JWT subject to the entity id.
51 * @param authResult The authentication result
52 * @param params Service call parameters
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 // Set the subject to the entity id if it is available
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 * Create and return a new JWT for a given authentication request.
73 * Will trigger the `login` event.
74 * @param data The authentication request (should include `strategy` key)
75 * @param params Service call parameters
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 * Mark a JWT as removed. By default only verifies the JWT and returns the result.
104 * Triggers the `logout` event.
105 * @param id The JWT to remove or null
106 * @param params Service call parameters
107 */
108 remove(id, params) {
109 return __awaiter(this, void 0, void 0, function* () {
110 const { authentication } = params;
111 const { authStrategies } = this.configuration;
112 // When an id is passed it is expected to be the authentication `accessToken`
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 * Validates the service configuration.
122 */
123 setup() {
124 // The setup method checks for valid settings and registers the
125 // connection and event (login, logout) hooks
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}
155exports.AuthenticationService = AuthenticationService;
156//# sourceMappingURL=service.js.map
\No newline at end of file