@feathersjs/authentication 5.0.0-pre.21 → 5.0.0-pre.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/core.ts CHANGED
@@ -1,32 +1,32 @@
1
- import merge from 'lodash/merge';
2
- import jsonwebtoken, { SignOptions, Secret, VerifyOptions } from 'jsonwebtoken';
3
- import { v4 as uuidv4 } from 'uuid';
4
- import { NotAuthenticated } from '@feathersjs/errors';
5
- import { createDebug } from '@feathersjs/commons';
6
- import { Application, Params } from '@feathersjs/feathers';
7
- import { IncomingMessage, ServerResponse } from 'http';
8
- import { defaultOptions } from './options';
1
+ import merge from 'lodash/merge'
2
+ import jsonwebtoken, { SignOptions, Secret, VerifyOptions } from 'jsonwebtoken'
3
+ import { v4 as uuidv4 } from 'uuid'
4
+ import { NotAuthenticated } from '@feathersjs/errors'
5
+ import { createDebug } from '@feathersjs/commons'
6
+ import { Application, Params } from '@feathersjs/feathers'
7
+ import { IncomingMessage, ServerResponse } from 'http'
8
+ import { defaultOptions } from './options'
9
9
 
10
- const debug = createDebug('@feathersjs/authentication/base');
10
+ const debug = createDebug('@feathersjs/authentication/base')
11
11
 
12
12
  export interface AuthenticationResult {
13
- [key: string]: any;
13
+ [key: string]: any
14
14
  }
15
15
 
16
16
  export interface AuthenticationRequest {
17
- strategy?: string;
18
- [key: string]: any;
17
+ strategy?: string
18
+ [key: string]: any
19
19
  }
20
20
 
21
21
  export interface AuthenticationParams extends Params {
22
- payload?: { [key: string]: any };
23
- jwtOptions?: SignOptions;
24
- authStrategies?: string[];
25
- secret?: string;
26
- [key: string]: any;
22
+ payload?: { [key: string]: any }
23
+ jwtOptions?: SignOptions
24
+ authStrategies?: string[]
25
+ secret?: string
26
+ [key: string]: any
27
27
  }
28
28
 
29
- export type ConnectionEvent = 'login' | 'logout' | 'disconnect';
29
+ export type ConnectionEvent = 'login' | 'logout' | 'disconnect'
30
30
 
31
31
  export interface AuthenticationStrategy {
32
32
  /**
@@ -34,30 +34,30 @@ export interface AuthenticationStrategy {
34
34
  *
35
35
  * @param auth The AuthenticationService
36
36
  */
37
- setAuthentication? (auth: AuthenticationBase): void;
37
+ setAuthentication?(auth: AuthenticationBase): void
38
38
  /**
39
39
  * Implement this method to get access to the Feathers application
40
40
  *
41
41
  * @param app The Feathers application instance
42
42
  */
43
- setApplication? (app: Application): void;
43
+ setApplication?(app: Application): void
44
44
  /**
45
45
  * Implement this method to get access to the strategy name
46
46
  *
47
47
  * @param name The name of the strategy
48
48
  */
49
- setName? (name: string): void;
49
+ setName?(name: string): void
50
50
  /**
51
51
  * Implement this method to verify the current configuration
52
52
  * and throw an error if it is invalid.
53
53
  */
54
- verifyConfiguration? (): void;
54
+ verifyConfiguration?(): void
55
55
  /**
56
56
  * Implement this method to setup this strategy
57
57
  * @param auth The AuthenticationService
58
58
  * @param name The name of the strategy
59
59
  */
60
- setup? (auth: AuthenticationBase, name: string): Promise<void>;
60
+ setup?(auth: AuthenticationBase, name: string): Promise<void>
61
61
  /**
62
62
  * Authenticate an authentication request with this strategy.
63
63
  * Should throw an error if the strategy did not succeed.
@@ -65,35 +65,38 @@ export interface AuthenticationStrategy {
65
65
  * @param authentication The authentication request
66
66
  * @param params The service call parameters
67
67
  */
68
- authenticate? (authentication: AuthenticationRequest, params: AuthenticationParams): Promise<AuthenticationResult>;
68
+ authenticate?(
69
+ authentication: AuthenticationRequest,
70
+ params: AuthenticationParams
71
+ ): Promise<AuthenticationResult>
69
72
  /**
70
73
  * Update a real-time connection according to this strategy.
71
74
  *
72
75
  * @param connection The real-time connection
73
76
  * @param context The hook context
74
77
  */
75
- handleConnection? (event: ConnectionEvent, connection: any, authResult?: AuthenticationResult): Promise<void>;
78
+ handleConnection?(event: ConnectionEvent, connection: any, authResult?: AuthenticationResult): Promise<void>
76
79
  /**
77
80
  * Parse a basic HTTP request and response for authentication request information.
78
81
  *
79
82
  * @param req The HTTP request
80
83
  * @param res The HTTP response
81
84
  */
82
- parse? (req: IncomingMessage, res: ServerResponse): Promise<AuthenticationRequest | null>;
85
+ parse?(req: IncomingMessage, res: ServerResponse): Promise<AuthenticationRequest | null>
83
86
  }
