Add github as an auth provider to the backend

This commit is contained in:
Marcus Eide
2020-05-29 15:16:10 +02:00
parent 2112095487
commit 7a665c3c2b
6 changed files with 137 additions and 21 deletions
+8 -6
View File
@@ -16,21 +16,23 @@
},
"dependencies": {
"@backstage/backend-common": "^0.1.1-alpha.6",
"@types/cookie-parser": "^1.4.2",
"@types/passport": "^1.0.3",
"@types/passport-github2": "^1.2.4",
"@types/passport-google-oauth20": "^2.0.3",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-promise-router": "^3.0.3",
"fs-extra": "^9.0.0",
"helmet": "^3.22.0",
"morgan": "^1.10.0",
"winston": "^3.2.1",
"yn": "^4.0.0",
"passport": "^0.4.1",
"passport-github2": "^0.1.12",
"passport-google-oauth20": "^2.0.0",
"cookie-parser": "^1.4.5",
"@types/passport": "^1.0.3",
"@types/passport-google-oauth20": "^2.0.3",
"@types/cookie-parser": "^1.4.2"
"winston": "^3.2.1",
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.6",
@@ -23,4 +23,12 @@ export const providers = [
callbackURL: 'http://localhost:7000/auth/google/handler/frame',
},
},
{
provider: 'github',
options: {
clientID: process.env.AUTH_GITHUB_CLIENT_ID!,
clientSecret: process.env.AUTH_GITHUB_CLIENT_SECRET!,
callbackURL: 'http://localhost:7000/auth/github/handler/frame',
},
},
];
@@ -16,10 +16,12 @@
import { AuthProviderFactories, AuthProviderFactory } from './types';
import { GoogleAuthProvider } from './google';
import { GithubAuthProvider } from './github';
export class ProviderFactories {
private static readonly providerFactories: AuthProviderFactories = {
google: GoogleAuthProvider,
github: GithubAuthProvider,
};
public static getProviderFactory(providerId: string): AuthProviderFactory {
@@ -0,0 +1,17 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { GithubAuthProvider } from './provider';
@@ -0,0 +1,84 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import express from 'express';
import { Strategy as GithubStrategy } from 'passport-github2';
import {
executeFrameHandlerStrategy,
executeRedirectStrategy,
executeRefreshTokenStrategy,
} from '../PassportStrategyHelper';
import {
OAuthProviderHandlers,
AuthProviderConfig,
RedirectInfo,
AuthInfoBase,
AuthInfoPrivate,
} from '../types';
export class GithubAuthProvider implements OAuthProviderHandlers {
private readonly providerConfig: AuthProviderConfig;
private readonly _strategy: GithubStrategy;
constructor(providerConfig: AuthProviderConfig) {
this.providerConfig = providerConfig;
this._strategy = new GithubStrategy(
{ ...this.providerConfig.options },
(
accessToken: any,
refreshToken: any,
params: any,
profile: any,
done: any,
) => {
done(
undefined,
{
profile,
accessToken,
scope: 'user', // params.scope is an empty string here for some reason, so hardcoding for now
expiresInSeconds: params.expires_in,
},
{ refreshToken },
);
},
);
}
async start(req: express.Request, options: any): Promise<RedirectInfo> {
return await executeRedirectStrategy(req, this._strategy, options);
}
async handler(
req: express.Request,
): Promise<{ user: AuthInfoBase; info: AuthInfoPrivate }> {
return await executeFrameHandlerStrategy(req, this._strategy);
}
async refresh(refreshToken: string, scope: string): Promise<AuthInfoBase> {
const { accessToken, params } = await executeRefreshTokenStrategy(
this._strategy,
refreshToken,
scope,
);
return {
accessToken,
expiresInSeconds: params.expires_in,
scope: params.scope,
};
}
}