Merge pull request #2300 from coreos-inc/openid-connect

OpenID Connect support and OAuth login refactoring
This commit is contained in:
josephschorr 2017-01-31 18:14:44 -05:00 committed by GitHub
commit 01ec22b362
36 changed files with 1623 additions and 983 deletions

View file

@ -12,18 +12,15 @@ angular.module('quay').directive('externalLoginButton', function () {
'signInStarted': '&signInStarted',
'redirectUrl': '=redirectUrl',
'isLink': '=isLink',
'provider': '@provider',
'provider': '=provider',
'action': '@action'
},
controller: function($scope, $timeout, $interval, ApiService, KeyService, CookieService, ExternalLoginService) {
$scope.signingIn = false;
$scope.providerInfo = ExternalLoginService.getProvider($scope.provider);
$scope.startSignin = function() {
$scope.signInStarted({'service': $scope.provider});
ApiService.generateExternalLoginToken().then(function(data) {
var url = ExternalLoginService.getLoginUrl($scope.provider, $scope.action || 'login');
url = url + '&state=' + encodeURIComponent(data['token']);
ExternalLoginService.getLoginUrl($scope.provider, $scope.action || 'login', function(url) {
// Save the redirect URL in a cookie so that we can redirect back after the service returns to us.
var redirectURL = $scope.redirectUrl || window.location.toString();
@ -35,7 +32,7 @@ angular.module('quay').directive('externalLoginButton', function () {
$timeout(function() {
document.location = url;
}, 250);
}, ApiService.errorDisplay('Could not perform sign in'));
});
};
}
};

View file

@ -34,11 +34,11 @@ angular.module('quay').directive('externalLoginsManager', function () {
}
});
$scope.detachExternalLogin = function(kind) {
$scope.detachExternalLogin = function(service_id) {
if (!Features.DIRECT_LOGIN) { return; }
var params = {
'servicename': kind
'service_id': service_id
};
ApiService.detachExternalLogin(null, params).then(function() {

View file

@ -16,7 +16,9 @@ angular.module('quay').directive('headerBar', function () {
PlanService, ApiService, NotificationService, Config, Features,
DocumentationService, ExternalLoginService) {
$scope.externalSigninUrl = ExternalLoginService.getSingleSigninUrl();
ExternalLoginService.getSingleSigninUrl(function(url) {
$scope.externalSigninUrl = url;
});
var hotkeysAdded = false;
var userUpdated = function(cUser) {

View file

@ -0,0 +1,18 @@
/**
* An element which displays either an icon or an image, depending on the value.
*/
angular.module('quay').directive('iconImageView', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/icon-image-view.html',
replace: false,
transclude: true,
restrict: 'C',
scope: {
'value': '@value'
},
controller: function($scope, $element) {
}
};
return directiveDefinitionObject;
});

View file

@ -11,9 +11,10 @@
function SignInCtrl($scope, $location, ExternalLoginService, Features) {
$scope.redirectUrl = '/';
var singleUrl = ExternalLoginService.getSingleSigninUrl();
if (singleUrl) {
document.location = singleUrl;
}
ExternalLoginService.getSingleSigninUrl(function(singleUrl) {
if (singleUrl) {
document.location = singleUrl;
}
});
}
})();

View file

@ -1,131 +1,42 @@
/**
* Service which exposes the supported external logins.
*/
angular.module('quay').factory('ExternalLoginService', ['KeyService', 'Features', 'Config',
function(KeyService, Features, Config) {
angular.module('quay').factory('ExternalLoginService', ['Features', 'Config', 'ApiService',
function(Features, Config, ApiService) {
var externalLoginService = {};
externalLoginService.getLoginUrl = function(service, action) {
var serviceInfo = externalLoginService.getProvider(service);
if (!serviceInfo) { return ''; }
externalLoginService.EXTERNAL_LOGINS = window.__external_login || [];
var loginUrl = KeyService.getConfiguration(serviceInfo.key, 'AUTHORIZE_ENDPOINT');
var clientId = KeyService.getConfiguration(serviceInfo.key, 'CLIENT_ID');
externalLoginService.getLoginUrl = function(loginService, action, callback) {
var errorDisplay = ApiService.errorDisplay('Could not load external login service ' +
'information. Please contact your service ' +
'administrator.')
var scope = serviceInfo.scopes();
var redirectUri = Config.getUrl('/oauth2/' + service + '/callback');
var params = {
'service_id': loginService['id']
};
if (action == 'attach') {
redirectUri += '/attach';
}
var data = {
'kind': action
};
var url = loginUrl + 'client_id=' + clientId + '&scope=' + scope + '&redirect_uri=' +
redirectUri;
return url;
};
var DEX = {
id: 'dex',
key: 'DEX_LOGIN_CONFIG',
title: function() {
return KeyService.getConfiguration('DEX_LOGIN_CONFIG', 'OIDC_TITLE');
},
icon: function() {
return {'url': KeyService.getConfiguration('DEX_LOGIN_CONFIG', 'OIDC_LOGO') };
},
scopes: function() {
return 'openid email profile'
},
enabled: Features.DEX_LOGIN
};
var GITHUB = {
id: 'github',
key: 'GITHUB_LOGIN_CONFIG',
title: function() {
return KeyService.isEnterprise('github') ? 'GitHub Enterprise' : 'GitHub';
},
icon: function() {
return {'icon': 'fa-github'};
},
hasUserInfo: true,
getUserInfo: function(service_info) {
username = service_info['metadata']['service_username'];
return {
'username': username,
'endpoint': KeyService['githubEndpoint'] + username
}
},
scopes: function() {
var scopes = 'user:email';
if (KeyService.getConfiguration('GITHUB_LOGIN_CONFIG', 'ORG_RESTRICT')) {
scopes += ' read:org';
}
return scopes;
},
enabled: Features.GITHUB_LOGIN
};
var GOOGLE = {
id: 'google',
key: 'GOOGLE_LOGIN_CONFIG',
title: function() {
return 'Google';
},
icon: function() {
return {'icon': 'fa-google'};
},
scopes: function() {
return 'openid email';
},
enabled: Features.GOOGLE_LOGIN
};
externalLoginService.ALL_EXTERNAL_LOGINS = [
DEX, GITHUB, GOOGLE
];
externalLoginService.EXTERNAL_LOGINS = externalLoginService.ALL_EXTERNAL_LOGINS.filter(function(el) {
return el.enabled;
});
externalLoginService.getProvider = function(providerId) {
for (var i = 0; i < externalLoginService.EXTERNAL_LOGINS.length; ++i) {
var current = externalLoginService.EXTERNAL_LOGINS[i];
if (current.id == providerId) {
return current;
}
}
return null;
ApiService.retrieveExternalLoginAuthorizationUrl(data, params).then(function(resp) {
callback(resp['auth_url']);
}, errorDisplay);
};
externalLoginService.hasSingleSignin = function() {
return externalLoginService.EXTERNAL_LOGINS.length == 1 && !Features.DIRECT_LOGIN;
};
externalLoginService.getSingleSigninUrl = function() {
// If there is a single external login service and direct login is disabled,
// then redirect to the external login directly.
if (externalLoginService.hasSingleSignin()) {
return externalLoginService.getLoginUrl(externalLoginService.EXTERNAL_LOGINS[0].id);
externalLoginService.getSingleSigninUrl = function(callback) {
if (!externalLoginService.hasSingleSignin()) {
return callback(null);
}
return null;
// If there is a single external login service and direct login is disabled,
// then redirect to the external login directly.
externalLoginService.getLoginUrl(externalLoginService.EXTERNAL_LOGINS[0], 'login', callback);
};
return externalLoginService;