diff --git a/api/http/handler/auth/authenticate_oauth.go b/api/http/handler/auth/authenticate_oauth.go index d8a446d3e..89b828383 100644 --- a/api/http/handler/auth/authenticate_oauth.go +++ b/api/http/handler/auth/authenticate_oauth.go @@ -55,7 +55,7 @@ func (handler *Handler) validateOAuth(w http.ResponseWriter, r *http.Request) *h } if user == nil && !settings.OAuthSettings.OAuthAutoCreateUsers { - return &httperror.HandlerError{http.StatusForbidden, "Unregistered account", portainer.ErrUnauthorized} + return &httperror.HandlerError{http.StatusForbidden, "Account not created beforehand in Portainer and automatic user provisioning not enabled", portainer.ErrUnauthorized} } if user == nil { diff --git a/api/oauth/oauth.go b/api/oauth/oauth.go index 3b3d210bc..b7de6792f 100644 --- a/api/oauth/oauth.go +++ b/api/oauth/oauth.go @@ -23,9 +23,18 @@ type Service struct{} // GetAccessToken takes an access code and exchanges it for an access token from portainer OAuthSettings token endpoint func (*Service) GetAccessToken(code string, settings *portainer.OAuthSettings) (string, error) { + unescapedCode, err := url.QueryUnescape(code) + if err != nil { + return "", err + } + config := buildConfig(settings) - token, err := config.Exchange(context.Background(), code) - return token.AccessToken, err + token, err := config.Exchange(context.Background(), unescapedCode) + if err != nil { + return "", err + } + + return token.AccessToken, nil } // GetUsername takes a token and retrieves the portainer OAuthSettings user identifier from resource server. @@ -109,7 +118,6 @@ func buildConfig(oauthSettings *portainer.OAuthSettings) *oauth2.Config { ClientSecret: oauthSettings.ClientSecret, Endpoint: endpoint, RedirectURL: oauthSettings.RedirectURI, - // TODO figure out how to handle different providers, see https://github.com/golang/oauth2/issues/119 - Scopes: []string{oauthSettings.Scopes}, + Scopes: []string{oauthSettings.Scopes}, } } diff --git a/app/extensions/oauth/components/oauth-providers-selector/oauth-provider-selector-controller.js b/app/extensions/oauth/components/oauth-providers-selector/oauth-provider-selector-controller.js new file mode 100644 index 000000000..2f5be632a --- /dev/null +++ b/app/extensions/oauth/components/oauth-providers-selector/oauth-provider-selector-controller.js @@ -0,0 +1,56 @@ +angular.module('portainer.extensions.oauth') + .controller('OAuthProviderSelectorController', function OAuthProviderSelectorController() { + var ctrl = this; + + this.providers = [ + { + userIdentifier: 'mail', + scope: 'id,email,name', + name: 'microsoft' + }, + { + authUrl: 'https://accounts.google.com/o/oauth2/auth', + accessTokenUrl: 'https://accounts.google.com/o/oauth2/token', + resourceUrl: 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json', + userIdentifier: 'email', + scopes: 'profile email', + name: 'google' + }, + { + authUrl: 'https://github.com/login/oauth/authorize', + accessTokenUrl: 'https://github.com/login/oauth/access_token', + resourceUrl: 'https://api.github.com/user', + userIdentifier: 'login', + scopes: 'id email name', + name: 'github' + }, + { + name: 'custom' + } + ]; + + this.$onInit = onInit; + + function onInit() { + console.log(ctrl.provider.authUrl); + if (ctrl.provider.authUrl) { + ctrl.provider = getProviderByURL(ctrl.provider.authUrl); + } else { + ctrl.provider = ctrl.providers[0]; + } + ctrl.onSelect(ctrl.provider); + } + + function getProviderByURL(providerAuthURL) { + if (providerAuthURL.indexOf('login.microsoftonline.com') !== -1) { + return ctrl.providers[0]; + } + else if (providerAuthURL.indexOf('accounts.google.com') !== -1) { + return ctrl.providers[1]; + } + else if (providerAuthURL.indexOf('github.com') !== -1) { + return ctrl.providers[2]; + } + return ctrl.provider[3]; + } + }); diff --git a/app/extensions/oauth/components/oauth-providers-selector/oauth-providers-selector.html b/app/extensions/oauth/components/oauth-providers-selector/oauth-providers-selector.html index f451768fe..8422f0900 100644 --- a/app/extensions/oauth/components/oauth-providers-selector/oauth-providers-selector.html +++ b/app/extensions/oauth/components/oauth-providers-selector/oauth-providers-selector.html @@ -1,17 +1,49 @@