Support providers without refresh tokens

This commit is contained in:
Marcus Eide
2020-06-01 12:09:05 +02:00
parent 438bdba2cf
commit 86930c9dd2
5 changed files with 47 additions and 19 deletions
@@ -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<any> {
@@ -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`];
@@ -30,5 +30,6 @@ export const providers = [
clientSecret: process.env.AUTH_GITHUB_CLIENT_SECRET!,
callbackURL: 'http://localhost:7000/auth/github/handler/frame',
},
disableRefresh: true,
},
];
@@ -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;
}
}
+1 -5
View File
@@ -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 };
};
+2 -1
View File
@@ -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<any>;
handler(req: express.Request): Promise<any>;
refresh(refreshToken: string, scope: string): Promise<any>;
refresh?(refreshToken: string, scope: string): Promise<any>;
logout?(): Promise<any>;
}