Remove github provider. Refactored Google provider to be a class

This commit is contained in:
Raghunandan
2020-05-19 14:20:46 +02:00
parent 79ace90811
commit 50658a166b
4 changed files with 89 additions and 92 deletions
@@ -1,22 +0,0 @@
import express from 'express';
import Router from 'express-promise-router';
export const router = Router();
router.get('/', async (_req: express.Request, res: express.Response) => {
res.send('initiate auth');
});
router.get('/login', async (_req: express.Request, res: express.Response) => {
res.send('github provider login');
});
router.get('/logout', async (_req: express.Request, res: express.Response) => {
res.send('github provider logout');
});
router.get(
'/handler/frame',
async (req: express.Request, res: express.Response) => {
res.send('github provider frame response handler');
},
);
@@ -1,13 +1,55 @@
import passport from 'passport';
import express from 'express';
import Router from 'express-promise-router';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
import { AuthProviderHandlers, AuthResponse } from './../types';
import {
AuthProvider,
AuthProviderRouteHandlers,
AuthResponse,
} from './../types';
export const provider = {
makeStrategy(options: any): passport.Strategy {
export class GoogleAuthProvider
implements AuthProvider, AuthProviderRouteHandlers {
providerConfig: any;
constructor(providerConfig: any) {
this.providerConfig = providerConfig;
}
start(
req: express.Request,
res: express.Response,
next: express.NextFunction,
) {
const scopes = req.query.scopes?.toString().split(',');
return passport.authenticate('google', {
scope: scopes,
accessType: 'offline',
prompt: 'consent',
})(req, res, next);
}
frameHandler(
req: express.Request,
res: express.Response,
next: express.NextFunction,
) {
return passport.authenticate('google', function (_, user) {
postMessageResponse(res, {
type: 'auth-result',
payload: user,
});
})(req, res, next);
}
logout(
req: express.Request,
res: express.Response,
next: express.NextFunction,
) {
return res.send('logout!');
}
strategy(): passport.Strategy {
return new GoogleStrategy(
{ ...options, passReqToCallback: true },
{ ...this.providerConfig.options, passReqToCallback: true },
function (
_req: any,
accessToken: any,
@@ -18,56 +60,8 @@ export const provider = {
cb(undefined, { profile, accessToken, refreshToken });
},
);
},
makeRouter(): express.Router {
return defaultRouter(GoogleAuthProviderHandler);
},
};
const defaultRouter = (handlers: AuthProviderHandlers) => {
const router = Router();
router.get('/start', handlers.start);
router.get('/handler/frame', handlers.handle);
router.get('/logout', handlers.logout);
if (handlers.refresh) {
router.get('/refreshToken', handlers.refresh);
}
return router;
};
// Make this a class
// add a getStrategy method
// pass the config as a new constructor
// class GoogleAuthProvider implements AuthProviderHandlers {
// config: any;
// constructor(config: any) {
// this.config = config;
// }
// }
export const GoogleAuthProviderHandler: AuthProviderHandlers = {
start(req, res, next) {
const scopes = req.query.scopes?.toString().split(',');
return passport.authenticate('google', {
scope: scopes,
accessType: 'offline',
prompt: 'consent',
})(req, res, next);
},
handle(req, res, next) {
return passport.authenticate('google', function (_, user) {
postMessageResponse(res, {
type: 'oauth-result',
payload: user,
});
})(req, res, next);
},
logout(_req, res, _next) {
return res.send('logout!');
},
};
}
const postMessageResponse = (res: express.Response, data: AuthResponse) => {
const jsonData = JSON.stringify(data);
+23 -6
View File
@@ -1,14 +1,31 @@
import { AuthProvider } from './types';
import { provider as GoogleAuthProvider } from './google/provider';
import Router from 'express-promise-router';
import { AuthProviderRouteHandlers, AuthProviderFactories } from './types';
const providerFactories: AuthProvider = {
import { GoogleAuthProvider } from './google/provider';
const providerFactories: AuthProviderFactories = {
google: GoogleAuthProvider,
};
export const makeProvider = (config: any) => {
const provider = config.provider;
const providerFactory = providerFactories[provider];
const strategy = providerFactory.makeStrategy(config.options);
const providerRouter = providerFactory.makeRouter();
const providerImpl = providerFactories[provider];
if (!providerImpl) {
throw Error(`Provider Implementation missing for provider: ${provider}`);
}
const providerInstance = new providerImpl(config);
const strategy = providerInstance.strategy();
const providerRouter = defaultRouter(providerInstance);
return { provider, strategy, providerRouter };
};
export const defaultRouter = (provider: AuthProviderRouteHandlers) => {
const router = Router();
router.get('/start', provider.start);
router.get('/handler/frame', provider.frameHandler);
router.get('/logout', provider.logout);
if (provider.refresh) {
router.get('/refreshToken', provider.refresh);
}
return router;
};
+18 -10
View File
@@ -1,13 +1,13 @@
import express from 'express';
import passport from 'passport';
export type AuthProviderHandlers = {
export interface AuthProviderRouteHandlers {
start(
req: express.Request,
res: express.Response,
next: express.NextFunction,
): Promise<any>;
handle(
frameHandler(
req: express.Request,
res: express.Response,
next: express.NextFunction,
@@ -22,12 +22,15 @@ export type AuthProviderHandlers = {
res: express.Response,
next: express.NextFunction,
): express.Response<any>;
};
}
export interface AuthProvider {
strategy(): passport.Strategy;
router?(): express.Router;
}
export type AuthProvider = {
export type AuthProviderFactories = {
[key: string]: {
makeStrategy(options: any): passport.Strategy;
makeRouter(): express.Router;
new (providerConfig: any): AuthProvider & AuthProviderRouteHandlers;
};
};
@@ -38,7 +41,12 @@ export type AuthInfo = {
expiresAt?: number;
};
export type AuthResponse = {
type: string;
payload: AuthInfo;
};
export type AuthResponse =
| {
type: 'auth-result';
payload: AuthInfo;
}
| {
type: 'auth-result';
error: Error | undefined;
};