From 81492dc91100572ef22cba2d0495eab8524f9093 Mon Sep 17 00:00:00 2001 From: Omar Elazhary Date: Mon, 8 Feb 2016 15:19:02 +0000 Subject: [PATCH] Adding a provider for CloudFoundry's UAA OAuth * Added a cloudfoundry provider (cloudfoundry.go) to interface with cloudfoundry's UAA [1] * Provide defaults for local Cloudfoundry installation on BOSH lite [2] * One workaround for UAA bug [3] in provider_default is necessary, but only applied if provider "cloudfoundry" is used [1] https://github.com/cloudfoundry/uaa [2] https://github.com/cloudfoundry/bosh-lite [3] https://github.com/cloudfoundry/uaa/issues/308 --- providers/cloudfoundry.go | 77 +++++++++++++++++++++++++++++++++++ providers/provider_default.go | 4 ++ providers/providers.go | 5 +++ 3 files changed, 86 insertions(+) create mode 100644 providers/cloudfoundry.go diff --git a/providers/cloudfoundry.go b/providers/cloudfoundry.go new file mode 100644 index 000000000..ad95bb83d --- /dev/null +++ b/providers/cloudfoundry.go @@ -0,0 +1,77 @@ +package providers + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/url" +) + +type CloudFoundryProvider struct { + *ProviderData +} + +func NewCloudFoundryProvider(p *ProviderData) *CloudFoundryProvider { + p.ProviderName = "CloudFoundry" + // Defaults for Bosh-Lite, must be configured for other OAuth Endpoints. + if p.LoginURL == nil || p.LoginURL.String() == "" { + p.LoginURL = &url.URL{ + Scheme: "http", + Host: "login.bosh-lite.com", + Path: "/oauth/authorize", + } + } + if p.RedeemURL == nil || p.RedeemURL.String() == "" { + p.RedeemURL = &url.URL{ + Scheme: "http", + Host: "login.bosh-lite.com", + Path: "/oauth/token", + } + } + if p.ValidateURL == nil || p.ValidateURL.String() == "" { + p.ValidateURL = &url.URL{ + Scheme: "http", + Host: "login.bosh-lite.com", + Path: "/userinfo", + } + } + if p.Scope == "" { + p.Scope = "openid" + } + return &CloudFoundryProvider{ProviderData: p} +} + +func (p *CloudFoundryProvider) GetEmailAddress(s *SessionState) (string, error) { + + var email struct { + Email string `json:"email"` + } + + params := url.Values{ + "access_token": {s.AccessToken}, + } + endpoint := p.ValidateURL.String() + "?" + params.Encode() + resp, err := http.DefaultClient.Get(endpoint) + if err != nil { + return "", err + } + body, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return "", err + } + + if resp.StatusCode != 200 { + return "", fmt.Errorf("got %d from %q %s", resp.StatusCode, endpoint, body) + } else { + log.Printf("got %d from %q %s", resp.StatusCode, endpoint, body) + } + + if err := json.Unmarshal(body, &email); err != nil { + return "", fmt.Errorf("%s unmarshaling %s", err, body) + } + + return email.Email, nil +} diff --git a/providers/provider_default.go b/providers/provider_default.go index 82b73ec3d..9b9cca2bc 100644 --- a/providers/provider_default.go +++ b/providers/provider_default.go @@ -35,6 +35,10 @@ func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err er return } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + // workaround for Cloudfoundry UAA bug https://github.com/cloudfoundry/uaa/issues/308 + if (p.ProviderName == "CloudFoundry") { + req.SetBasicAuth(p.ClientID, p.ClientSecret) + } var resp *http.Response resp, err = http.DefaultClient.Do(req) diff --git a/providers/providers.go b/providers/providers.go index 010e633bf..5a54ab1d8 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -26,8 +26,13 @@ func New(provider string, p *ProviderData) Provider { return NewGitHubProvider(p) case "azure": return NewAzureProvider(p) +<<<<<<< HEAD case "gitlab": return NewGitLabProvider(p) +======= + case "cloudfoundry": + return NewCloudFoundryProvider(p) +>>>>>>> Adding a provider for CloudFoundry's UAA OAuth default: return NewGoogleProvider(p) }