84
87
 
85
88
  export interface JwtVerifyOptions extends VerifyOptions {
86
- algorithm?: string | string[];
89
+ algorithm?: string | string[]
87
90
  }
88
91
 
89
92
  /**
90
93
  * A base class for managing authentication strategies and creating and verifying JWTs
91
94
  */
92
95
  export class AuthenticationBase {
93
- app: Application;
94
- strategies: { [key: string]: AuthenticationStrategy };
95
- configKey: string;
96
- isReady: boolean;
96
+ app: Application
97
+ strategies: { [key: string]: AuthenticationStrategy }
98
+ configKey: string
99
+ isReady: boolean
97
100
 
98
101
  /**
99
102
  * Create a new authentication service.
@@ -102,33 +105,33 @@ export class AuthenticationBase {
102
105
  * @param configKey The configuration key name in `app.get` (default: `authentication`)
103
106
  * @param options Optional initial options
104
107
  */
105
- constructor (app: Application, configKey = 'authentication', options = {}) {
108
+ constructor(app: Application, configKey = 'authentication', options = {}) {
106
109
  if (!app || typeof app.use !== 'function') {
107
- throw new Error('An application instance has to be passed to the authentication service');
110
+ throw new Error('An application instance has to be passed to the authentication service')
108
111
  }
109
112
 
110
- this.app = app;
111
- this.strategies = {};
112
- this.configKey = configKey;
113
- this.isReady = false;
113
+ this.app = app
114
+ this.strategies = {}
115
+ this.configKey = configKey
116
+ this.isReady = false
114
117
 
115
- app.set('defaultAuthentication', app.get('defaultAuthentication') || configKey);
116
- app.set(configKey, merge({}, app.get(configKey), options));
118
+ app.set('defaultAuthentication', app.get('defaultAuthentication') || configKey)
119
+ app.set(configKey, merge({}, app.get(configKey), options))
117
120
  }
118
121
 
119
122
  /**
120
123
  * Return the current configuration from the application
121
124
  */
122
- get configuration () {
125
+ get configuration() {
123
126
  // Always returns a copy of the authentication configuration
124
- return Object.assign({}, defaultOptions, this.app.get(this.configKey));
127
+ return Object.assign({}, defaultOptions, this.app.get(this.configKey))
125
128
  }
126
129
 
127
130
  /**
128
131
  * A list of all registered strategy names
129
132
  */
130
- get strategyNames () {
131
- return Object.keys(this.strategies);
133
+ get strategyNames() {
134
+ return Object.keys(this.strategies)
132
135
  }
133
136
 
134
137
  /**
@@ -137,29 +140,29 @@ export class AuthenticationBase {
137
140
  * @param name The name to register the strategy under
138
141
  * @param strategy The authentication strategy instance
139
142
  */
140
- register (name: string, strategy: AuthenticationStrategy) {
143
+ register(name: string, strategy: AuthenticationStrategy) {
141
144
  // Call the functions a strategy can implement
142
145
  if (typeof strategy.setName === 'function') {
143
- strategy.setName(name);
146
+ strategy.setName(name)
144
147
  }
145
148
 
146
149
  if (typeof strategy.setApplication === 'function') {
147
- strategy.setApplication(this.app);
150
+ strategy.setApplication(this.app)
148
151
  }
149
152
 
150
153
  if (typeof strategy.setAuthentication === 'function') {
151
- strategy.setAuthentication(this);
154
+ strategy.setAuthentication(this)
152
155
  }
153
156
 
154
157
  if (typeof strategy.verifyConfiguration === 'function') {
155
- strategy.verifyConfiguration();
158
+ strategy.verifyConfiguration()
156
159
  }
157
160
 
158
161
  // Register strategy as name
159
- this.strategies[name] = strategy;
162
+ this.strategies[name] = strategy
160
163
 
161
164
  if (this.isReady) {
162
- strategy.setup?.(this, name);
165
+ strategy.setup?.(this, name)
163
166
  }
164
167
  }
165
168
 
@@ -168,9 +171,8 @@ export class AuthenticationBase {
168
171
  *
169
172
  * @param names The list or strategy names
170
173
  */
171
- getStrategies (...names: string[]) {
172
- return names.map(name => this.strategies[name])
173
- .filter(current => !!current);
174
+ getStrategies(...names: string[]) {
175
+ return names.map((name) => this.strategies[name]).filter((current) => !!current)
174
176
  }
175
177
 
176
178
  /**
@@ -179,8 +181,8 @@ export class AuthenticationBase {
179
181
  * @param name The strategy name
180
182
  * @returns The authentication strategy or undefined
181
183
  */
182
- getStrategy (name: string) {
183
- return this.strategies[name];
184
+ getStrategy(name: string) {
185
+ return this.strategies[name]
184
186
  }
185
187
 
186
188
  /**
@@ -190,19 +192,23 @@ export class AuthenticationBase {
190
192
  * @param optsOverride The options to extend the defaults (`configuration.jwtOptions`) with
191
193
  * @param secretOverride Use a different secret instead
192
194
  */
193
- async createAccessToken (payload: string | Buffer | object, optsOverride?: SignOptions, secretOverride?: Secret) {
194
- const { secret, jwtOptions } = this.configuration;
195
+ async createAccessToken(
196
+ payload: string | Buffer | object,
197
+ optsOverride?: SignOptions,
198
+ secretOverride?: Secret
199
+ ) {
200
+ const { secret, jwtOptions } = this.configuration
195
201
  // Use configuration by default but allow overriding the secret
196
- const jwtSecret = secretOverride || secret;
202
+ const jwtSecret = secretOverride || secret
197
203
  // Default jwt options merged with additional options
198
- const options = merge({}, jwtOptions, optsOverride);
204
+ const options = merge({}, jwtOptions, optsOverride)
199
205
 
200
206
  if (!options.jwtid) {
201
207
  // Generate a UUID as JWT ID by default
202
- options.jwtid = uuidv4();
208
+ options.jwtid = uuidv4()
203
209
  }
204
210
 
205
- return jsonwebtoken.sign(payload, jwtSecret, options);
211
+ return jsonwebtoken.sign(payload, jwtSecret, options)
206
212
  }
207
213
 
208
214
  /**
@@ -212,24 +218,24 @@ export class AuthenticationBase {
212
218
  * @param optsOverride The options to extend the defaults (`configuration.jwtOptions`) with
213
219
  * @param secretOverride Use a different secret instead
214
220
  */
215
- async verifyAccessToken (accessToken: string, optsOverride?: JwtVerifyOptions, secretOverride?: Secret) {
216
- const { secret, jwtOptions } = this.configuration;
217
- const jwtSecret = secretOverride || secret;
218
- const options = merge({}, jwtOptions, optsOverride);
219
- const { algorithm } = options;
221
+ async verifyAccessToken(accessToken: string, optsOverride?: JwtVerifyOptions, secretOverride?: Secret) {
222
+ const { secret, jwtOptions } = this.configuration
223
+ const jwtSecret = secretOverride || secret
224
+ const options = merge({}, jwtOptions, optsOverride)
225
+ const { algorithm } = options
220
226
 
221
227
  // Normalize the `algorithm` setting into the algorithms array
222
228
  if (algorithm && !options.algorithms) {
223
- options.algorithms = Array.isArray(algorithm) ? algorithm : [ algorithm ];
224
- delete options.algorithm;
229
+ options.algorithms = Array.isArray(algorithm) ? algorithm : [algorithm]
230
+ delete options.algorithm
225
231
  }
226
232
 
227
233
  try {
228
- const verified = jsonwebtoken.verify(accessToken, jwtSecret, options);
234
+ const verified = jsonwebtoken.verify(accessToken, jwtSecret, options)
229
235
 
230
- return verified as any;
236
+ return verified as any
231
237
  } catch (error: any) {
232
- throw new NotAuthenticated(error.message, error);
238
+ throw new NotAuthenticated(error.message, error)
233
239
  }
234
240
  }
235
241
 
@@ -240,33 +246,40 @@ export class AuthenticationBase {
240
246
  * @param params Service call parameters
241
247
  * @param allowed A list of allowed strategy names
242
248
  */
243
- async authenticate (authentication: AuthenticationRequest, params: AuthenticationParams, ...allowed: string[]) {
244
- const { strategy } = authentication || {};
245
- const [ authStrategy ] = this.getStrategies(strategy);
246
- const strategyAllowed = allowed.includes(strategy);
249
+ async authenticate(
250
+ authentication: AuthenticationRequest,
251
+ params: AuthenticationParams,
252
+ ...allowed: string[]
253
+ ) {
254
+ const { strategy } = authentication || {}
255
+ const [authStrategy] = this.getStrategies(strategy)
256
+ const strategyAllowed = allowed.includes(strategy)
247
257
 
248
- debug('Running authenticate for strategy', strategy, allowed);
258
+ debug('Running authenticate for strategy', strategy, allowed)
249
259
 
250
260
  if (!authentication || !authStrategy || !strategyAllowed) {
251
- const additionalInfo = (!strategy && ' (no `strategy` set)') ||
252
- (!strategyAllowed && ' (strategy not allowed in authStrategies)') || '';
261
+ const additionalInfo =
262
+ (!strategy && ' (no `strategy` set)') ||
263
+ (!strategyAllowed && ' (strategy not allowed in authStrategies)') ||
264
+ ''
253
265
 
254
266
  // If there are no valid strategies or `authentication` is not an object
255
- throw new NotAuthenticated('Invalid authentication information' + additionalInfo);
267
+ throw new NotAuthenticated('Invalid authentication information' + additionalInfo)
256
268
  }
257
269
 
258
270
  return authStrategy.authenticate(authentication, {
259
271
  ...params,
260
272
  authenticated: true
261
- });
273
+ })
262
274
  }
263
275
 
264
- async handleConnection (event: ConnectionEvent, connection: any, authResult?: AuthenticationResult) {
265
- const strategies = this.getStrategies(...Object.keys(this.strategies))
266
- .filter(current => typeof current.handleConnection === 'function');
276
+ async handleConnection(event: ConnectionEvent, connection: any, authResult?: AuthenticationResult) {
277
+ const strategies = this.getStrategies(...Object.keys(this.strategies)).filter(
278
+ (current) => typeof current.handleConnection === 'function'
279
+ )
267
280
 
268
281
  for (const strategy of strategies) {
269
- await strategy.handleConnection(event, connection, authResult);
282
+ await strategy.handleConnection(event, connection, authResult)
270
283
  }
271
284
  }
272
285
 
@@ -277,30 +290,29 @@ export class AuthenticationBase {
277
290
  * @param res The HTTP response
278
291
  * @param names A list of strategies to use
279
292
  */
280
- async parse (req: IncomingMessage, res: ServerResponse, ...names: string[]) {
281
- const strategies = this.getStrategies(...names)
282
- .filter(current => typeof current.parse === 'function');
293
+ async parse(req: IncomingMessage, res: ServerResponse, ...names: string[]) {
294
+ const strategies = this.getStrategies(...names).filter((current) => typeof current.parse === 'function')
283
295
 
284
- debug('Strategies parsing HTTP header for authentication information', names);
296
+ debug('Strategies parsing HTTP header for authentication information', names)
285
297
 
286
298
  for (const authStrategy of strategies) {
287
- const value = await authStrategy.parse(req, res);
299
+ const value = await authStrategy.parse(req, res)
288
300
 
289
301
  if (value !== null) {
290
- return value;
302
+ return value
291
303
  }
292
304
  }
293
305
 
294
- return null;
306
+ return null
295
307
  }
296
308
 
297
- async setup () {
298
- this.isReady = true;
309
+ async setup() {
310
+ this.isReady = true
299
311
 
300
312
  for (const name of Object.keys(this.strategies)) {
301
- const strategy = this.strategies[name];
313
+ const strategy = this.strategies[name]
302
314
 
303
- await strategy.setup?.(this, name);
315
+ await strategy.setup?.(this, name)
304
316
  }
305
317
  }
306
318
  }
@@ -1,63 +1,67 @@
1
- import flatten from 'lodash/flatten';
2
- import omit from 'lodash/omit';
3
- import { HookContext, NextFunction } from '@feathersjs/feathers';
4
- import { NotAuthenticated } from '@feathersjs/errors';
5
- import { createDebug } from '@feathersjs/commons';
1
+ import flatten from 'lodash/flatten'
2
+ import omit from 'lodash/omit'
3
+ import { HookContext, NextFunction } from '@feathersjs/feathers'
4
+ import { NotAuthenticated } from '@feathersjs/errors'
5
+ import { createDebug } from '@feathersjs/commons'
6
6
 
7
- const debug = createDebug('@feathersjs/authentication/hooks/authenticate');
7
+ const debug = createDebug('@feathersjs/authentication/hooks/authenticate')
8
8
 
9
9
  export interface AuthenticateHookSettings {
10
- service?: string;
11
- strategies?: string[];
10
+ service?: string
11
+ strategies?: string[]
12
12
  }
13
13
 
14
14
  export default (originalSettings: string | AuthenticateHookSettings, ...originalStrategies: string[]) => {
15
- const settings = typeof originalSettings === 'string'
16
- ? { strategies: flatten([ originalSettings, ...originalStrategies ]) }
17
- : originalSettings;
15
+ const settings =
16
+ typeof originalSettings === 'string'
17
+ ? { strategies: flatten([originalSettings, ...originalStrategies]) }
18
+ : originalSettings
18
19
 
19
20
  if (!originalSettings || settings.strategies.length === 0) {
20
- throw new Error('The authenticate hook needs at least one allowed strategy');
21
+ throw new Error('The authenticate hook needs at least one allowed strategy')
21
22
  }
22
23
 
23
24
  return async (context: HookContext, _next?: NextFunction) => {
24
- const next = typeof _next === 'function' ? _next : async () => context;
25
- const { app, params, type, path, service } = context;
26
- const { strategies } = settings;
27
- const { provider, authentication } = params;
28
- const authService = app.defaultAuthentication(settings.service);
25
+ const next = typeof _next === 'function' ? _next : async () => context
26
+ const { app, params, type, path, service } = context
27
+ const { strategies } = settings
28
+ const { provider, authentication } = params
29
+ const authService = app.defaultAuthentication(settings.service)
29
30
 
30
- debug(`Running authenticate hook on '${path}'`);
31
+ debug(`Running authenticate hook on '${path}'`)
31
32
 
32
33
  if (type && type !== 'before') {
33
- throw new NotAuthenticated('The authenticate hook must be used as a before hook');
34
+ throw new NotAuthenticated('The authenticate hook must be used as a before hook')
34
35
  }
35
36
 
36
37
  if (!authService || typeof authService.authenticate !== 'function') {
37
- throw new NotAuthenticated('Could not find a valid authentication service');
38
+ throw new NotAuthenticated('Could not find a valid authentication service')
38
39
  }
39
40
 
40
- // @ts-ignore
41
41
  if (service === authService) {
42
- throw new NotAuthenticated('The authenticate hook does not need to be used on the authentication service');
42
+ throw new NotAuthenticated(
43
+ 'The authenticate hook does not need to be used on the authentication service'
44
+ )
43
45
  }
44
46
 
45
47
  if (params.authenticated === true) {
46
- return next();
48
+ return next()
47
49
  }
48
50
 
49
51
  if (authentication) {
50
- const authParams = omit(params, 'provider', 'authentication');
52
+ const authParams = omit(params, 'provider', 'authentication')
51
53
 
52
- debug('Authenticating with', authentication, strategies);
54
+ debug('Authenticating with', authentication, strategies)
53
55
 
54
- const authResult = await authService.authenticate(authentication, authParams, ...strategies);
56
+ const authResult = await authService.authenticate(authentication, authParams, ...strategies)
55
57
 
56
- context.params = Object.assign({}, params, omit(authResult, 'accessToken'), { authenticated: true });
58
+ context.params = Object.assign({}, params, omit(authResult, 'accessToken'), {
59
+ authenticated: true
60
+ })
57
61
  } else if (provider) {
58
- throw new NotAuthenticated('Not authenticated');
62
+ throw new NotAuthenticated('Not authenticated')
59
63
  }
60
64
 
61
- return next();
62
- };
63
- };
65
+ return next()
66
+ }
67
+ }
@@ -1,17 +1,20 @@
1
- import { HookContext, NextFunction } from '@feathersjs/feathers';
2
- import omit from 'lodash/omit';
3
- import { AuthenticationBase, ConnectionEvent } from '../core';
1
+ import { HookContext, NextFunction } from '@feathersjs/feathers'
2
+ import omit from 'lodash/omit'
3
+ import { AuthenticationBase, ConnectionEvent } from '../core'
4
4
 
5
5
  export default (event: ConnectionEvent) => async (context: HookContext, next: NextFunction) => {
6
- await next();
6
+ await next()
7
7
 
8
- const { result, params: { connection } } = context;
8
+ const {
9
+ result,
10
+ params: { connection }
11
+ } = context
9
12
 
10
13
  if (connection) {
11
- const service = context.service as unknown as AuthenticationBase;
14
+ const service = context.service as unknown as AuthenticationBase
12
15
 
13
- Object.assign(connection, omit(result, 'accessToken', 'authentication'));
16
+ Object.assign(connection, omit(result, 'accessToken', 'authentication'))
14
17
 
15
- await service.handleConnection(event, connection, result);
18
+ await service.handleConnection(event, connection, result)
16
19
  }
17
- };
20
+ }
@@ -1,16 +1,16 @@
1
- import { HookContext, NextFunction } from '@feathersjs/feathers';
2
- import { createDebug } from '@feathersjs/commons';
3
- import { ConnectionEvent } from '../core';
1
+ import { HookContext, NextFunction } from '@feathersjs/feathers'
2
+ import { createDebug } from '@feathersjs/commons'
3
+ import { ConnectionEvent } from '../core'
4
4
 
5
- const debug = createDebug('@feathersjs/authentication/hooks/connection');
5
+ const debug = createDebug('@feathersjs/authentication/hooks/connection')
6
6
 
7
7
  export default (event: ConnectionEvent) => async (context: HookContext, next: NextFunction) => {
8
- await next();
8
+ await next()
9
9
 
10
- const { app, result, params } = context;
10
+ const { app, result, params } = context
11
11
 
12
12
  if (params.provider && result) {
13
- debug(`Sending authentication event '${event}'`);
14
- app.emit(event, result, params, context);
13
+ debug(`Sending authentication event '${event}'`)
14
+ app.emit(event, result, params, context)
15
15
  }
16
- };
16
+ }
@@ -1,3 +1,3 @@
1
- export { default as authenticate } from './authenticate';
2
- export { default as connection } from './connection';
3
- export { default as event } from './event';
1
+ export { default as authenticate } from './authenticate'
2
+ export { default as connection } from './connection'
3
+ export { default as event } from './event'
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * as hooks from './hooks';
2
- export { authenticate } from './hooks';
1
+ export * as hooks from './hooks'
2
+ export { authenticate } from './hooks'
3
3
  export {
4
4
  AuthenticationBase,
5
5
  AuthenticationRequest,
@@ -7,8 +7,8 @@ export {
7
7
  AuthenticationStrategy,
8
8
  AuthenticationParams,
9
9
  ConnectionEvent
10
- } from './core';
11
- export { AuthenticationBaseStrategy } from './strategy';
12
- export { AuthenticationService } from './service';
13
- export { JWTStrategy } from './jwt';
14
- export { authenticationSettingsSchema } from './options';
10
+ } from './core'
11
+ export { AuthenticationBaseStrategy } from './strategy'
12
+ export { AuthenticationService } from './service'
13
+ export { JWTStrategy } from './jwt'
14
+ export { authenticationSettingsSchema } from './options'