diff --git a/packages/authentication-client/src/core.ts b/packages/authentication-client/src/core.ts index effec73b8f..59cd8fdd63 100644 --- a/packages/authentication-client/src/core.ts +++ b/packages/authentication-client/src/core.ts @@ -149,7 +149,7 @@ export class AuthenticationClient { return authPromise; } - authenticate (authentication: AuthenticationRequest, params?: Params): Promise { + authenticate (authentication?: AuthenticationRequest, params?: Params): Promise { if (!authentication) { return this.reAuthenticate(); } @@ -172,7 +172,7 @@ export class AuthenticationClient { return promise; } - logout () { + logout (): Promise { return Promise.resolve(this.app.get('authentication')) .then(() => this.service.remove(null) .then((authResult: AuthenticationResult) => this.removeAccessToken() diff --git a/packages/authentication-client/src/index.ts b/packages/authentication-client/src/index.ts index f6650418da..1f47ba6ef8 100644 --- a/packages/authentication-client/src/index.ts +++ b/packages/authentication-client/src/index.ts @@ -1,7 +1,6 @@ import { AuthenticationClient, AuthenticationClientOptions } from './core'; import * as hooks from './hooks'; import { Application } from '@feathersjs/feathers'; -import { AuthenticationResult, AuthenticationRequest } from '@feathersjs/authentication'; import { Storage, MemoryStorage, StorageWrapper } from './storage'; declare module '@feathersjs/feathers' { @@ -10,9 +9,9 @@ declare module '@feathersjs/feathers' { rest?: any; primus?: any; authentication: AuthenticationClient; - authenticate (authentication?: AuthenticationRequest): Promise; - reAuthenticate (force: boolean): Promise; - logout (): Promise; + authenticate: AuthenticationClient['authenticate']; + reAuthenticate: AuthenticationClient['reAuthenticate']; + logout: AuthenticationClient['logout']; } } diff --git a/packages/authentication/src/core.ts b/packages/authentication/src/core.ts index 49537d5b14..6811b5b9b3 100644 --- a/packages/authentication/src/core.ts +++ b/packages/authentication/src/core.ts @@ -21,7 +21,7 @@ export interface AuthenticationRequest { [key: string]: any; } -export type ConnectionEvent = 'login'|'logout'|'disconnect'; +export type ConnectionEvent = 'login' | 'logout' | 'disconnect'; export interface AuthenticationStrategy { /** @@ -63,11 +63,11 @@ export interface AuthenticationStrategy { * @param req The HTTP request * @param res The HTTP response */ - parse? (req: IncomingMessage, res: ServerResponse): Promise; + parse? (req: IncomingMessage, res: ServerResponse): Promise; } export interface JwtVerifyOptions extends VerifyOptions { - algorithm?: string|string[]; + algorithm?: string | string[]; } /** diff --git a/packages/authentication/src/hooks/authenticate.ts b/packages/authentication/src/hooks/authenticate.ts index b60cb45275..4ebe639760 100644 --- a/packages/authentication/src/hooks/authenticate.ts +++ b/packages/authentication/src/hooks/authenticate.ts @@ -10,7 +10,7 @@ export interface AuthenticateHookSettings { strategies: string[]; } -export default (originalSettings: string|AuthenticateHookSettings, ...originalStrategies: string[]) => { +export default (originalSettings: string | AuthenticateHookSettings, ...originalStrategies: string[]) => { const settings = typeof originalSettings === 'string' ? { strategies: flatten([ originalSettings, ...originalStrategies ]) } : originalSettings; @@ -54,7 +54,7 @@ export default (originalSettings: string|AuthenticateHookSettings, ...originalSt context.params = merge({}, params, omit(authResult, 'accessToken'), { authenticated: true }); return context; - } else if (!authentication && provider) { + } else if (provider) { throw new NotAuthenticated('Not authenticated'); } diff --git a/packages/authentication/src/jwt.ts b/packages/authentication/src/jwt.ts index 4fda2f9a68..9f114d043c 100644 --- a/packages/authentication/src/jwt.ts +++ b/packages/authentication/src/jwt.ts @@ -44,6 +44,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy { const timer = lt.setTimeout(() => this.app.emit('disconnect', connection), duration); debug(`Registering connection expiration timer for ${duration}ms`); + lt.clearTimeout(this.expirationTimers.get(connection)); this.expirationTimers.set(connection, timer); debug('Adding authentication information to connection'); @@ -56,6 +57,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy { delete connection.authentication; lt.clearTimeout(this.expirationTimers.get(connection)); + this.expirationTimers.delete(connection); } } @@ -128,8 +130,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy { } async parse (req: IncomingMessage) { - const result = { strategy: this.name }; - const { header, schemes }: { header: any, schemes: string[] } = this.configuration; + const { header, schemes }: { header: string, schemes: string[] } = this.configuration; const headerValue = req.headers && req.headers[header.toLowerCase()]; if (!headerValue || typeof headerValue !== 'string') { @@ -138,7 +139,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy { debug('Found parsed header value'); - const [ , scheme = null, schemeValue = null ] = headerValue.match(SPLIT_HEADER) || []; + const [ , scheme, schemeValue ] = headerValue.match(SPLIT_HEADER) || []; const hasScheme = scheme && schemes.some( current => new RegExp(current, 'i').test(scheme) ); @@ -148,7 +149,7 @@ export class JWTStrategy extends AuthenticationBaseStrategy { } return { - ...result, + strategy: this.name, accessToken: hasScheme ? schemeValue : headerValue }; } diff --git a/packages/authentication/src/service.ts b/packages/authentication/src/service.ts index d6261be64e..d2df469af4 100644 --- a/packages/authentication/src/service.ts +++ b/packages/authentication/src/service.ts @@ -114,7 +114,7 @@ export class AuthenticationService extends AuthenticationBase implements Partial * @param id The JWT to remove or null * @param params Service call parameters */ - async remove (id: null|string, params: Params) { + async remove (id: string | null, params: Params) { const { authentication } = params; const { authStrategies } = this.configuration; @@ -131,11 +131,10 @@ export class AuthenticationService extends AuthenticationBase implements Partial /** * Validates the service configuration. */ - setup () { + setup (this: AuthenticationService & ServiceAddons) { // The setup method checks for valid settings and registers the // connection and event (login, logout) hooks const { secret, service, entity, entityId } = this.configuration; - const self = this as unknown as ServiceAddons; if (typeof secret !== 'string') { throw new Error(`A 'secret' must be provided in your authentication configuration`); @@ -155,15 +154,19 @@ export class AuthenticationService extends AuthenticationBase implements Partial } } - self.hooks({ + this.hooks({ after: { create: [ connection('login'), event('login') ], remove: [ connection('logout'), event('logout') ] } }); - if (typeof self.publish === 'function') { - self.publish(() => null); + this.app.on('disconnect', async (connection) => { + await this.handleConnection('disconnect', connection); + }); + + if (typeof this.publish === 'function') { + this.publish(() => null); } } } diff --git a/packages/authentication/test/jwt.test.ts b/packages/authentication/test/jwt.test.ts index f78f7ad359..728e4e52f6 100644 --- a/packages/authentication/test/jwt.test.ts +++ b/packages/authentication/test/jwt.test.ts @@ -127,6 +127,8 @@ describe('authentication/jwt', () => { const disconnection = await new Promise(resolve => app.once('disconnect', resolve)); assert.strictEqual(disconnection, connection); + + assert.ok(!connection.authentication); }); it('deletes authentication information on remove', async () => {