git.iko.soy/typeable/oauth2-proxy
on master help sign in
Add MyUSA provider
commit59c3ba40f60273f5d346184d3ed3c6d6322c24d4 authorMike Bland <michael.bland@gsa.gov> dateTue 31 Mar 2015, 15:17 (12 years ago) parent243dbb7
3 files changed+191
providers/myusa.go+55 providers/myusa_test.go+134 providers/providers.go+2
providers/myusa.gonew file+55
@@ -0,0 +1,55 @@
1+package providers
2+
3+import (
4+ "log"
5+ "net/http"
6+ "net/url"
7+
8+ "github.com/bitly/go-simplejson"
9+ "github.com/bitly/google_auth_proxy/api"
10+)
11+
12+type MyUsaProvider struct {
13+ *ProviderData
14+}
15+
16+func NewMyUsaProvider(p *ProviderData) *MyUsaProvider {
17+ const myUsaHost string = "alpha.my.usa.gov"
18+
19+ p.ProviderName = "MyUSA"
20+ if p.LoginUrl.String() == "" {
21+ p.LoginUrl = &url.URL{Scheme: "https",
22+ Host: myUsaHost,
23+ Path: "/oauth/authorize"}
24+ }
25+ if p.RedeemUrl.String() == "" {
26+ p.RedeemUrl = &url.URL{Scheme: "https",
27+ Host: myUsaHost,
28+ Path: "/oauth/token"}
29+ }
30+ if p.ProfileUrl.String() == "" {
31+ p.ProfileUrl = &url.URL{Scheme: "https",
32+ Host: myUsaHost,
33+ Path: "/api/v1/profile"}
34+ }
35+ if p.Scope == "" {
36+ p.Scope = "profile.email"
37+ }
38+ return &MyUsaProvider{ProviderData: p}
39+}
40+
41+func (p *MyUsaProvider) GetEmailAddress(auth_response *simplejson.Json,
42+ access_token string) (string, error) {
43+ req, err := http.NewRequest("GET",
44+ p.ProfileUrl.String()+"?access_token="+access_token, nil)
45+ if err != nil {
46+ log.Printf("failed building request %s", err)
47+ return "", err
48+ }
49+ json, err := api.Request(req)
50+ if err != nil {
51+ log.Printf("failed making request %s", err)
52+ return "", err
53+ }
54+ return json.Get("email").String()
55+}
providers/myusa_test.gonew file+134
@@ -0,0 +1,134 @@
1+package providers
2+
3+import (
4+ "github.com/bitly/go-simplejson"
5+ "github.com/bmizerany/assert"
6+ "net/http"
7+ "net/http/httptest"
8+ "net/url"
9+ "testing"
10+)
11+
12+func updateUrl(url *url.URL, hostname string) {
13+ url.Scheme = "http"
14+ url.Host = hostname
15+}
16+
17+func testMyUsaProvider(hostname string) *MyUsaProvider {
18+ p := NewMyUsaProvider(
19+ &ProviderData{
20+ ProviderName: "",
21+ LoginUrl: &url.URL{},
22+ RedeemUrl: &url.URL{},
23+ ProfileUrl: &url.URL{},
24+ Scope: ""})
25+ if hostname != "" {
26+ updateUrl(p.Data().LoginUrl, hostname)
27+ updateUrl(p.Data().RedeemUrl, hostname)
28+ updateUrl(p.Data().ProfileUrl, hostname)
29+ }
30+ return p
31+}
32+
33+func testMyUsaBackend(payload string) *httptest.Server {
34+ path := "/api/v1/profile"
35+ query := "access_token=imaginary_access_token"
36+
37+ return httptest.NewServer(http.HandlerFunc(
38+ func(w http.ResponseWriter, r *http.Request) {
39+ url := r.URL
40+ if url.Path != path || url.RawQuery != query {
41+ w.WriteHeader(404)
42+ } else {
43+ w.WriteHeader(200)
44+ w.Write([]byte(payload))
45+ }
46+ }))
47+}
48+
49+func TestMyUsaProviderDefaults(t *testing.T) {
50+ p := testMyUsaProvider("")
51+ assert.NotEqual(t, nil, p)
52+ assert.Equal(t, "MyUSA", p.Data().ProviderName)
53+ assert.Equal(t, "https://alpha.my.usa.gov/oauth/authorize",
54+ p.Data().LoginUrl.String())
55+ assert.Equal(t, "https://alpha.my.usa.gov/oauth/token",
56+ p.Data().RedeemUrl.String())
57+ assert.Equal(t, "https://alpha.my.usa.gov/api/v1/profile",
58+ p.Data().ProfileUrl.String())
59+ assert.Equal(t, "profile.email", p.Data().Scope)
60+}
61+
62+func TestMyUsaProviderOverrides(t *testing.T) {
63+ p := NewMyUsaProvider(
64+ &ProviderData{
65+ LoginUrl: &url.URL{
66+ Scheme: "https",
67+ Host: "example.com",
68+ Path: "/oauth/auth"},
69+ RedeemUrl: &url.URL{
70+ Scheme: "https",
71+ Host: "example.com",
72+ Path: "/oauth/token"},
73+ ProfileUrl: &url.URL{
74+ Scheme: "https",
75+ Host: "example.com",
76+ Path: "/oauth/profile"},
77+ Scope: "profile"})
78+ assert.NotEqual(t, nil, p)
79+ assert.Equal(t, "MyUSA", p.Data().ProviderName)
80+ assert.Equal(t, "https://example.com/oauth/auth",
81+ p.Data().LoginUrl.String())
82+ assert.Equal(t, "https://example.com/oauth/token",
83+ p.Data().RedeemUrl.String())
84+ assert.Equal(t, "https://example.com/oauth/profile",
85+ p.Data().ProfileUrl.String())
86+ assert.Equal(t, "profile", p.Data().Scope)
87+}
88+
89+func TestMyUsaProviderGetEmailAddress(t *testing.T) {
90+ b := testMyUsaBackend("{\"email\": \"michael.bland@gsa.gov\"}")
91+ defer b.Close()
92+
93+ b_url, _ := url.Parse(b.URL)
94+ p := testMyUsaProvider(b_url.Host)
95+ unused_auth_response := simplejson.New()
96+
97+ email, err := p.GetEmailAddress(unused_auth_response,
98+ "imaginary_access_token")
99+ assert.Equal(t, nil, err)
100+ assert.Equal(t, "michael.bland@gsa.gov", email)
101+}
102+
103+// Note that trying to trigger the "failed building request" case is not
104+// practical, since the only way it can fail is if the URL fails to parse.
105+func TestMyUsaProviderGetEmailAddressFailedRequest(t *testing.T) {
106+ b := testMyUsaBackend("unused payload")
107+ defer b.Close()
108+
109+ b_url, _ := url.Parse(b.URL)
110+ p := testMyUsaProvider(b_url.Host)
111+ unused_auth_response := simplejson.New()
112+
113+ // We'll trigger a request failure by using an unexpected access
114+ // token. Alternatively, we could allow the parsing of the payload as
115+ // JSON to fail.
116+ email, err := p.GetEmailAddress(unused_auth_response,
117+ "unexpected_access_token")
118+ assert.NotEqual(t, nil, err)
119+ assert.Equal(t, "", email)
120+}
121+
122+func TestMyUsaProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) {
123+ b := testMyUsaBackend("{\"foo\": \"bar\"}")
124+ defer b.Close()
125+
126+ b_url, _ := url.Parse(b.URL)
127+ p := testMyUsaProvider(b_url.Host)
128+ unused_auth_response := simplejson.New()
129+
130+ email, err := p.GetEmailAddress(unused_auth_response,
131+ "imaginary_access_token")
132+ assert.NotEqual(t, nil, err)
133+ assert.Equal(t, "", email)
134+}
providers/providers.go+2
@@ -12,6 +12,8 @@ type Provider interface {
1212
1313func New(provider string, p *ProviderData) Provider {
1414 switch provider {
15+ case "myusa":
16+ return NewMyUsaProvider(p)
1517 default:
1618 return NewGoogleProvider(p)
1719 }