@@ -0,0 +1,148 @@
1+package providers
2+
3+import (
4+ "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
5+ "net/http"
6+ "net/http/httptest"
7+ "net/url"
8+ "testing"
9+
10+ "github.com/bmizerany/assert"
11+)
12+
13+func testKeycloakProvider(hostname, group string) *KeycloakProvider {
14+ p := NewKeycloakProvider(
15+ &ProviderData{
16+ ProviderName: "",
17+ LoginURL: &url.URL{},
18+ RedeemURL: &url.URL{},
19+ ProfileURL: &url.URL{},
20+ ValidateURL: &url.URL{},
21+ Scope: ""})
22+
23+ if group != "" {
24+ p.SetGroup(group)
25+ }
26+
27+ if hostname != "" {
28+ updateURL(p.Data().LoginURL, hostname)
29+ updateURL(p.Data().RedeemURL, hostname)
30+ updateURL(p.Data().ProfileURL, hostname)
31+ updateURL(p.Data().ValidateURL, hostname)
32+ }
33+ return p
34+}
35+
36+func testKeycloakBackend(payload string) *httptest.Server {
37+ path := "/api/v3/user"
38+
39+ return httptest.NewServer(http.HandlerFunc(
40+ func(w http.ResponseWriter, r *http.Request) {
41+ url := r.URL
42+ if url.Path != path {
43+ w.WriteHeader(404)
44+ } else if r.Header.Get("Authorization") != "Bearer imaginary_access_token" {
45+ w.WriteHeader(403)
46+ } else {
47+ w.WriteHeader(200)
48+ w.Write([]byte(payload))
49+ }
50+ }))
51+}
52+
53+func TestKeycloakProviderDefaults(t *testing.T) {
54+ p := testKeycloakProvider("", "")
55+ assert.NotEqual(t, nil, p)
56+ assert.Equal(t, "Keycloak", p.Data().ProviderName)
57+ assert.Equal(t, "https://keycloak.org/oauth/authorize",
58+ p.Data().LoginURL.String())
59+ assert.Equal(t, "https://keycloak.org/oauth/token",
60+ p.Data().RedeemURL.String())
61+ assert.Equal(t, "https://keycloak.org/api/v3/user",
62+ p.Data().ValidateURL.String())
63+ assert.Equal(t, "api", p.Data().Scope)
64+}
65+
66+func TestKeycloakProviderOverrides(t *testing.T) {
67+ p := NewKeycloakProvider(
68+ &ProviderData{
69+ LoginURL: &url.URL{
70+ Scheme: "https",
71+ Host: "example.com",
72+ Path: "/oauth/auth"},
73+ RedeemURL: &url.URL{
74+ Scheme: "https",
75+ Host: "example.com",
76+ Path: "/oauth/token"},
77+ ValidateURL: &url.URL{
78+ Scheme: "https",
79+ Host: "example.com",
80+ Path: "/api/v3/user"},
81+ Scope: "profile"})
82+ assert.NotEqual(t, nil, p)
83+ assert.Equal(t, "Keycloak", p.Data().ProviderName)
84+ assert.Equal(t, "https://example.com/oauth/auth",
85+ p.Data().LoginURL.String())
86+ assert.Equal(t, "https://example.com/oauth/token",
87+ p.Data().RedeemURL.String())
88+ assert.Equal(t, "https://example.com/api/v3/user",
89+ p.Data().ValidateURL.String())
90+ assert.Equal(t, "profile", p.Data().Scope)
91+}
92+
93+func TestKeycloakProviderGetEmailAddress(t *testing.T) {
94+ b := testKeycloakBackend("{\"email\": \"michael.bland@gsa.gov\"}")
95+ defer b.Close()
96+
97+ b_url, _ := url.Parse(b.URL)
98+ p := testKeycloakProvider(b_url.Host, "")
99+
100+ session := &sessions.SessionState{AccessToken: "imaginary_access_token"}
101+ email, err := p.GetEmailAddress(session)
102+ assert.Equal(t, nil, err)
103+ assert.Equal(t, "michael.bland@gsa.gov", email)
104+}
105+
106+func TestKeycloakProviderGetEmailAddressAndGroup(t *testing.T) {
107+ b := testKeycloakBackend("{\"email\": \"michael.bland@gsa.gov\", \"groups\": [\"test-grp1\", \"test-grp2\"]}")
108+ defer b.Close()
109+
110+ b_url, _ := url.Parse(b.URL)
111+ p := testKeycloakProvider(b_url.Host, "test-grp1")
112+
113+ session := &sessions.SessionState{AccessToken: "imaginary_access_token"}
114+ email, err := p.GetEmailAddress(session)
115+ assert.Equal(t, nil, err)
116+ assert.Equal(t, "michael.bland@gsa.gov", email)
117+}
118+
119+// Note that trying to trigger the "failed building request" case is not
120+// practical, since the only way it can fail is if the URL fails to parse.
121+func TestKeycloakProviderGetEmailAddressFailedRequest(t *testing.T) {
122+ b := testKeycloakBackend("unused payload")
123+ defer b.Close()
124+
125+ b_url, _ := url.Parse(b.URL)
126+ p := testKeycloakProvider(b_url.Host, "")
127+
128+ // We'll trigger a request failure by using an unexpected access
129+ // token. Alternatively, we could allow the parsing of the payload as
130+ // JSON to fail.
131+ session := &sessions.SessionState{AccessToken: "unexpected_access_token"}
132+ email, err := p.GetEmailAddress(session)
133+ assert.NotEqual(t, nil, err)
134+ assert.Equal(t, "", email)
135+}
136+
137+func TestKeycloakProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) {
138+ b := testKeycloakBackend("{\"foo\": \"bar\"}")
139+ defer b.Close()
140+
141+ b_url, _ := url.Parse(b.URL)
142+ p := testKeycloakProvider(b_url.Host, "")
143+
144+ session := &sessions.SessionState{AccessToken: "imaginary_access_token"}
145+ email, err := p.GetEmailAddress(session)
146+ assert.NotEqual(t, nil, err)
147+ assert.Equal(t, "", email)
148+}