git.iko.soy/typeable/oauth2-proxy
on master help sign in
Add GitLab provider
commit034612bf8ba67c8990aa6d28fec4c3e4ee508754 authorpmosbach <peter.c.mosbacher@nasa.gov> dateWed 17 Feb 2016, 06:19 (11 years ago) parentb1ccb05
4 files changed+200
README.md+12 providers/gitlab.go+58 providers/gitlab_test.go+128 providers/providers.go+2
README.md+12
@@ -31,6 +31,7 @@ Valid providers are :
3131* [Google](#google-auth-provider) *default*
3232* [Azure](#azure-auth-provider)
3333* [GitHub](#github-auth-provider)
34+* [GitLab](#gitlab-auth-provider)
3435* [LinkedIn](#linkedin-auth-provider)
3536* [MyUSA](#myusa-auth-provider)
3637
@@ -103,6 +104,17 @@ If you are using github enterprise, make sure you set the following to the appro
103104 -validate-url="<enterprise github api url>/user/emails"
104105
105106
107+### GitLab Auth Provider
108+
109+Whether you are using GitLab.com or self-hosting GitLab, follow [these steps to add an application](http://doc.gitlab.com/ce/integration/oauth_provider.html)
110+
111+If you are using self-hosted GitLab, make sure you set the following to the appropriate URL:
112+
113+ -login-url="<your gitlab url>/oauth/authorize"
114+ -redeem-url="<your gitlab url>/oauth/token"
115+ -validate-url="<your gitlab url>/api/v3/user"
116+
117+
106118### LinkedIn Auth Provider
107119
108120For LinkedIn, the registration steps are:
providers/gitlab.gonew file+58
@@ -0,0 +1,58 @@
1+package providers
2+
3+import (
4+ "log"
5+ "net/http"
6+ "net/url"
7+
8+ "github.com/bitly/oauth2_proxy/api"
9+)
10+
11+type GitLabProvider struct {
12+ *ProviderData
13+}
14+
15+func NewGitLabProvider(p *ProviderData) *GitLabProvider {
16+ p.ProviderName = "GitLab"
17+ if p.LoginURL == nil || p.LoginURL.String() == "" {
18+ p.LoginURL = &url.URL{
19+ Scheme: "https",
20+ Host: "gitlab.com",
21+ Path: "/oauth/authorize",
22+ }
23+ }
24+ if p.RedeemURL == nil || p.RedeemURL.String() == "" {
25+ p.RedeemURL = &url.URL{
26+ Scheme: "https",
27+ Host: "gitlab.com",
28+ Path: "/oauth/token",
29+ }
30+ }
31+ if p.ValidateURL == nil || p.ValidateURL.String() == "" {
32+ p.ValidateURL = &url.URL{
33+ Scheme: "https",
34+ Host: "gitlab.com",
35+ Path: "/api/v3/user",
36+ }
37+ }
38+ if p.Scope == "" {
39+ p.Scope = "api"
40+ }
41+ return &GitLabProvider{ProviderData: p}
42+}
43+
44+func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) {
45+
46+ req, err := http.NewRequest("GET",
47+ p.ValidateURL.String()+"?access_token="+s.AccessToken, nil)
48+ if err != nil {
49+ log.Printf("failed building request %s", err)
50+ return "", err
51+ }
52+ json, err := api.Request(req)
53+ if err != nil {
54+ log.Printf("failed making request %s", err)
55+ return "", err
56+ }
57+ return json.Get("email").String()
58+}
providers/gitlab_test.gonew file+128
@@ -0,0 +1,128 @@
1+package providers
2+
3+import (
4+ "net/http"
5+ "net/http/httptest"
6+ "net/url"
7+ "testing"
8+
9+ "github.com/bmizerany/assert"
10+)
11+
12+func testGitLabProvider(hostname string) *GitLabProvider {
13+ p := NewGitLabProvider(
14+ &ProviderData{
15+ ProviderName: "",
16+ LoginURL: &url.URL{},
17+ RedeemURL: &url.URL{},
18+ ProfileURL: &url.URL{},
19+ ValidateURL: &url.URL{},
20+ Scope: ""})
21+ if hostname != "" {
22+ updateURL(p.Data().LoginURL, hostname)
23+ updateURL(p.Data().RedeemURL, hostname)
24+ updateURL(p.Data().ProfileURL, hostname)
25+ updateURL(p.Data().ValidateURL, hostname)
26+ }
27+ return p
28+}
29+
30+func testGitLabBackend(payload string) *httptest.Server {
31+ path := "/api/v3/user"
32+ query := "access_token=imaginary_access_token"
33+
34+ return httptest.NewServer(http.HandlerFunc(
35+ func(w http.ResponseWriter, r *http.Request) {
36+ url := r.URL
37+ if url.Path != path || url.RawQuery != query {
38+ w.WriteHeader(404)
39+ } else {
40+ w.WriteHeader(200)
41+ w.Write([]byte(payload))
42+ }
43+ }))
44+}
45+
46+func TestGitLabProviderDefaults(t *testing.T) {
47+ p := testGitLabProvider("")
48+ assert.NotEqual(t, nil, p)
49+ assert.Equal(t, "GitLab", p.Data().ProviderName)
50+ assert.Equal(t, "https://gitlab.com/oauth/authorize",
51+ p.Data().LoginURL.String())
52+ assert.Equal(t, "https://gitlab.com/oauth/token",
53+ p.Data().RedeemURL.String())
54+ assert.Equal(t, "https://gitlab.com/api/v3/user",
55+ p.Data().ValidateURL.String())
56+ assert.Equal(t, "api", p.Data().Scope)
57+}
58+
59+func TestGitLabProviderOverrides(t *testing.T) {
60+ p := NewGitLabProvider(
61+ &ProviderData{
62+ LoginURL: &url.URL{
63+ Scheme: "https",
64+ Host: "example.com",
65+ Path: "/oauth/auth"},
66+ RedeemURL: &url.URL{
67+ Scheme: "https",
68+ Host: "example.com",
69+ Path: "/oauth/token"},
70+ ValidateURL: &url.URL{
71+ Scheme: "https",
72+ Host: "example.com",
73+ Path: "/api/v3/user"},
74+ Scope: "profile"})
75+ assert.NotEqual(t, nil, p)
76+ assert.Equal(t, "GitLab", p.Data().ProviderName)
77+ assert.Equal(t, "https://example.com/oauth/auth",
78+ p.Data().LoginURL.String())
79+ assert.Equal(t, "https://example.com/oauth/token",
80+ p.Data().RedeemURL.String())
81+ assert.Equal(t, "https://example.com/api/v3/user",
82+ p.Data().ValidateURL.String())
83+ assert.Equal(t, "profile", p.Data().Scope)
84+}
85+
86+func TestGitLabProviderGetEmailAddress(t *testing.T) {
87+ b := testGitLabBackend("{\"email\": \"michael.bland@gsa.gov\"}")
88+ defer b.Close()
89+
90+ b_url, _ := url.Parse(b.URL)
91+ p := testGitLabProvider(b_url.Host)
92+
93+ session := &SessionState{AccessToken: "imaginary_access_token"}
94+ email, err := p.GetEmailAddress(session)
95+ assert.Equal(t, nil, err)
96+ assert.Equal(t, "michael.bland@gsa.gov", email)
97+}
98+
99+// Note that trying to trigger the "failed building request" case is not
100+// practical, since the only way it can fail is if the URL fails to parse.
101+func TestGitLabProviderGetEmailAddressFailedRequest(t *testing.T) {
102+ b := testGitLabBackend("unused payload")
103+ defer b.Close()
104+
105+ b_url, _ := url.Parse(b.URL)
106+ p := testGitLabProvider(b_url.Host)
107+
108+ // We'll trigger a request failure by using an unexpected access
109+ // token. Alternatively, we could allow the parsing of the payload as
110+ // JSON to fail.
111+ session := &SessionState{AccessToken: "unexpected_access_token"}
112+ email, err := p.GetEmailAddress(session)
113+ assert.NotEqual(t, nil, err)
114+ assert.Equal(t, "", email)
115+}
116+
117+func TestGitLabProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) {
118+ b := testGitLabBackend("{\"foo\": \"bar\"}")
119+ defer b.Close()
120+
121+ b_url, _ := url.Parse(b.URL)
122+ p := testGitLabProvider(b_url.Host)
123+
124+ session := &SessionState{AccessToken: "imaginary_access_token"}
125+ email, err := p.GetEmailAddress(session)
126+ assert.NotEqual(t, nil, err)
127+ assert.Equal(t, "", email)
128+}
providers/providers.go+2
@@ -26,6 +26,8 @@ func New(provider string, p *ProviderData) Provider {
2626 return NewGitHubProvider(p)
2727 case "azure":
2828 return NewAzureProvider(p)
29+ case "gitlab":
30+ return NewGitLabProvider(p)
2931 default:
3032 return NewGoogleProvider(p)
3133 }