parent
							
								
									7b26256df6
								
							
						
					
					
						commit
						d118cb7bbb
					
				|  | @ -32,7 +32,6 @@ Valid providers are : | ||||||
| * [GitHub](#github-auth-provider) | * [GitHub](#github-auth-provider) | ||||||
| * [GitLab](#gitlab-auth-provider) | * [GitLab](#gitlab-auth-provider) | ||||||
| * [LinkedIn](#linkedin-auth-provider) | * [LinkedIn](#linkedin-auth-provider) | ||||||
| * [MyUSA](#myusa-auth-provider) |  | ||||||
| 
 | 
 | ||||||
| The provider can be selected using the `provider` configuration value. | The provider can be selected using the `provider` configuration value. | ||||||
| 
 | 
 | ||||||
|  | @ -129,10 +128,6 @@ For LinkedIn, the registration steps are: | ||||||
| 3. Fill in the remaining required fields and Save. | 3. Fill in the remaining required fields and Save. | ||||||
| 4. Take note of the **Consumer Key / API Key** and **Consumer Secret / Secret Key** | 4. Take note of the **Consumer Key / API Key** and **Consumer Secret / Secret Key** | ||||||
| 
 | 
 | ||||||
| ### MyUSA Auth Provider |  | ||||||
| 
 |  | ||||||
| The [MyUSA](https://alpha.my.usa.gov) authentication service ([GitHub](https://github.com/18F/myusa)) |  | ||||||
| 
 |  | ||||||
| ### Microsoft Azure AD Provider | ### Microsoft Azure AD Provider | ||||||
| 
 | 
 | ||||||
| For adding an application to the Microsoft Azure AD follow [these steps to add an application](https://azure.microsoft.com/en-us/documentation/articles/active-directory-integrating-applications/). | For adding an application to the Microsoft Azure AD follow [these steps to add an application](https://azure.microsoft.com/en-us/documentation/articles/active-directory-integrating-applications/). | ||||||
|  |  | ||||||
|  | @ -72,3 +72,8 @@ func validateToken(p Provider, access_token string, header http.Header) bool { | ||||||
| 	log.Printf("token validation request failed: status %d - %s", resp.StatusCode, body) | 	log.Printf("token validation request failed: status %d - %s", resp.StatusCode, body) | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func updateURL(url *url.URL, hostname string) { | ||||||
|  | 	url.Scheme = "http" | ||||||
|  | 	url.Host = hostname | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,58 +0,0 @@ | ||||||
| package providers |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"log" |  | ||||||
| 	"net/http" |  | ||||||
| 	"net/url" |  | ||||||
| 
 |  | ||||||
| 	"github.com/bitly/oauth2_proxy/api" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type MyUsaProvider struct { |  | ||||||
| 	*ProviderData |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func NewMyUsaProvider(p *ProviderData) *MyUsaProvider { |  | ||||||
| 	const myUsaHost string = "alpha.my.usa.gov" |  | ||||||
| 
 |  | ||||||
| 	p.ProviderName = "MyUSA" |  | ||||||
| 	if p.LoginURL.String() == "" { |  | ||||||
| 		p.LoginURL = &url.URL{Scheme: "https", |  | ||||||
| 			Host: myUsaHost, |  | ||||||
| 			Path: "/oauth/authorize"} |  | ||||||
| 	} |  | ||||||
| 	if p.RedeemURL.String() == "" { |  | ||||||
| 		p.RedeemURL = &url.URL{Scheme: "https", |  | ||||||
| 			Host: myUsaHost, |  | ||||||
| 			Path: "/oauth/token"} |  | ||||||
| 	} |  | ||||||
| 	if p.ProfileURL.String() == "" { |  | ||||||
| 		p.ProfileURL = &url.URL{Scheme: "https", |  | ||||||
| 			Host: myUsaHost, |  | ||||||
| 			Path: "/api/v1/profile"} |  | ||||||
| 	} |  | ||||||
| 	if p.ValidateURL.String() == "" { |  | ||||||
| 		p.ValidateURL = &url.URL{Scheme: "https", |  | ||||||
| 			Host: myUsaHost, |  | ||||||
| 			Path: "/api/v1/tokeninfo"} |  | ||||||
| 	} |  | ||||||
| 	if p.Scope == "" { |  | ||||||
| 		p.Scope = "profile.email" |  | ||||||
| 	} |  | ||||||
| 	return &MyUsaProvider{ProviderData: p} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (p *MyUsaProvider) GetEmailAddress(s *SessionState) (string, error) { |  | ||||||
| 	req, err := http.NewRequest("GET", |  | ||||||
| 		p.ProfileURL.String()+"?access_token="+s.AccessToken, nil) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Printf("failed building request %s", err) |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	json, err := api.Request(req) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Printf("failed making request %s", err) |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return json.Get("email").String() |  | ||||||
| } |  | ||||||
|  | @ -1,141 +0,0 @@ | ||||||
| package providers |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
| 	"net/http/httptest" |  | ||||||
| 	"net/url" |  | ||||||
| 	"testing" |  | ||||||
| 
 |  | ||||||
| 	"github.com/bmizerany/assert" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func updateURL(url *url.URL, hostname string) { |  | ||||||
| 	url.Scheme = "http" |  | ||||||
| 	url.Host = hostname |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func testMyUsaProvider(hostname string) *MyUsaProvider { |  | ||||||
| 	p := NewMyUsaProvider( |  | ||||||
| 		&ProviderData{ |  | ||||||
| 			ProviderName: "", |  | ||||||
| 			LoginURL:     &url.URL{}, |  | ||||||
| 			RedeemURL:    &url.URL{}, |  | ||||||
| 			ProfileURL:   &url.URL{}, |  | ||||||
| 			ValidateURL:  &url.URL{}, |  | ||||||
| 			Scope:        ""}) |  | ||||||
| 	if hostname != "" { |  | ||||||
| 		updateURL(p.Data().LoginURL, hostname) |  | ||||||
| 		updateURL(p.Data().RedeemURL, hostname) |  | ||||||
| 		updateURL(p.Data().ProfileURL, hostname) |  | ||||||
| 		updateURL(p.Data().ValidateURL, hostname) |  | ||||||
| 	} |  | ||||||
| 	return p |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func testMyUsaBackend(payload string) *httptest.Server { |  | ||||||
| 	path := "/api/v1/profile" |  | ||||||
| 	query := "access_token=imaginary_access_token" |  | ||||||
| 
 |  | ||||||
| 	return httptest.NewServer(http.HandlerFunc( |  | ||||||
| 		func(w http.ResponseWriter, r *http.Request) { |  | ||||||
| 			url := r.URL |  | ||||||
| 			if url.Path != path || url.RawQuery != query { |  | ||||||
| 				w.WriteHeader(404) |  | ||||||
| 			} else { |  | ||||||
| 				w.WriteHeader(200) |  | ||||||
| 				w.Write([]byte(payload)) |  | ||||||
| 			} |  | ||||||
| 		})) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestMyUsaProviderDefaults(t *testing.T) { |  | ||||||
| 	p := testMyUsaProvider("") |  | ||||||
| 	assert.NotEqual(t, nil, p) |  | ||||||
| 	assert.Equal(t, "MyUSA", p.Data().ProviderName) |  | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/authorize", |  | ||||||
| 		p.Data().LoginURL.String()) |  | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/token", |  | ||||||
| 		p.Data().RedeemURL.String()) |  | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/profile", |  | ||||||
| 		p.Data().ProfileURL.String()) |  | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/tokeninfo", |  | ||||||
| 		p.Data().ValidateURL.String()) |  | ||||||
| 	assert.Equal(t, "profile.email", p.Data().Scope) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestMyUsaProviderOverrides(t *testing.T) { |  | ||||||
| 	p := NewMyUsaProvider( |  | ||||||
| 		&ProviderData{ |  | ||||||
| 			LoginURL: &url.URL{ |  | ||||||
| 				Scheme: "https", |  | ||||||
| 				Host:   "example.com", |  | ||||||
| 				Path:   "/oauth/auth"}, |  | ||||||
| 			RedeemURL: &url.URL{ |  | ||||||
| 				Scheme: "https", |  | ||||||
| 				Host:   "example.com", |  | ||||||
| 				Path:   "/oauth/token"}, |  | ||||||
| 			ProfileURL: &url.URL{ |  | ||||||
| 				Scheme: "https", |  | ||||||
| 				Host:   "example.com", |  | ||||||
| 				Path:   "/oauth/profile"}, |  | ||||||
| 			ValidateURL: &url.URL{ |  | ||||||
| 				Scheme: "https", |  | ||||||
| 				Host:   "example.com", |  | ||||||
| 				Path:   "/oauth/tokeninfo"}, |  | ||||||
| 			Scope: "profile"}) |  | ||||||
| 	assert.NotEqual(t, nil, p) |  | ||||||
| 	assert.Equal(t, "MyUSA", p.Data().ProviderName) |  | ||||||
| 	assert.Equal(t, "https://example.com/oauth/auth", |  | ||||||
| 		p.Data().LoginURL.String()) |  | ||||||
| 	assert.Equal(t, "https://example.com/oauth/token", |  | ||||||
| 		p.Data().RedeemURL.String()) |  | ||||||
| 	assert.Equal(t, "https://example.com/oauth/profile", |  | ||||||
| 		p.Data().ProfileURL.String()) |  | ||||||
| 	assert.Equal(t, "https://example.com/oauth/tokeninfo", |  | ||||||
| 		p.Data().ValidateURL.String()) |  | ||||||
| 	assert.Equal(t, "profile", p.Data().Scope) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestMyUsaProviderGetEmailAddress(t *testing.T) { |  | ||||||
| 	b := testMyUsaBackend("{\"email\": \"michael.bland@gsa.gov\"}") |  | ||||||
| 	defer b.Close() |  | ||||||
| 
 |  | ||||||
| 	b_url, _ := url.Parse(b.URL) |  | ||||||
| 	p := testMyUsaProvider(b_url.Host) |  | ||||||
| 
 |  | ||||||
| 	session := &SessionState{AccessToken: "imaginary_access_token"} |  | ||||||
| 	email, err := p.GetEmailAddress(session) |  | ||||||
| 	assert.Equal(t, nil, err) |  | ||||||
| 	assert.Equal(t, "michael.bland@gsa.gov", email) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Note that trying to trigger the "failed building request" case is not
 |  | ||||||
| // practical, since the only way it can fail is if the URL fails to parse.
 |  | ||||||
| func TestMyUsaProviderGetEmailAddressFailedRequest(t *testing.T) { |  | ||||||
| 	b := testMyUsaBackend("unused payload") |  | ||||||
| 	defer b.Close() |  | ||||||
| 
 |  | ||||||
| 	b_url, _ := url.Parse(b.URL) |  | ||||||
| 	p := testMyUsaProvider(b_url.Host) |  | ||||||
| 
 |  | ||||||
| 	// We'll trigger a request failure by using an unexpected access
 |  | ||||||
| 	// token. Alternatively, we could allow the parsing of the payload as
 |  | ||||||
| 	// JSON to fail.
 |  | ||||||
| 	session := &SessionState{AccessToken: "unexpected_access_token"} |  | ||||||
| 	email, err := p.GetEmailAddress(session) |  | ||||||
| 	assert.NotEqual(t, nil, err) |  | ||||||
| 	assert.Equal(t, "", email) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestMyUsaProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) { |  | ||||||
| 	b := testMyUsaBackend("{\"foo\": \"bar\"}") |  | ||||||
| 	defer b.Close() |  | ||||||
| 
 |  | ||||||
| 	b_url, _ := url.Parse(b.URL) |  | ||||||
| 	p := testMyUsaProvider(b_url.Host) |  | ||||||
| 
 |  | ||||||
| 	session := &SessionState{AccessToken: "imaginary_access_token"} |  | ||||||
| 	email, err := p.GetEmailAddress(session) |  | ||||||
| 	assert.NotEqual(t, nil, err) |  | ||||||
| 	assert.Equal(t, "", email) |  | ||||||
| } |  | ||||||
|  | @ -18,8 +18,6 @@ type Provider interface { | ||||||
| 
 | 
 | ||||||
| func New(provider string, p *ProviderData) Provider { | func New(provider string, p *ProviderData) Provider { | ||||||
| 	switch provider { | 	switch provider { | ||||||
| 	case "myusa": |  | ||||||
| 		return NewMyUsaProvider(p) |  | ||||||
| 	case "linkedin": | 	case "linkedin": | ||||||
| 		return NewLinkedInProvider(p) | 		return NewLinkedInProvider(p) | ||||||
| 	case "facebook": | 	case "facebook": | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue