UNPKG

6.61 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.AuthenticationService = void 0;
7const merge_1 = __importDefault(require("lodash/merge"));
8const errors_1 = require("@feathersjs/errors");
9require("@feathersjs/transport-commons");
10const commons_1 = require("@feathersjs/commons");
11const schema_1 = require("@feathersjs/schema");
12const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
13const hooks_1 = require("@feathersjs/hooks");
14const core_1 = require("./core");
15const hooks_2 = require("./hooks");
16const debug = (0, commons_1.createDebug)('@feathersjs/authentication/service');
17class 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 * Return the payload for a JWT based on the authentication result.
38 * Called internally by the `create` method.
39 *
40 * @param _authResult The current authentication result
41 * @param params The service call parameters
42 */
43 async getPayload(_authResult, params) {
44 // Uses `params.payload` or returns an empty payload
45 const { payload = {} } = params;
46 return payload;
47 }
48 /**
49 * Returns the JWT options based on an authentication result.
50 * By default sets the JWT subject to the entity id.
51 *
52 * @param authResult The authentication result
53 * @param params Service call parameters
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 // 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 * Create and return a new JWT for a given authentication request.
72 * Will trigger the `login` event.
73 *
74 * @param data The authentication request (should include `strategy` key)
75 * @param params Service call parameters
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 * Mark a JWT as removed. By default only verifies the JWT and returns the result.
104 * Triggers the `logout` event.
105 *
106 * @param id The JWT to remove or null
107 * @param params Service call parameters
108 */
109 async remove(id, params) {
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 * Validates the service configuration.
121 */
122 async setup() {
123 await super.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 const publishable = this;
142 if (typeof publishable.publish === 'function') {
143 publishable.publish(() => null);
144 }
145 }
146}
147exports.AuthenticationService = AuthenticationService;
148//# sourceMappingURL=service.js.map
\No newline at end of file