UNPKG

8.43 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.AuthenticationBase = void 0;
16const merge_1 = __importDefault(require("lodash/merge"));
17const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
18const uuid_1 = require("uuid");
19const errors_1 = require("@feathersjs/errors");
20const debug_1 = __importDefault(require("debug"));
21const options_1 = __importDefault(require("./options"));
22const debug = (0, debug_1.default)('@feathersjs/authentication/base');
23/**
24 * A base class for managing authentication strategies and creating and verifying JWTs
25 */
26class AuthenticationBase {
27 /**
28 * Create a new authentication service.
29 * @param app The Feathers application instance
30 * @param configKey The configuration key name in `app.get` (default: `authentication`)
31 * @param options Optional initial options
32 */
33 constructor(app, configKey = 'authentication', options = {}) {
34 if (!app || typeof app.use !== 'function') {
35 throw new Error('An application instance has to be passed to the authentication service');
36 }
37 this.app = app;
38 this.strategies = {};
39 this.configKey = configKey;
40 app.set('defaultAuthentication', app.get('defaultAuthentication') || configKey);
41 app.set(configKey, (0, merge_1.default)({}, app.get(configKey), options));
42 }
43 /**
44 * Return the current configuration from the application
45 */
46 get configuration() {
47 // Always returns a copy of the authentication configuration
48 return Object.assign({}, options_1.default, this.app.get(this.configKey));
49 }
50 /**
51 * A list of all registered strategy names
52 */
53 get strategyNames() {
54 return Object.keys(this.strategies);
55 }
56 /**
57 * Register a new authentication strategy under a given name.
58 * @param name The name to register the strategy under
59 * @param strategy The authentication strategy instance
60 */
61 register(name, strategy) {
62 // Call the functions a strategy can implement
63 if (typeof strategy.setName === 'function') {
64 strategy.setName(name);
65 }
66 if (typeof strategy.setApplication === 'function') {
67 strategy.setApplication(this.app);
68 }
69 if (typeof strategy.setAuthentication === 'function') {
70 strategy.setAuthentication(this);
71 }
72 if (typeof strategy.verifyConfiguration === 'function') {
73 strategy.verifyConfiguration();
74 }
75 // Register strategy as name
76 this.strategies[name] = strategy;
77 }
78 /**
79 * Get the registered authentication strategies for a list of names.
80 * @param names The list or strategy names
81 */
82 getStrategies(...names) {
83 return names.map(name => this.strategies[name])
84 .filter(current => !!current);
85 }
86 /**
87 * Create a new access token with payload and options.
88 * @param payload The JWT payload
89 * @param optsOverride The options to extend the defaults (`configuration.jwtOptions`) with
90 * @param secretOverride Use a different secret instead
91 */
92 createAccessToken(payload, optsOverride, secretOverride) {
93 return __awaiter(this, void 0, void 0, function* () {
94 const { secret, jwtOptions } = this.configuration;
95 // Use configuration by default but allow overriding the secret
96 const jwtSecret = secretOverride || secret;
97 // Default jwt options merged with additional options
98 const options = (0, merge_1.default)({}, jwtOptions, optsOverride);
99 if (!options.jwtid) {
100 // Generate a UUID as JWT ID by default
101 options.jwtid = (0, uuid_1.v4)();
102 }
103 return jsonwebtoken_1.default.sign(payload, jwtSecret, options);
104 });
105 }
106 /**
107 * Verifies an access token.
108 * @param accessToken The token to verify
109 * @param optsOverride The options to extend the defaults (`configuration.jwtOptions`) with
110 * @param secretOverride Use a different secret instead
111 */
112 verifyAccessToken(accessToken, optsOverride, secretOverride) {
113 return __awaiter(this, void 0, void 0, function* () {
114 const { secret, jwtOptions } = this.configuration;
115 const jwtSecret = secretOverride || secret;
116 const options = (0, merge_1.default)({}, jwtOptions, optsOverride);
117 const { algorithm } = options;
118 // Normalize the `algorithm` setting into the algorithms array
119 if (algorithm && !options.algorithms) {
120 options.algorithms = Array.isArray(algorithm) ? algorithm : [algorithm];
121 delete options.algorithm;
122 }
123 try {
124 const verified = yield jsonwebtoken_1.default.verify(accessToken, jwtSecret, options);
125 return verified;
126 }
127 catch (error) {
128 throw new errors_1.NotAuthenticated(error.message, error);
129 }
130 });
131 }
132 /**
133 * Authenticate a given authentication request against a list of strategies.
134 * @param authentication The authentication request
135 * @param params Service call parameters
136 * @param allowed A list of allowed strategy names
137 */
138 authenticate(authentication, params, ...allowed) {
139 return __awaiter(this, void 0, void 0, function* () {
140 const { strategy } = authentication || {};
141 const [authStrategy] = this.getStrategies(strategy);
142 const strategyAllowed = allowed.includes(strategy);
143 debug('Running authenticate for strategy', strategy, allowed);
144 if (!authentication || !authStrategy || !strategyAllowed) {
145 const additionalInfo = (!strategy && ' (no `strategy` set)') ||
146 (!strategyAllowed && ' (strategy not allowed in authStrategies)') || '';
147 // If there are no valid strategies or `authentication` is not an object
148 throw new errors_1.NotAuthenticated('Invalid authentication information' + additionalInfo);
149 }
150 return authStrategy.authenticate(authentication, Object.assign(Object.assign({}, params), { authenticated: true }));
151 });
152 }
153 handleConnection(event, connection, authResult) {
154 return __awaiter(this, void 0, void 0, function* () {
155 const strategies = this.getStrategies(...Object.keys(this.strategies))
156 .filter(current => typeof current.handleConnection === 'function');
157 for (const strategy of strategies) {
158 yield strategy.handleConnection(event, connection, authResult);
159 }
160 });
161 }
162 /**
163 * Parse an HTTP request and response for authentication request information.
164 * @param req The HTTP request
165 * @param res The HTTP response
166 * @param names A list of strategies to use
167 */
168 parse(req, res, ...names) {
169 return __awaiter(this, void 0, void 0, function* () {
170 const strategies = this.getStrategies(...names)
171 .filter(current => typeof current.parse === 'function');
172 debug('Strategies parsing HTTP header for authentication information', names);
173 for (const authStrategy of strategies) {
174 const value = yield authStrategy.parse(req, res);
175 if (value !== null) {
176 return value;
177 }
178 }
179 return null;
180 });
181 }
182}
183exports.AuthenticationBase = AuthenticationBase;
184//# sourceMappingURL=core.js.map
\No newline at end of file