Support providers without refresh tokens
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user