Google Apps / GSuite authentication support
Supports using Google Authentication with a specific GSuite domain as opposed to using Azure Active Directory.
This commit is contained in:
Родитель
538e28989a
Коммит
21faa74775
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"clientId": "env://AUTH_GOOGLE_CLIENT_ID",
|
||||
"clientSecret": "env://AUTH_GOOGLE_CLIENT_SECRET",
|
||||
"domain": "env://AUTH_GOOGLE_DOMAIN",
|
||||
"redirectUrl": "env://AUTH_GOOGLE_REDIRECT_URL"
|
||||
}
|
|
@ -9,8 +9,7 @@ const passport = require('passport');
|
|||
const serializer = require('./passport/serializer');
|
||||
const GitHubStrategy = require('../thirdparty/passport-github').Strategy;
|
||||
const OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
|
||||
|
||||
// FYI: GitHub does not provide refresh tokens
|
||||
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
||||
|
||||
function githubResponseToSubset(accessToken, refreshToken, profile, done) {
|
||||
let subset = {
|
||||
|
@ -61,12 +60,29 @@ function activeDirectorySubset(iss, sub, profile, done) {
|
|||
|
||||
module.exports = function (app, config) {
|
||||
if (!config.authentication.scheme) {
|
||||
config.authentication.scheme = 'github';
|
||||
config.authentication.scheme = 'aad';
|
||||
}
|
||||
if (config.authentication.scheme !== 'github' && config.authentication.scheme !== 'aad') {
|
||||
if (config.authentication.scheme !== 'github'
|
||||
&& config.authentication.scheme !== 'aad'
|
||||
&& config.authentication.scheme !== 'google') {
|
||||
throw new Error(`Unsupported primary authentication scheme type "${config.authentication.scheme}"`);
|
||||
}
|
||||
|
||||
function googleSubset(accessToken, refreshToken, profile, callback) {
|
||||
const json = profile._json;
|
||||
let domain = json && json.domain ? json.domain : null;
|
||||
let expectedDomain = config.authentication.google && config.authentication.google.domain ? config.authentication.google.domain : null;
|
||||
if (!expectedDomain) {
|
||||
return callback(new Error('The Google Authentication provider must be configured with the expected Google Apps domain name. None has been configured.'));
|
||||
}
|
||||
if (domain !== expectedDomain) {
|
||||
return callback(new Error(`You must be a member of the ${expectedDomain} domain to use this app`));
|
||||
}
|
||||
|
||||
return callback(null, profile);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GitHub Passport session setup.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -79,6 +95,7 @@ module.exports = function (app, config) {
|
|||
userAgent: 'passport-azure-oss-portal-for-github' // CONSIDER: User agent should be configured.
|
||||
};
|
||||
let githubPassportStrategy = new GitHubStrategy(githubOptions, githubResponseToSubset);
|
||||
|
||||
let aadStrategy = new OIDCStrategy({
|
||||
redirectUrl: config.activeDirectory.redirectUrl,
|
||||
allowHttpForRedirectUrl: config.webServer.allowHttp,
|
||||
|
@ -92,6 +109,16 @@ module.exports = function (app, config) {
|
|||
validateIssuer: true,
|
||||
}, activeDirectorySubset);
|
||||
|
||||
let googleStrategy = null;
|
||||
if (config.authentication && config.authentication.google) {
|
||||
googleStrategy = new GoogleStrategy({
|
||||
clientID: config.authentication.google.clientId,
|
||||
clientSecret: config.authentication.google.clientSecret,
|
||||
callbackURL: config.authentication.google.redierctUrl,
|
||||
scope: ['email'],
|
||||
}, googleSubset);
|
||||
}
|
||||
|
||||
// Validate the borrow some parameters from the GitHub passport library
|
||||
if (githubPassportStrategy._oauth2 && githubPassportStrategy._oauth2._authorizeUrl) {
|
||||
app.set('runtime/passport/github/authorizeUrl', githubPassportStrategy._oauth2._authorizeUrl);
|
||||
|
@ -105,7 +132,8 @@ module.exports = function (app, config) {
|
|||
}
|
||||
|
||||
passport.use('github', githubPassportStrategy);
|
||||
passport.use('azure-active-directory', aadStrategy);
|
||||
//passport.use('azure-active-directory', aadStrategy);
|
||||
passport.use('google', googleStrategy);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Expanded OAuth-scope GitHub access for org membership writes.
|
||||
|
|
|
@ -179,17 +179,35 @@ module.exports = function configurePassport(app, passport, initialConfig) {
|
|||
// ----------------------------------------------------------------------------
|
||||
// passport integration with Azure Active Directory
|
||||
// ----------------------------------------------------------------------------
|
||||
var aadMiddleware = initialConfig.authentication.scheme === 'github' ? passport.authorize('azure-active-directory') : passport.authenticate('azure-active-directory');
|
||||
const hasAAD = false;
|
||||
if (hasAAD) {
|
||||
var aadMiddleware = initialConfig.authentication.scheme === 'github' ? passport.authorize('azure-active-directory') : passport.authenticate('azure-active-directory');
|
||||
|
||||
app.get('/auth/azure', aadMiddleware);
|
||||
app.get('/auth/azure', aadMiddleware);
|
||||
|
||||
app.post('/auth/azure/callback', aadMiddleware, authenticationCallback.bind(null, 'aad', 'azure'));
|
||||
app.post('/auth/azure/callback', aadMiddleware, authenticationCallback.bind(null, 'aad', 'azure'));
|
||||
|
||||
app.get('/signin/azure', function (req, res) {
|
||||
utils.storeReferrer(req, res, '/auth/azure', 'request for the /signin/azure page, need to authenticate');
|
||||
});
|
||||
app.get('/signin/azure', function (req, res) {
|
||||
utils.storeReferrer(req, res, '/auth/azure', 'request for the /signin/azure page, need to authenticate');
|
||||
});
|
||||
|
||||
app.get('/signout/azure', processSignout.bind(null, 'aad', 'azure'));
|
||||
app.get('/signout/azure', processSignout.bind(null, 'aad', 'azure'));
|
||||
}
|
||||
|
||||
const hasGoogle = true;
|
||||
if (hasGoogle) {
|
||||
const googleMiddleware = passport.authenticate('google');
|
||||
|
||||
app.get('/auth/google', googleMiddleware);
|
||||
|
||||
app.get('/auth/google/callback', googleMiddleware, authenticationCallback.bind(null, 'google', 'google'));
|
||||
|
||||
app.get('/signin/google', function (req, res) {
|
||||
utils.storeReferrer(req, res, '/auth/google', 'request for the /signin/google page, need to authenticate');
|
||||
});
|
||||
|
||||
app.get('/signout/google', processSignout.bind(null, 'aad', 'azure'));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
"painless-config-resolver": "1.0.0",
|
||||
"passport": "^0.3.2",
|
||||
"passport-azure-ad": "^3.0.5",
|
||||
"passport-google-oauth20": "^1.0.0",
|
||||
"passport-strategy": "1.x.x",
|
||||
"pug": "=2.0.0-beta4",
|
||||
"q": "^1.5.0",
|
||||
|
|
|
@ -20,8 +20,10 @@ const utils = require('../utils');
|
|||
|
||||
router.use(function (req, res, next) {
|
||||
var config = req.app.settings.runtimeConfig;
|
||||
const authType = 'google'; // 'azure'
|
||||
const redirectType = 'google'; // 'azure'
|
||||
if (req.isAuthenticated()) {
|
||||
var expectedAuthenticationProperty = config.authentication.scheme === 'github' ? 'github' : 'azure';
|
||||
var expectedAuthenticationProperty = config.authentication.scheme === 'github' ? 'github' : authType;
|
||||
if (req.user && !req.user[expectedAuthenticationProperty]) {
|
||||
console.warn(`A user session was authenticated but did not have present the property "${expectedAuthenticationProperty}" expected for this type of authentication. Signing them out.`);
|
||||
return res.redirect('/signout');
|
||||
|
@ -32,7 +34,7 @@ router.use(function (req, res, next) {
|
|||
}
|
||||
return next();
|
||||
}
|
||||
utils.storeOriginalUrlAsReferrer(req, res, config.authentication.scheme === 'github' ? '/auth/github' : '/auth/azure', 'user is not authenticated and needs to authenticate');
|
||||
utils.storeOriginalUrlAsReferrer(req, res, config.authentication.scheme === 'github' ? '/auth/github' : '/auth/' + redirectType, 'user is not authenticated and needs to authenticate');
|
||||
});
|
||||
|
||||
router.use((req, res, next) => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче