From 86930c9dd2061381567c5b14564ae4e75ba6bb80 Mon Sep 17 00:00:00 2001 From: Marcus Eide Date: Mon, 1 Jun 2020 12:09:05 +0200 Subject: [PATCH] Support providers without refresh tokens --- .../src/providers/OAuthProvider.ts | 36 +++++++++++++------ plugins/auth-backend/src/providers/config.ts | 1 + .../auth-backend/src/providers/factories.ts | 20 +++++++++-- plugins/auth-backend/src/providers/index.ts | 6 +--- plugins/auth-backend/src/providers/types.ts | 3 +- 5 files changed, 47 insertions(+), 19 deletions(-) diff --git a/plugins/auth-backend/src/providers/OAuthProvider.ts b/plugins/auth-backend/src/providers/OAuthProvider.ts index 81f5ed25a6..30fd60f51f 100644 --- a/plugins/auth-backend/src/providers/OAuthProvider.ts +++ b/plugins/auth-backend/src/providers/OAuthProvider.ts @@ -89,9 +89,15 @@ export const removeRefreshTokenCookie = ( export class OAuthProvider implements AuthProviderRouteHandlers { private readonly provider: string; private readonly providerHandlers: OAuthProviderHandlers; - constructor(providerHandlers: OAuthProviderHandlers, provider: string) { + private readonly disableRefresh: boolean; + constructor( + providerHandlers: OAuthProviderHandlers, + provider: string, + disableRefresh?: boolean, + ) { this.provider = provider; this.providerHandlers = providerHandlers; + this.disableRefresh = disableRefresh ?? false; } async start(req: express.Request, res: express.Response): Promise { @@ -129,14 +135,16 @@ export class OAuthProvider implements AuthProviderRouteHandlers { const { user, info } = await this.providerHandlers.handler(req); - // throw error if missing refresh token - const { refreshToken } = info; - if (!refreshToken) { - throw new Error('Missing refresh token'); - } + if (!this.disableRefresh) { + // throw error if missing refresh token + const { refreshToken } = info; + if (!refreshToken) { + throw new Error('Missing refresh token'); + } - // set new refresh token - setRefreshTokenCookie(res, this.provider, refreshToken); + // set new refresh token + setRefreshTokenCookie(res, this.provider, refreshToken); + } // post message back to popup if successful return postMessageResponse(res, { @@ -160,8 +168,10 @@ export class OAuthProvider implements AuthProviderRouteHandlers { return res.status(401).send('Invalid X-Requested-With header'); } - // remove refresh token cookie before logout - removeRefreshTokenCookie(res, this.provider); + if (!this.disableRefresh) { + // remove refresh token cookie before logout + removeRefreshTokenCookie(res, this.provider); + } return res.send('logout!'); } @@ -170,6 +180,12 @@ export class OAuthProvider implements AuthProviderRouteHandlers { return res.status(401).send('Invalid X-Requested-With header'); } + if (!this.providerHandlers.refresh || this.disableRefresh) { + return res.send( + `Refresh token not supported for provider: ${this.provider}`, + ); + } + try { const refreshToken = req.cookies[`${this.provider}-refresh-token`]; diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts index dad87e0448..8d04dc5a1f 100644 --- a/plugins/auth-backend/src/providers/config.ts +++ b/plugins/auth-backend/src/providers/config.ts @@ -30,5 +30,6 @@ export const providers = [ clientSecret: process.env.AUTH_GITHUB_CLIENT_SECRET!, callbackURL: 'http://localhost:7000/auth/github/handler/frame', }, + disableRefresh: true, }, ]; diff --git a/plugins/auth-backend/src/providers/factories.ts b/plugins/auth-backend/src/providers/factories.ts index 10e4153714..0c9f99e878 100644 --- a/plugins/auth-backend/src/providers/factories.ts +++ b/plugins/auth-backend/src/providers/factories.ts @@ -14,9 +14,14 @@ * limitations under the License. */ -import { AuthProviderFactories, AuthProviderFactory } from './types'; +import { + AuthProviderFactories, + AuthProviderRouteHandlers, + AuthProviderConfig, +} from './types'; import { GoogleAuthProvider } from './google'; import { GithubAuthProvider } from './github'; +import { OAuthProvider } from './OAuthProvider'; export class ProviderFactories { private static readonly providerFactories: AuthProviderFactories = { @@ -24,13 +29,22 @@ export class ProviderFactories { github: GithubAuthProvider, }; - public static getProviderFactory(providerId: string): AuthProviderFactory { + public static getProviderFactory( + config: AuthProviderConfig, + ): AuthProviderRouteHandlers { + const providerId = config.provider; const ProviderImpl = ProviderFactories.providerFactories[providerId]; if (!ProviderImpl) { throw Error( `Provider Implementation missing for : ${providerId} auth provider`, ); } - return ProviderImpl; + const providerInstance = new ProviderImpl(config); + const oauthProvider = new OAuthProvider( + providerInstance, + providerId, + config.disableRefresh, + ); + return oauthProvider; } } diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 59dd116fa6..cfbabbbad1 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -17,7 +17,6 @@ import Router from 'express-promise-router'; import { AuthProviderRouteHandlers, AuthProviderConfig } from './types'; import { ProviderFactories } from './factories'; -import { OAuthProvider } from './OAuthProvider'; export const defaultRouter = (provider: AuthProviderRouteHandlers) => { const router = Router(); @@ -32,10 +31,7 @@ export const defaultRouter = (provider: AuthProviderRouteHandlers) => { export const makeProvider = (config: AuthProviderConfig) => { const providerId = config.provider; - const ProviderImpl = ProviderFactories.getProviderFactory(providerId); - const providerInstance = new ProviderImpl(config); - - const oauthProvider = new OAuthProvider(providerInstance, providerId); + const oauthProvider = ProviderFactories.getProviderFactory(config); const providerRouter = defaultRouter(oauthProvider); return { providerId, providerRouter }; }; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index dcbe6ad1de..dc83c19dd0 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -20,12 +20,13 @@ import passport from 'passport'; export type AuthProviderConfig = { provider: string; options: any; + disableRefresh?: boolean; }; export interface OAuthProviderHandlers { start(req: express.Request, options: any): Promise; handler(req: express.Request): Promise; - refresh(refreshToken: string, scope: string): Promise; + refresh?(refreshToken: string, scope: string): Promise; logout?(): Promise; }