Call logout OAuth handler in OAuthAdapter

Signed-off-by: Alessandro Dalfovo <dalfovo.alessandro@gmail.com>
This commit is contained in:
Alessandro Dalfovo
2022-09-13 16:27:30 +02:00
committed by Francesco Saltori
parent c3e68fe249
commit 7289b5ec4e
5 changed files with 36 additions and 5 deletions
@@ -17,7 +17,7 @@
import express from 'express';
import { THOUSAND_DAYS_MS, TEN_MINUTES_MS, OAuthAdapter } from './OAuthAdapter';
import { encodeState } from './helpers';
import { OAuthHandlers, OAuthState } from './types';
import { OAuthHandlers, OAuthLogoutRequest, OAuthState } from './types';
import { CookieConfigurer } from '../../providers/types';
const mockResponseData = {
@@ -60,6 +60,7 @@ describe('OAuthAdapter', () => {
refreshToken: 'token',
};
}
async logout(_: OAuthLogoutRequest) {}
}
const providerInstance = new MyAuthProvider();
const mockCookieConfig: ReturnType<CookieConfigurer> = {
@@ -262,13 +263,17 @@ describe('OAuthAdapter', () => {
);
});
it('removes refresh cookie when logging out', async () => {
it('removes refresh cookie and calls logout handler when logging out', async () => {
const logoutSpy = jest.spyOn(providerInstance, 'logout');
const oauthProvider = new OAuthAdapter(providerInstance, {
...oAuthProviderOptions,
isOriginAllowed: () => false,
});
const mockRequest = {
cookies: {
'test-provider-refresh-token': 'token',
},
header: () => 'XMLHttpRequest',
get: jest.fn(),
} as unknown as express.Request;
@@ -281,6 +286,7 @@ describe('OAuthAdapter', () => {
await oauthProvider.logout(mockRequest, mockResponse);
expect(mockRequest.get).toHaveBeenCalledTimes(1);
expect(logoutSpy).toHaveBeenCalledTimes(1);
expect(mockResponse.cookie).toHaveBeenCalledTimes(1);
expect(mockResponse.cookie).toHaveBeenCalledWith(
expect.stringContaining('test-provider-refresh-token'),
@@ -39,6 +39,7 @@ import {
OAuthStartRequest,
OAuthRefreshRequest,
OAuthState,
OAuthLogoutRequest,
} from './types';
import { prepareBackstageIdentityResponse } from '../../providers/prepareBackstageIdentityResponse';
@@ -190,6 +191,14 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
throw new AuthenticationError('Invalid X-Requested-With header');
}
if (this.handlers.logout) {
const refreshToken = this.getRefreshTokenFromCookie(req);
const revokeRequest: OAuthLogoutRequest = Object.assign(req, {
refreshToken,
});
await this.handlers.logout(revokeRequest);
}
// remove refresh token cookie if it is set
const origin = req.get('origin');
const cookieConfig = this.getCookieConfig(origin);
@@ -210,8 +219,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
}
try {
const refreshToken =
req.cookies[`${this.options.providerId}-refresh-token`];
const refreshToken = this.getRefreshTokenFromCookie(req);
// throw error if refresh token is missing in the request
if (!refreshToken) {
@@ -286,6 +294,10 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
});
};
private getRefreshTokenFromCookie = (req: express.Request) => {
return req.cookies[`${this.options.providerId}-refresh-token`];
};
private getGrantedScopeFromCookie = (req: express.Request) => {
return req.cookies[`${this.options.providerId}-granted-scope`];
};
@@ -26,5 +26,6 @@ export type {
OAuthState,
OAuthStartRequest,
OAuthRefreshRequest,
OAuthLogoutRequest,
OAuthResult,
} from './types';
+6 -1
View File
@@ -104,6 +104,11 @@ export type OAuthRefreshRequest = express.Request<{}> & {
refreshToken: string;
};
/** @public */
export type OAuthLogoutRequest = express.Request<{}> & {
refreshToken: string;
};
/**
* Any OAuth provider needs to implement this interface which has provider specific
* handlers for different methods to perform authentication, get access tokens,
@@ -136,5 +141,5 @@ export interface OAuthHandlers {
/**
* (Optional) Sign out of the auth provider.
*/
logout?(): Promise<void>;
logout?(req: OAuthLogoutRequest): Promise<void>;
}
@@ -16,6 +16,7 @@
import express from 'express';
import passport from 'passport';
import { OAuth2Client } from 'google-auth-library';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
import {
encodeState,
@@ -27,6 +28,7 @@ import {
OAuthResponse,
OAuthResult,
OAuthStartRequest,
OAuthLogoutRequest,
} from '../../lib/oauth';
import {
executeFetchUserProfileStrategy,
@@ -119,6 +121,11 @@ export class GoogleAuthProvider implements OAuthHandlers {
};
}
async logout(req: OAuthLogoutRequest) {
const oauthClient = new OAuth2Client();
await oauthClient.revokeToken(req.refreshToken);
}
async refresh(req: OAuthRefreshRequest) {
const { accessToken, refreshToken, params } =
await executeRefreshTokenStrategy(