@feathersjs/authentication 5.0.0-pre.2 → 5.0.0-pre.20

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.
@@ -1,14 +1,14 @@
1
1
  import flatten from 'lodash/flatten';
2
2
  import omit from 'lodash/omit';
3
- import { HookContext } from '@feathersjs/feathers';
3
+ import { HookContext, NextFunction } from '@feathersjs/feathers';
4
4
  import { NotAuthenticated } from '@feathersjs/errors';
5
- import Debug from 'debug';
5
+ import { createDebug } from '@feathersjs/commons';
6
6
 
7
- const debug = Debug('@feathersjs/authentication/hooks/authenticate');
7
+ const debug = createDebug('@feathersjs/authentication/hooks/authenticate');
8
8
 
9
9
  export interface AuthenticateHookSettings {
10
10
  service?: string;
11
- strategies: string[];
11
+ strategies?: string[];
12
12
  }
13
13
 
14
14
  export default (originalSettings: string | AuthenticateHookSettings, ...originalStrategies: string[]) => {
@@ -20,7 +20,8 @@ export default (originalSettings: string | AuthenticateHookSettings, ...original
20
20
  throw new Error('The authenticate hook needs at least one allowed strategy');
21
21
  }
22
22
 
23
- return async (context: HookContext<any, any>) => {
23
+ return async (context: HookContext, _next?: NextFunction) => {
24
+ const next = typeof _next === 'function' ? _next : async () => context;
24
25
  const { app, params, type, path, service } = context;
25
26
  const { strategies } = settings;
26
27
  const { provider, authentication } = params;
@@ -42,7 +43,7 @@ export default (originalSettings: string | AuthenticateHookSettings, ...original
42
43
  }
43
44
 
44
45
  if (params.authenticated === true) {
45
- return context;
46
+ return next();
46
47
  }
47
48
 
48
49
  if (authentication) {
@@ -53,12 +54,10 @@ export default (originalSettings: string | AuthenticateHookSettings, ...original
53
54
  const authResult = await authService.authenticate(authentication, authParams, ...strategies);
54
55
 
55
56
  context.params = Object.assign({}, params, omit(authResult, 'accessToken'), { authenticated: true });
56
-
57
- return context;
58
57
  } else if (provider) {
59
58
  throw new NotAuthenticated('Not authenticated');
60
59
  }
61
60
 
62
- return context;
61
+ return next();
63
62
  };
64
63
  };
@@ -1,19 +1,17 @@
1
- import { HookContext } from '@feathersjs/feathers';
1
+ import { HookContext, NextFunction } from '@feathersjs/feathers';
2
2
  import omit from 'lodash/omit';
3
3
  import { AuthenticationBase, ConnectionEvent } from '../core';
4
4
 
5
- export default (event: ConnectionEvent) => async (context: HookContext) => {
6
- const { result, params: { connection } } = context;
7
-
8
- if (!connection) {
9
- return context;
10
- }
5
+ export default (event: ConnectionEvent) => async (context: HookContext, next: NextFunction) => {
6
+ await next();
11
7
 
12
- const service = context.service as unknown as AuthenticationBase;
8
+ const { result, params: { connection } } = context;
13
9
 
14
- Object.assign(connection, omit(result, 'accessToken', 'authentication'));
10
+ if (connection) {
11
+ const service = context.service as unknown as AuthenticationBase;
15
12
 
16
- await service.handleConnection(event, connection, result);
13
+ Object.assign(connection, omit(result, 'accessToken', 'authentication'));
17
14
 
18
- return context;
15
+ await service.handleConnection(event, connection, result);
16
+ }
19
17
  };
@@ -1,16 +1,16 @@
1
- import Debug from 'debug';
2
- import { HookContext } from '@feathersjs/feathers';
1
+ import { HookContext, NextFunction } from '@feathersjs/feathers';
2
+ import { createDebug } from '@feathersjs/commons';
3
3
  import { ConnectionEvent } from '../core';
4
4
 
5
- const debug = Debug('@feathersjs/authentication/hooks/connection');
5
+ const debug = createDebug('@feathersjs/authentication/hooks/connection');
6
+
7
+ export default (event: ConnectionEvent) => async (context: HookContext, next: NextFunction) => {
8
+ await next();
6
9
 
7
- export default (event: ConnectionEvent) => async (context: HookContext) => {
8
10
  const { app, result, params } = context;
9
11
 
10
12
  if (params.provider && result) {
11
13
  debug(`Sending authentication event '${event}'`);
12
14
  app.emit(event, result, params, context);
13
15
  }
14
-
15
- return context;
16
16
  };
package/src/index.ts CHANGED
@@ -1,16 +1,14 @@
1
- import * as hooks from './hooks';
2
-
3
- const { authenticate } = hooks;
4
-
5
- export { hooks };
6
- export { authenticate };
1
+ export * as hooks from './hooks';
2
+ export { authenticate } from './hooks';
7
3
  export {
8
4
  AuthenticationBase,
9
5
  AuthenticationRequest,
10
6
  AuthenticationResult,
11
7
  AuthenticationStrategy,
8
+ AuthenticationParams,
12
9
  ConnectionEvent
13
10
  } from './core';
14
11
  export { AuthenticationBaseStrategy } from './strategy';
15
12
  export { AuthenticationService } from './service';
16
13
  export { JWTStrategy } from './jwt';
14
+ export { authenticationSettingsSchema } from './options';
package/src/jwt.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import Debug from 'debug';
3
2
  import omit from 'lodash/omit';
4
3
  import { IncomingMessage } from 'http';
5
4
  import { NotAuthenticated } from '@feathersjs/errors';
6
5
  import { Params } from '@feathersjs/feathers';
6
+ import { createDebug } from '@feathersjs/commons';
7
7
  // @ts-ignore
8
8
  import lt from 'long-timeout';
9
9
 
10
10
  import { AuthenticationBaseStrategy } from './strategy';
11
- import { AuthenticationRequest, AuthenticationResult, ConnectionEvent } from './core';
11
+ import { AuthenticationParams, AuthenticationRequest, AuthenticationResult, ConnectionEvent } from './core';
12
12
 
13
- const debug = Debug('@feathersjs/authentication/jwt');
13
+ const debug = createDebug('@feathersjs/authentication/jwt');
14
14
  const SPLIT_HEADER = /(\S+)\s+(\S+)/;
15
15
 
16
16
  export class JWTStrategy extends AuthenticationBaseStrategy {
@@ -116,7 +116,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy {
116
116
  return authResult.authentication.payload.sub;
117
117
  }
118
118
 
119
- async authenticate (authentication: AuthenticationRequest, params: Params) {
119
+ async authenticate (authentication: AuthenticationRequest, params: AuthenticationParams) {
120
120
  const { accessToken } = authentication;
121
121
  const { entity } = this.configuration;
122
122
 
@@ -147,7 +147,10 @@ export class JWTStrategy extends AuthenticationBaseStrategy {
147
147
  };
148
148
  }
149
149
 
150
- async parse (req: IncomingMessage) {
150
+ async parse (req: IncomingMessage): Promise<{
151
+ strategy: string;
152
+ accessToken: string;
153
+ } | null> {
151
154
  const { header, schemes }: { header: string, schemes: string[] } = this.configuration;
152
155
  const headerValue = req.headers && req.headers[header.toLowerCase()];
153
156
 
package/src/options.ts CHANGED
@@ -1,5 +1,5 @@
1
- export default {
2
- authStrategies: [],
1
+ export const defaultOptions = {
2
+ authStrategies: [] as string[],
3
3
  jwtOptions: {
4
4
  header: { typ: 'access' }, // by default is an access token but can be any type
5
5
  audience: 'https://yourdomain.com', // The resource server where the token is processed
@@ -8,3 +8,108 @@ export default {
8
8
  expiresIn: '1d'
9
9
  }
10
10
  };
11
+
12
+ export const authenticationSettingsSchema = {
13
+ type: 'object',
14
+ required: ['secret', 'entity', 'authStrategies'],
15
+ properties: {
16
+ secret: {
17
+ type: 'string',
18
+ description: 'The JWT signing secret'
19
+ },
20
+ entity: {
21
+ oneOf: [{
22
+ type: 'null'
23
+ }, {
24
+ type: 'string'
25
+ }],
26
+ description: 'The name of the authentication entity (e.g. user)'
27
+ },
28
+ entityId: {
29
+ type: 'string',
30
+ description: 'The name of the authentication entity id property'
31
+ },
32
+ service: {
33
+ type: 'string',
34
+ description: 'The path of the entity service'
35
+ },
36
+ authStrategies: {
37
+ type: 'array',
38
+ items: { type: 'string' },
39
+ description: 'A list of authentication strategy names that are allowed to create JWT access tokens'
40
+ },
41
+ parseStrategies: {
42
+ type: 'array',
43
+ items: { type: 'string' },
44
+ description: 'A list of authentication strategy names that should parse HTTP headers for authentication information (defaults to `authStrategies`)'
45
+ },
46
+ jwtOptions: {
47
+ type: 'object'
48
+ },
49
+ jwt: {
50
+ type: 'object',
51
+ properties: {
52
+ header: {
53
+ type: 'string',
54
+ default: 'Authorization',
55
+ description: 'The HTTP header containing the JWT'
56
+ },
57
+ schemes: {
58
+ type: 'array',
59
+ items: { type: 'string' },
60
+ description: 'An array of schemes to support'
61
+ }
62
+ }
63
+ },
64
+ local: {
65
+ type: 'object',
66
+ required: ['usernameField', 'passwordField'],
67
+ properties: {
68
+ usernameField: {
69
+ type: 'string',
70
+ description: 'Name of the username field (e.g. `email`)'
71
+ },
72
+ passwordField: {
73
+ type: 'string',
74
+ description: 'Name of the password field (e.g. `password`)'
75
+ },
76
+ hashSize: {
77
+ type: 'number',
78
+ description: 'The BCrypt salt length'
79
+ },
80
+ errorMessage: {
81
+ type: 'string',
82
+ default: 'Invalid login',
83
+ description: 'The error message to return on errors'
84
+ },
85
+ entityUsernameField: {
86
+ type: 'string',
87
+ description: 'Name of the username field on the entity if authentication request data and entity field names are different'
88
+ },
89
+ entityPasswordField: {
90
+ type: 'string',
91
+ description: 'Name of the password field on the entity if authentication request data and entity field names are different'
92
+ }
93
+ }
94
+ },
95
+ oauth: {
96
+ type: 'object',
97
+ properties: {
98
+ redirect: {
99
+ type: 'string'
100
+ },
101
+ origins: {
102
+ type: 'array',
103
+ items: { type: 'string' }
104
+ },
105
+ defaults: {
106
+ type: 'object',
107
+ properties: {
108
+ key: { type: 'string' },
109
+ secret: { type: 'string' }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ } as const;
package/src/service.ts CHANGED
@@ -1,16 +1,16 @@
1
- import Debug from 'debug';
2
1
  import merge from 'lodash/merge';
3
2
  import { NotAuthenticated } from '@feathersjs/errors';
4
- import { AuthenticationBase, AuthenticationResult, AuthenticationRequest } from './core';
3
+ import { AuthenticationBase, AuthenticationResult, AuthenticationRequest, AuthenticationParams } from './core';
5
4
  import { connection, event } from './hooks';
6
5
  import '@feathersjs/transport-commons';
7
- import { Params, ServiceMethods, ServiceAddons } from '@feathersjs/feathers';
6
+ import { createDebug } from '@feathersjs/commons';
7
+ import { ServiceMethods, ServiceAddons } from '@feathersjs/feathers';
8
8
  import jsonwebtoken from 'jsonwebtoken';
9
9
 
10
- const debug = Debug('@feathersjs/authentication/service');
10
+ const debug = createDebug('@feathersjs/authentication/service');
11
11
 
12
12
  declare module '@feathersjs/feathers/lib/declarations' {
13
- interface FeathersApplication<ServiceTypes, AppSettings> { // eslint-disable-line
13
+ interface FeathersApplication<Services, Settings> { // eslint-disable-line
14
14
  /**
15
15
  * Returns the default authentication service or the
16
16
  * authentication service for a given path.
@@ -29,7 +29,7 @@ declare module '@feathersjs/feathers/lib/declarations' {
29
29
  // eslint-disable-next-line
30
30
  export interface AuthenticationService extends ServiceAddons<AuthenticationResult, AuthenticationResult> {}
31
31
 
32
- export class AuthenticationService extends AuthenticationBase implements Partial<ServiceMethods<AuthenticationResult>> {
32
+ export class AuthenticationService extends AuthenticationBase implements Partial<ServiceMethods<AuthenticationResult, AuthenticationRequest, AuthenticationParams>> {
33
33
  constructor (app: any, configKey = 'authentication', options = {}) {
34
34
  super(app, configKey, options);
35
35
 
@@ -51,7 +51,7 @@ export class AuthenticationService extends AuthenticationBase implements Partial
51
51
  * @param _authResult The current authentication result
52
52
  * @param params The service call parameters
53
53
  */
54
- async getPayload (_authResult: AuthenticationResult, params: Params) {
54
+ async getPayload (_authResult: AuthenticationResult, params: AuthenticationParams) {
55
55
  // Uses `params.payload` or returns an empty payload
56
56
  const { payload = {} } = params;
57
57
 
@@ -65,7 +65,7 @@ export class AuthenticationService extends AuthenticationBase implements Partial
65
65
  * @param authResult The authentication result
66
66
  * @param params Service call parameters
67
67
  */
68
- async getTokenOptions (authResult: AuthenticationResult, params: Params) {
68
+ async getTokenOptions (authResult: AuthenticationResult, params: AuthenticationParams) {
69
69
  const { service, entity, entityId } = this.configuration;
70
70
  const jwtOptions = merge({}, params.jwtOptions, params.jwt);
71
71
  const value = service && entity && authResult[entity];
@@ -92,7 +92,7 @@ export class AuthenticationService extends AuthenticationBase implements Partial
92
92
  * @param data The authentication request (should include `strategy` key)
93
93
  * @param params Service call parameters
94
94
  */
95
- async create (data: AuthenticationRequest, params?: Params) {
95
+ async create (data: AuthenticationRequest, params?: AuthenticationParams) {
96
96
  const authStrategies = params.authStrategies || this.configuration.authStrategies;
97
97
 
98
98
  if (!authStrategies.length) {
@@ -131,7 +131,7 @@ export class AuthenticationService extends AuthenticationBase implements Partial
131
131
  * @param id The JWT to remove or null
132
132
  * @param params Service call parameters
133
133
  */
134
- async remove (id: string | null, params?: Params) {
134
+ async remove (id: string | null, params?: AuthenticationParams) {
135
135
  const { authentication } = params;
136
136
  const { authStrategies } = this.configuration;
137
137
 
@@ -149,6 +149,8 @@ export class AuthenticationService extends AuthenticationBase implements Partial
149
149
  * Validates the service configuration.
150
150
  */
151
151
  async setup () {
152
+ await super.setup();
153
+
152
154
  // The setup method checks for valid settings and registers the
153
155
  // connection and event (login, logout) hooks
154
156
  const { secret, service, entity, entityId } = this.configuration;
@@ -172,10 +174,8 @@ export class AuthenticationService extends AuthenticationBase implements Partial
172
174
  }
173
175
 
174
176
  (this as any).hooks({
175
- after: {
176
- create: [ connection('login'), event('login') ],
177
- remove: [ connection('logout'), event('logout') ]
178
- }
177
+ create: [ connection('login'), event('login') ],
178
+ remove: [ connection('logout'), event('logout') ]
179
179
  });
180
180
 
181
181
  this.app.on('disconnect', async (connection) => {
package/src/strategy.ts CHANGED
@@ -22,7 +22,7 @@ export class AuthenticationBaseStrategy implements AuthenticationStrategy {
22
22
  return this.authentication.configuration[this.name];
23
23
  }
24
24
 
25
- get entityService (): Service<any> {
25
+ get entityService (): Service {
26
26
  const { service } = this.configuration;
27
27
 
28
28
  if (!service) {