git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #561 from oauth2-proxy/provider-urls-refactor
c5da3dfJoel Speed
CHANGELOG.md+1
@@ -11,6 +11,7 @@
11
11
12## Changes since v6.0.0
12## Changes since v6.0.0
13
13
14+- [#561](https://github.com/oauth2-proxy/oauth2-proxy/pull/561) Refactor provider URLs to package level vars (@JoelSpeed)
14- [#682](https://github.com/oauth2-proxy/oauth2-proxy/pull/682) Refactor persistent session store session ticket management (@NickMeves)
15- [#682](https://github.com/oauth2-proxy/oauth2-proxy/pull/682) Refactor persistent session store session ticket management (@NickMeves)
15- [#688](https://github.com/oauth2-proxy/oauth2-proxy/pull/688) Refactor session loading to make use of middleware pattern (@JoelSpeed)
16- [#688](https://github.com/oauth2-proxy/oauth2-proxy/pull/688) Refactor session loading to make use of middleware pattern (@JoelSpeed)
16- [#593](https://github.com/oauth2-proxy/oauth2-proxy/pull/593) Integrate upstream package with OAuth2 Proxy (@JoelSpeed)
17- [#593](https://github.com/oauth2-proxy/oauth2-proxy/pull/593) Integrate upstream package with OAuth2 Proxy (@JoelSpeed)
providers/azure.go+64−29
@@ -23,49 +23,84 @@ type AzureProvider struct {
23
23
24var _ Provider = (*AzureProvider)(nil)
24var _ Provider = (*AzureProvider)(nil)
25
25
26+const (
27+ azureProviderName = "Azure"
28+ azureDefaultScope = "openid"
29+)
30+
31+var (
32+ // Default Login URL for Azure.
33+ // Pre-parsed URL of https://login.microsoftonline.com/common/oauth2/authorize.
34+ azureDefaultLoginURL = &url.URL{
35+ Scheme: "https",
36+ Host: "login.microsoftonline.com",
37+ Path: "/common/oauth2/authorize",
38+ }
39+
40+ // Default Redeem URL for Azure.
41+ // Pre-parsed URL of https://login.microsoftonline.com/common/oauth2/token.
42+ azureDefaultRedeemURL = &url.URL{
43+ Scheme: "https",
44+ Host: "login.microsoftonline.com",
45+ Path: "/common/oauth2/token",
46+ }
47+
48+ // Default Profile URL for Azure.
49+ // Pre-parsed URL of https://graph.microsoft.com/v1.0/me.
50+ azureDefaultProfileURL = &url.URL{
51+ Scheme: "https",
52+ Host: "graph.microsoft.com",
53+ Path: "/v1.0/me",
54+ }
55+
56+ // Default ProtectedResource URL for Azure.
57+ // Pre-parsed URL of https://graph.microsoft.com.
58+ azureDefaultProtectResourceURL = &url.URL{
59+ Scheme: "https",
60+ Host: "graph.microsoft.com",
61+ }
62+)
63+
26// NewAzureProvider initiates a new AzureProvider
64// NewAzureProvider initiates a new AzureProvider
27func NewAzureProvider(p *ProviderData) *AzureProvider {
65func NewAzureProvider(p *ProviderData) *AzureProvider {
28− p.ProviderName = "Azure"
66+ p.setProviderDefaults(providerDefaults{
67+ name: azureProviderName,
68+ loginURL: azureDefaultLoginURL,
69+ redeemURL: azureDefaultRedeemURL,
70+ profileURL: azureDefaultProfileURL,
71+ validateURL: nil,
72+ scope: azureDefaultScope,
73+ })
29
74
30− if p.ProfileURL == nil || p.ProfileURL.String() == "" {
31− p.ProfileURL = &url.URL{
32− Scheme: "https",
33− Host: "graph.microsoft.com",
34− Path: "/v1.0/me",
35− }
36− }
37 if p.ProtectedResource == nil || p.ProtectedResource.String() == "" {
75 if p.ProtectedResource == nil || p.ProtectedResource.String() == "" {
38− p.ProtectedResource = &url.URL{
76+ p.ProtectedResource = azureDefaultProtectResourceURL
39− Scheme: "https",
40− Host: "graph.microsoft.com",
41− }
42− }
43− if p.Scope == "" {
44− p.Scope = "openid"
45 }
77 }
46
78
47− return &AzureProvider{ProviderData: p}
79+ return &AzureProvider{
80+ ProviderData: p,
81+ Tenant: "common",
82+ }
48}
83}
49
84
50// Configure defaults the AzureProvider configuration options
85// Configure defaults the AzureProvider configuration options
51func (p *AzureProvider) Configure(tenant string) {
86func (p *AzureProvider) Configure(tenant string) {
52− p.Tenant = tenant
53− if tenant == "" {
87+ if tenant == "" || tenant == "common" {
54− p.Tenant = "common"
88+ // tenant is empty or default, remain on the default "common" tenant
89+ return
55 }
90 }
56
91
57− if p.LoginURL == nil || p.LoginURL.String() == "" {
92+ // Specific tennant specified, override the Login and RedeemURLs
58− p.LoginURL = &url.URL{
93+ p.Tenant = tenant
59− Scheme: "https",
94+ overrideTenantURL(p.LoginURL, azureDefaultLoginURL, tenant, "authorize")
60− Host: "login.microsoftonline.com",
95+ overrideTenantURL(p.RedeemURL, azureDefaultRedeemURL, tenant, "token")
61− Path: "/" + p.Tenant + "/oauth2/authorize"}
62− }
96+}
63− if p.RedeemURL == nil || p.RedeemURL.String() == "" {
97+
98+func overrideTenantURL(current, defaultURL *url.URL, tenant, path string) {
99+ if current == nil || current.String() == "" || current.String() == defaultURL.String() {
64− p.RedeemURL = &url.URL{
100+ *current = url.URL{
65 Scheme: "https",
101 Scheme: "https",
66 Host: "login.microsoftonline.com",
102 Host: "login.microsoftonline.com",
67− Path: "/" + p.Tenant + "/oauth2/token",
103+ Path: "/" + tenant + "/oauth2/" + path}
68− }
69 }
104 }
70}
105}
71
106
providers/azure_test.go+13−19
@@ -8,6 +8,7 @@ import (
8 "testing"
8 "testing"
9 "time"
9 "time"
10
10
11+ . "github.com/onsi/gomega"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/assert"
12)
13)
13
14
@@ -32,23 +33,17 @@ func testAzureProvider(hostname string) *AzureProvider {
32 return p
33 return p
33}
34}
34
35
35−func TestAzureProviderDefaults(t *testing.T) {
36+func TestNewAzureProvider(t *testing.T) {
36− p := testAzureProvider("")
37+ g := NewWithT(t)
37− assert.NotEqual(t, nil, p)
38+
38− p.Configure("")
39+ // Test that defaults are set when calling for a new provider with nothing set
39− assert.Equal(t, "Azure", p.Data().ProviderName)
40+ providerData := NewAzureProvider(&ProviderData{}).Data()
40− assert.Equal(t, "common", p.Tenant)
41+ g.Expect(providerData.ProviderName).To(Equal("Azure"))
41− assert.Equal(t, "https://login.microsoftonline.com/common/oauth2/authorize",
42+ g.Expect(providerData.LoginURL.String()).To(Equal("https://login.microsoftonline.com/common/oauth2/authorize"))
42− p.Data().LoginURL.String())
43− assert.Equal(t, "https://login.microsoftonline.com/common/oauth2/token",
43+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://login.microsoftonline.com/common/oauth2/token"))
44− p.Data().RedeemURL.String())
45− assert.Equal(t, "https://graph.microsoft.com/v1.0/me",
44+ g.Expect(providerData.ProfileURL.String()).To(Equal("https://graph.microsoft.com/v1.0/me"))
46− p.Data().ProfileURL.String())
47− assert.Equal(t, "https://graph.microsoft.com",
48− p.Data().ProtectedResource.String())
49− assert.Equal(t, "",
50− p.Data().ValidateURL.String())
45+ g.Expect(providerData.ValidateURL.String()).To(Equal(""))
51− assert.Equal(t, "openid", p.Data().Scope)
46+ g.Expect(providerData.Scope).To(Equal("openid"))
52}
47}
53
48
54func TestAzureProviderOverrides(t *testing.T) {
49func TestAzureProviderOverrides(t *testing.T) {
@@ -102,8 +97,7 @@ func TestAzureSetTenant(t *testing.T) {
102 p.Data().ProfileURL.String())
97 p.Data().ProfileURL.String())
103 assert.Equal(t, "https://graph.microsoft.com",
98 assert.Equal(t, "https://graph.microsoft.com",
104 p.Data().ProtectedResource.String())
99 p.Data().ProtectedResource.String())
105− assert.Equal(t, "",
106− p.Data().ValidateURL.String())
100+ assert.Equal(t, "", p.Data().ValidateURL.String())
107 assert.Equal(t, "openid", p.Data().Scope)
101 assert.Equal(t, "openid", p.Data().Scope)
108}
102}
109
103
providers/bitbucket.go+40−24
@@ -19,33 +19,49 @@ type BitbucketProvider struct {
19
19
20var _ Provider = (*BitbucketProvider)(nil)
20var _ Provider = (*BitbucketProvider)(nil)
21
21
22−// NewBitbucketProvider initiates a new BitbucketProvider
22+const (
23−func NewBitbucketProvider(p *ProviderData) *BitbucketProvider {
23+ bitbucketProviderName = "Bitbucket"
24− p.ProviderName = "Bitbucket"
24+ bitbucketDefaultScope = "email"
25− if p.LoginURL == nil || p.LoginURL.String() == "" {
25+)
26− p.LoginURL = &url.URL{
26+
27− Scheme: "https",
27+var (
28− Host: "bitbucket.org",
28+ // Default Login URL for Bitbucket.
29− Path: "/site/oauth2/authorize",
29+ // Pre-parsed URL of https://bitbucket.org/site/oauth2/authorize.
30− }
30+ bitbucketDefaultLoginURL = &url.URL{
31− }
32− if p.RedeemURL == nil || p.RedeemURL.String() == "" {
33− p.RedeemURL = &url.URL{
34− Scheme: "https",
31+ Scheme: "https",
35− Host: "bitbucket.org",
32+ Host: "bitbucket.org",
36− Path: "/site/oauth2/access_token",
33+ Path: "/site/oauth2/authorize",
37− }
38 }
34 }
39− if p.ValidateURL == nil || p.ValidateURL.String() == "" {
35+
40− p.ValidateURL = &url.URL{
36+ // Default Redeem URL for Bitbucket.
37+ // Pre-parsed URL of https://bitbucket.org/site/oauth2/access_token.
38+ bitbucketDefaultRedeemURL = &url.URL{
41− Scheme: "https",
39+ Scheme: "https",
42− Host: "api.bitbucket.org",
40+ Host: "bitbucket.org",
43− Path: "/2.0/user/emails",
41+ Path: "/site/oauth2/access_token",
44− }
45 }
42 }
46− if p.Scope == "" {
43+
47− p.Scope = "email"
44+ // Default Validation URL for Bitbucket.
45+ // This simply returns the email of the authenticated user.
46+ // Bitbucket does not have a Profile URL to use.
47+ // Pre-parsed URL of https://api.bitbucket.org/2.0/user/emails.
48+ bitbucketDefaultValidateURL = &url.URL{
49+ Scheme: "https",
50+ Host: "api.bitbucket.org",
51+ Path: "/2.0/user/emails",
48 }
52 }
53+)
54+
55+// NewBitbucketProvider initiates a new BitbucketProvider
56+func NewBitbucketProvider(p *ProviderData) *BitbucketProvider {
57+ p.setProviderDefaults(providerDefaults{
58+ name: bitbucketProviderName,
59+ loginURL: bitbucketDefaultLoginURL,
60+ redeemURL: bitbucketDefaultRedeemURL,
61+ profileURL: nil,
62+ validateURL: bitbucketDefaultValidateURL,
63+ scope: bitbucketDefaultScope,
64+ })
49 return &BitbucketProvider{ProviderData: p}
65 return &BitbucketProvider{ProviderData: p}
50}
66}
51
67
providers/bitbucket_test.go+13−13
@@ -8,9 +8,9 @@ import (
8 "net/url"
8 "net/url"
9 "testing"
9 "testing"
10
10
11− "github.com/stretchr/testify/assert"
12−
13 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
11 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
12+ . "github.com/onsi/gomega"
13+ "github.com/stretchr/testify/assert"
14)
14)
15
15
16func testBitbucketProvider(hostname, team string, repository string) *BitbucketProvider {
16func testBitbucketProvider(hostname, team string, repository string) *BitbucketProvider {
@@ -61,17 +61,17 @@ func testBitbucketBackend(payload string) *httptest.Server {
61 }))
61 }))
62}
62}
63
63
64−func TestBitbucketProviderDefaults(t *testing.T) {
64+func TestNewBitbucketProvider(t *testing.T) {
65− p := testBitbucketProvider("", "", "")
65+ g := NewWithT(t)
66− assert.NotEqual(t, nil, p)
66+
67− assert.Equal(t, "Bitbucket", p.Data().ProviderName)
67+ // Test that defaults are set when calling for a new provider with nothing set
68− assert.Equal(t, "https://bitbucket.org/site/oauth2/authorize",
68+ providerData := NewBitbucketProvider(&ProviderData{}).Data()
69− p.Data().LoginURL.String())
69+ g.Expect(providerData.ProviderName).To(Equal("Bitbucket"))
70− assert.Equal(t, "https://bitbucket.org/site/oauth2/access_token",
70+ g.Expect(providerData.LoginURL.String()).To(Equal("https://bitbucket.org/site/oauth2/authorize"))
71− p.Data().RedeemURL.String())
71+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://bitbucket.org/site/oauth2/access_token"))
72+ g.Expect(providerData.ProfileURL.String()).To(Equal(""))
72− assert.Equal(t, "https://api.bitbucket.org/2.0/user/emails",
73+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://api.bitbucket.org/2.0/user/emails"))
73− p.Data().ValidateURL.String())
74+ g.Expect(providerData.Scope).To(Equal("email"))
74− assert.Equal(t, "email", p.Data().Scope)
75}
75}
76
76
77func TestBitbucketProviderScopeAdjustForTeam(t *testing.T) {
77func TestBitbucketProviderScopeAdjustForTeam(t *testing.T) {
providers/digitalocean.go+38−24
@@ -18,33 +18,47 @@ type DigitalOceanProvider struct {
18
18
19var _ Provider = (*DigitalOceanProvider)(nil)
19var _ Provider = (*DigitalOceanProvider)(nil)
20
20
21−// NewDigitalOceanProvider initiates a new DigitalOceanProvider
21+const (
22−func NewDigitalOceanProvider(p *ProviderData) *DigitalOceanProvider {
22+ digitalOceanProviderName = "DigitalOcean"
23− p.ProviderName = "DigitalOcean"
23+ digitalOceanDefaultScope = "read"
24− if p.LoginURL.String() == "" {
24+)
25− p.LoginURL = &url.URL{Scheme: "https",
25+
26− Host: "cloud.digitalocean.com",
26+var (
27− Path: "/v1/oauth/authorize",
27+ // Default Login URL for DigitalOcean.
28− }
29− }
30− if p.RedeemURL.String() == "" {
31− p.RedeemURL = &url.URL{Scheme: "https",
32− Host: "cloud.digitalocean.com",
28+ // Pre-parsed URL of https://cloud.digitalocean.com/v1/oauth/authorize.
33− Path: "/v1/oauth/token",
29+ digitalOceanDefaultLoginURL = &url.URL{
34− }
35− }
36− if p.ProfileURL.String() == "" {
37− p.ProfileURL = &url.URL{Scheme: "https",
30+ Scheme: "https",
38− Host: "api.digitalocean.com",
31+ Host: "cloud.digitalocean.com",
39− Path: "/v2/account",
32+ Path: "/v1/oauth/authorize",
40− }
41 }
33 }
42− if p.ValidateURL.String() == "" {
34+
43− p.ValidateURL = p.ProfileURL
35+ // Default Redeem URL for DigitalOcean.
36+ // Pre-parsed URL of https://cloud.digitalocean.com/v1/oauth/token.
37+ digitalOceanDefaultRedeemURL = &url.URL{
38+ Scheme: "https",
39+ Host: "cloud.digitalocean.com",
40+ Path: "/v1/oauth/token",
44 }
41 }
45− if p.Scope == "" {
42+
46− p.Scope = "read"
43+ // Default Profile URL for DigitalOcean.
44+ // Pre-parsed URL of https://cloud.digitalocean.com/v2/account.
45+ digitalOceanDefaultProfileURL = &url.URL{
46+ Scheme: "https",
47+ Host: "api.digitalocean.com",
48+ Path: "/v2/account",
47 }
49 }
50+)
51+
52+// NewDigitalOceanProvider initiates a new DigitalOceanProvider
53+func NewDigitalOceanProvider(p *ProviderData) *DigitalOceanProvider {
54+ p.setProviderDefaults(providerDefaults{
55+ name: digitalOceanProviderName,
56+ loginURL: digitalOceanDefaultLoginURL,
57+ redeemURL: digitalOceanDefaultRedeemURL,
58+ profileURL: digitalOceanDefaultProfileURL,
59+ validateURL: digitalOceanDefaultProfileURL,
60+ scope: digitalOceanDefaultScope,
61+ })
48 return &DigitalOceanProvider{ProviderData: p}
62 return &DigitalOceanProvider{ProviderData: p}
49}
63}
50
64
providers/digitalocean_test.go+12−13
@@ -8,6 +8,7 @@ import (
8 "testing"
8 "testing"
9
9
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
11+ . "github.com/onsi/gomega"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/assert"
12)
13)
13
14
@@ -44,19 +45,17 @@ func testDigitalOceanBackend(payload string) *httptest.Server {
44 }))
45 }))
45}
46}
46
47
47−func TestDigitalOceanProviderDefaults(t *testing.T) {
48+func TestNewDigitalOceanProvider(t *testing.T) {
48− p := testDigitalOceanProvider("")
49+ g := NewWithT(t)
49− assert.NotEqual(t, nil, p)
50+
50− assert.Equal(t, "DigitalOcean", p.Data().ProviderName)
51+ // Test that defaults are set when calling for a new provider with nothing set
52+ providerData := NewDigitalOceanProvider(&ProviderData{}).Data()
53+ g.Expect(providerData.ProviderName).To(Equal("DigitalOcean"))
51− assert.Equal(t, "https://cloud.digitalocean.com/v1/oauth/authorize",
54+ g.Expect(providerData.LoginURL.String()).To(Equal("https://cloud.digitalocean.com/v1/oauth/authorize"))
52− p.Data().LoginURL.String())
53− assert.Equal(t, "https://cloud.digitalocean.com/v1/oauth/token",
55+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://cloud.digitalocean.com/v1/oauth/token"))
54− p.Data().RedeemURL.String())
55− assert.Equal(t, "https://api.digitalocean.com/v2/account",
56− p.Data().ProfileURL.String())
57− assert.Equal(t, "https://api.digitalocean.com/v2/account",
56+ g.Expect(providerData.ProfileURL.String()).To(Equal("https://api.digitalocean.com/v2/account"))
58− p.Data().ValidateURL.String())
57+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://api.digitalocean.com/v2/account"))
59− assert.Equal(t, "read", p.Data().Scope)
58+ g.Expect(providerData.Scope).To(Equal("read"))
60}
59}
61
60
62func TestDigitalOceanProviderOverrides(t *testing.T) {
61func TestDigitalOceanProviderOverrides(t *testing.T) {
providers/facebook.go+39−25
@@ -18,34 +18,48 @@ type FacebookProvider struct {
18
18
19var _ Provider = (*FacebookProvider)(nil)
19var _ Provider = (*FacebookProvider)(nil)
20
20
21−// NewFacebookProvider initiates a new FacebookProvider
21+const (
22−func NewFacebookProvider(p *ProviderData) *FacebookProvider {
22+ facebookProviderName = "Facebook"
23− p.ProviderName = "Facebook"
23+ facebookDefaultScope = "public_profile email"
24− if p.LoginURL.String() == "" {
24+)
25+
26+var (
27+ // Default Login URL for Facebook.
28+ // Pre-parsed URL of https://www.facebook.com/v2.5/dialog/oauth.
29+ facebookDefaultLoginURL = &url.URL{
25− p.LoginURL = &url.URL{Scheme: "https",
30+ Scheme: "https",
26− Host: "www.facebook.com",
31+ Host: "www.facebook.com",
27− Path: "/v2.5/dialog/oauth",
32+ Path: "/v2.5/dialog/oauth",
28− // ?granted_scopes=true
33+ // ?granted_scopes=true
29− }
30− }
31− if p.RedeemURL.String() == "" {
32− p.RedeemURL = &url.URL{Scheme: "https",
33− Host: "graph.facebook.com",
34− Path: "/v2.5/oauth/access_token",
35− }
36− }
37− if p.ProfileURL.String() == "" {
38− p.ProfileURL = &url.URL{Scheme: "https",
39− Host: "graph.facebook.com",
40− Path: "/v2.5/me",
41− }
42 }
34 }
43− if p.ValidateURL.String() == "" {
35+
44− p.ValidateURL = p.ProfileURL
36+ // Default Redeem URL for Facebook.
37+ // Pre-parsed URL of https://graph.facebook.com/v2.5/oauth/access_token.
38+ facebookDefaultRedeemURL = &url.URL{
39+ Scheme: "https",
40+ Host: "graph.facebook.com",
41+ Path: "/v2.5/oauth/access_token",
45 }
42 }
46− if p.Scope == "" {
43+
47− p.Scope = "public_profile email"
44+ // Default Profile URL for Facebook.
45+ // Pre-parsed URL of https://graph.facebook.com/v2.5/me.
46+ facebookDefaultProfileURL = &url.URL{
47+ Scheme: "https",
48+ Host: "graph.facebook.com",
49+ Path: "/v2.5/me",
48 }
50 }
51+)
52+
53+// NewFacebookProvider initiates a new FacebookProvider
54+func NewFacebookProvider(p *ProviderData) *FacebookProvider {
55+ p.setProviderDefaults(providerDefaults{
56+ name: facebookProviderName,
57+ loginURL: facebookDefaultLoginURL,
58+ redeemURL: facebookDefaultRedeemURL,
59+ profileURL: facebookDefaultProfileURL,
60+ validateURL: facebookDefaultProfileURL,
61+ scope: facebookDefaultScope,
62+ })
49 return &FacebookProvider{ProviderData: p}
63 return &FacebookProvider{ProviderData: p}
50}
64}
51
65
providers/facebook_test.gonew file+20
@@ -0,0 +1,20 @@
1+package providers
2+
3+import (
4+ "testing"
5+
6+ . "github.com/onsi/gomega"
7+)
8+
9+func TestNewFacebookProvider(t *testing.T) {
10+ g := NewWithT(t)
11+
12+ // Test that defaults are set when calling for a new provider with nothing set
13+ providerData := NewFacebookProvider(&ProviderData{}).Data()
14+ g.Expect(providerData.ProviderName).To(Equal("Facebook"))
15+ g.Expect(providerData.LoginURL.String()).To(Equal("https://www.facebook.com/v2.5/dialog/oauth"))
16+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://graph.facebook.com/v2.5/oauth/access_token"))
17+ g.Expect(providerData.ProfileURL.String()).To(Equal("https://graph.facebook.com/v2.5/me"))
18+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://graph.facebook.com/v2.5/me"))
19+ g.Expect(providerData.Scope).To(Equal("public_profile email"))
20+}
providers/github.go+40−25
@@ -28,34 +28,49 @@ type GitHubProvider struct {
28
28
29var _ Provider = (*GitHubProvider)(nil)
29var _ Provider = (*GitHubProvider)(nil)
30
30
31−// NewGitHubProvider initiates a new GitHubProvider
31+const (
32−func NewGitHubProvider(p *ProviderData) *GitHubProvider {
32+ githubProviderName = "GitHub"
33− p.ProviderName = "GitHub"
33+ githubDefaultScope = "user:email"
34− if p.LoginURL == nil || p.LoginURL.String() == "" {
34+)
35− p.LoginURL = &url.URL{
35+
36− Scheme: "https",
36+var (
37− Host: "github.com",
37+ // Default Login URL for GitHub.
38− Path: "/login/oauth/authorize",
38+ // Pre-parsed URL of https://github.org/login/oauth/authorize.
39− }
39+ githubDefaultLoginURL = &url.URL{
40− }
41− if p.RedeemURL == nil || p.RedeemURL.String() == "" {
42− p.RedeemURL = &url.URL{
43− Scheme: "https",
40+ Scheme: "https",
44− Host: "github.com",
41+ Host: "github.com",
45− Path: "/login/oauth/access_token",
42+ Path: "/login/oauth/authorize",
46− }
47 }
43 }
48− // ValidationURL is the API Base URL
44+
49− if p.ValidateURL == nil || p.ValidateURL.String() == "" {
45+ // Default Redeem URL for GitHub.
50− p.ValidateURL = &url.URL{
46+ // Pre-parsed URL of https://github.org/login/oauth/access_token.
47+ githubDefaultRedeemURL = &url.URL{
51− Scheme: "https",
48+ Scheme: "https",
52− Host: "api.github.com",
49+ Host: "github.com",
53− Path: "/",
50+ Path: "/login/oauth/access_token",
54− }
55 }
51 }
56− if p.Scope == "" {
52+
57− p.Scope = "user:email"
53+ // Default Validation URL for GitHub.
54+ // ValidationURL is the API Base URL.
55+ // Other API requests are based off of this (eg to fetch users/groups).
56+ // Pre-parsed URL of https://api.github.com/.
57+ githubDefaultValidateURL = &url.URL{
58+ Scheme: "https",
59+ Host: "api.github.com",
60+ Path: "/",
58 }
61 }
62+)
63+
64+// NewGitHubProvider initiates a new GitHubProvider
65+func NewGitHubProvider(p *ProviderData) *GitHubProvider {
66+ p.setProviderDefaults(providerDefaults{
67+ name: githubProviderName,
68+ loginURL: githubDefaultLoginURL,
69+ redeemURL: githubDefaultRedeemURL,
70+ profileURL: nil,
71+ validateURL: githubDefaultValidateURL,
72+ scope: githubDefaultScope,
73+ })
59 return &GitHubProvider{ProviderData: p}
74 return &GitHubProvider{ProviderData: p}
60}
75}
61
76
providers/github_test.go+12−11
@@ -8,6 +8,7 @@ import (
8 "testing"
8 "testing"
9
9
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
11+ . "github.com/onsi/gomega"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/assert"
12)
13)
13
14
@@ -66,17 +67,17 @@ func testGitHubBackend(payloads map[string][]string) *httptest.Server {
66 }))
67 }))
67}
68}
68
69
69−func TestGitHubProviderDefaults(t *testing.T) {
70+func TestNewGitHubProvider(t *testing.T) {
70− p := testGitHubProvider("")
71+ g := NewWithT(t)
71− assert.NotEqual(t, nil, p)
72+
72− assert.Equal(t, "GitHub", p.Data().ProviderName)
73+ // Test that defaults are set when calling for a new provider with nothing set
73− assert.Equal(t, "https://github.com/login/oauth/authorize",
74+ providerData := NewGitHubProvider(&ProviderData{}).Data()
74− p.Data().LoginURL.String())
75+ g.Expect(providerData.ProviderName).To(Equal("GitHub"))
75− assert.Equal(t, "https://github.com/login/oauth/access_token",
76+ g.Expect(providerData.LoginURL.String()).To(Equal("https://github.com/login/oauth/authorize"))
76− p.Data().RedeemURL.String())
77+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://github.com/login/oauth/access_token"))
77− assert.Equal(t, "https://api.github.com/",
78+ g.Expect(providerData.ProfileURL.String()).To(Equal(""))
78− p.Data().ValidateURL.String())
79+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://api.github.com/"))
79− assert.Equal(t, "user:email", p.Data().Scope)
80+ g.Expect(providerData.Scope).To(Equal("user:email"))
80}
81}
81
82
82func TestGitHubProviderOverrides(t *testing.T) {
83func TestGitHubProviderOverrides(t *testing.T) {
providers/gitlab.go+7−2
@@ -25,12 +25,17 @@ type GitLabProvider struct {
25
25
26var _ Provider = (*GitLabProvider)(nil)
26var _ Provider = (*GitLabProvider)(nil)
27
27
28+const (
29+ gitlabProviderName = "GitLab"
30+ gitlabDefaultScope = "openid email"
31+)
32+
28// NewGitLabProvider initiates a new GitLabProvider
33// NewGitLabProvider initiates a new GitLabProvider
29func NewGitLabProvider(p *ProviderData) *GitLabProvider {
34func NewGitLabProvider(p *ProviderData) *GitLabProvider {
30− p.ProviderName = "GitLab"
35+ p.ProviderName = gitlabProviderName
31
36
32 if p.Scope == "" {
37 if p.Scope == "" {
33− p.Scope = "openid email"
38+ p.Scope = gitlabDefaultScope
34 }
39 }
35
40
36 return &GitLabProvider{ProviderData: p}
41 return &GitLabProvider{ProviderData: p}
providers/google.go+39−21
@@ -39,31 +39,49 @@ type claims struct {
39 EmailVerified bool `json:"email_verified"`
39 EmailVerified bool `json:"email_verified"`
40}
40}
41
41
42−// NewGoogleProvider initiates a new GoogleProvider
42+const (
43−func NewGoogleProvider(p *ProviderData) *GoogleProvider {
43+ googleProviderName = "Google"
44− p.ProviderName = "Google"
44+ googleDefaultScope = "profile email"
45− if p.LoginURL.String() == "" {
45+)
46+
47+var (
48+ // Default Login URL for Google.
49+ // Pre-parsed URL of https://accounts.google.com/o/oauth2/auth?access_type=offline.
50+ googleDefaultLoginURL = &url.URL{
46− p.LoginURL = &url.URL{Scheme: "https",
51+ Scheme: "https",
47− Host: "accounts.google.com",
52+ Host: "accounts.google.com",
48− Path: "/o/oauth2/auth",
53+ Path: "/o/oauth2/auth",
49− // to get a refresh token. see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
54+ // to get a refresh token. see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
50− RawQuery: "access_type=offline",
55+ RawQuery: "access_type=offline",
51− }
52− }
53− if p.RedeemURL.String() == "" {
54− p.RedeemURL = &url.URL{Scheme: "https",
55− Host: "www.googleapis.com",
56− Path: "/oauth2/v3/token"}
57 }
56 }
58− if p.ValidateURL.String() == "" {
57+
58+ // Default Redeem URL for Google.
59+ // Pre-parsed URL of https://www.googleapis.com/oauth2/v3/token.
60+ googleDefaultRedeemURL = &url.URL{
59− p.ValidateURL = &url.URL{Scheme: "https",
61+ Scheme: "https",
60− Host: "www.googleapis.com",
62+ Host: "www.googleapis.com",
61− Path: "/oauth2/v1/tokeninfo"}
63+ Path: "/oauth2/v3/token",
62 }
64 }
63− if p.Scope == "" {
65+
64− p.Scope = "profile email"
66+ // Default Validation URL for Google.
67+ // Pre-parsed URL of https://www.googleapis.com/oauth2/v1/tokeninfo.
68+ googleDefaultValidateURL = &url.URL{
69+ Scheme: "https",
70+ Host: "www.googleapis.com",
71+ Path: "/oauth2/v1/tokeninfo",
65 }
72 }
73+)
66
74
75+// NewGoogleProvider initiates a new GoogleProvider
76+func NewGoogleProvider(p *ProviderData) *GoogleProvider {
77+ p.setProviderDefaults(providerDefaults{
78+ name: googleProviderName,
79+ loginURL: googleDefaultLoginURL,
80+ redeemURL: googleDefaultRedeemURL,
81+ profileURL: nil,
82+ validateURL: googleDefaultValidateURL,
83+ scope: googleDefaultScope,
84+ })
67 return &GoogleProvider{
85 return &GoogleProvider{
68 ProviderData: p,
86 ProviderData: p,
69 // Set a default GroupValidator to just always return valid (true), it will
87 // Set a default GroupValidator to just always return valid (true), it will
providers/google_test.go+12−13
@@ -10,8 +10,8 @@ import (
10 "net/url"
10 "net/url"
11 "testing"
11 "testing"
12
12
13+ . "github.com/onsi/gomega"
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/assert"
14−
15 admin "google.golang.org/api/admin/directory/v1"
15 admin "google.golang.org/api/admin/directory/v1"
16 option "google.golang.org/api/option"
16 option "google.golang.org/api/option"
17)
17)
@@ -35,18 +35,17 @@ func newGoogleProvider() *GoogleProvider {
35 Scope: ""})
35 Scope: ""})
36}
36}
37
37
38−func TestGoogleProviderDefaults(t *testing.T) {
38+func TestNewGoogleProvider(t *testing.T) {
39− p := newGoogleProvider()
39+ g := NewWithT(t)
40− assert.NotEqual(t, nil, p)
40+
41− assert.Equal(t, "Google", p.Data().ProviderName)
41+ // Test that defaults are set when calling for a new provider with nothing set
42+ providerData := NewGoogleProvider(&ProviderData{}).Data()
43+ g.Expect(providerData.ProviderName).To(Equal("Google"))
42− assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline",
44+ g.Expect(providerData.LoginURL.String()).To(Equal("https://accounts.google.com/o/oauth2/auth?access_type=offline"))
43− p.Data().LoginURL.String())
44− assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token",
45+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://www.googleapis.com/oauth2/v3/token"))
45− p.Data().RedeemURL.String())
46+ g.Expect(providerData.ProfileURL.String()).To(Equal(""))
46− assert.Equal(t, "https://www.googleapis.com/oauth2/v1/tokeninfo",
47+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://www.googleapis.com/oauth2/v1/tokeninfo"))
47− p.Data().ValidateURL.String())
48− assert.Equal(t, "", p.Data().ProfileURL.String())
49− assert.Equal(t, "profile email", p.Data().Scope)
48+ g.Expect(providerData.Scope).To(Equal("profile email"))
50}
49}
51
50
52func TestGoogleProviderOverrides(t *testing.T) {
51func TestGoogleProviderOverrides(t *testing.T) {
providers/internal_util_test.go+3
@@ -13,6 +13,9 @@ import (
13)
13)
14
14
15func updateURL(url *url.URL, hostname string) {
15func updateURL(url *url.URL, hostname string) {
16+ if url == nil {
17+ return
18+ }
16 url.Scheme = "http"
19 url.Scheme = "http"
17 url.Host = hostname
20 url.Host = hostname
18}
21}
providers/keycloak.go+37−23
@@ -16,32 +16,46 @@ type KeycloakProvider struct {
16
16
17var _ Provider = (*KeycloakProvider)(nil)
17var _ Provider = (*KeycloakProvider)(nil)
18
18
19−func NewKeycloakProvider(p *ProviderData) *KeycloakProvider {
19+const (
20− p.ProviderName = "Keycloak"
20+ keycloakProviderName = "Keycloak"
21− if p.LoginURL == nil || p.LoginURL.String() == "" {
21+ keycloakDefaultScope = "api"
22− p.LoginURL = &url.URL{
22+)
23− Scheme: "https",
23+
24− Host: "keycloak.org",
24+var (
25+ // Default Login URL for Keycloak.
25− Path: "/oauth/authorize",
26+ // Pre-parsed URL of https://keycloak.org/oauth/authorize.
26− }
27+ keycloakDefaultLoginURL = &url.URL{
27− }
28− if p.RedeemURL == nil || p.RedeemURL.String() == "" {
29− p.RedeemURL = &url.URL{
30− Scheme: "https",
28+ Scheme: "https",
31− Host: "keycloak.org",
29+ Host: "keycloak.org",
32− Path: "/oauth/token",
30+ Path: "/oauth/authorize",
33− }
34 }
31 }
35− if p.ValidateURL == nil || p.ValidateURL.String() == "" {
32+
36− p.ValidateURL = &url.URL{
33+ // Default Redeem URL for Keycloak.
34+ // Pre-parsed URL of ttps://keycloak.org/oauth/token.
35+ keycloakDefaultRedeemURL = &url.URL{
37− Scheme: "https",
36+ Scheme: "https",
38− Host: "keycloak.org",
37+ Host: "keycloak.org",
39− Path: "/api/v3/user",
38+ Path: "/oauth/token",
40− }
41 }
39 }
42− if p.Scope == "" {
40+
43− p.Scope = "api"
41+ // Default Validation URL for Keycloak.
42+ // Pre-parsed URL of https://keycloak.org/api/v3/user.
43+ keycloakDefaultValidateURL = &url.URL{
44+ Scheme: "https",
45+ Host: "keycloak.org",
46+ Path: "/api/v3/user",
44 }
47 }
48+)
49+
50+func NewKeycloakProvider(p *ProviderData) *KeycloakProvider {
51+ p.setProviderDefaults(providerDefaults{
52+ name: keycloakProviderName,
53+ loginURL: keycloakDefaultLoginURL,
54+ redeemURL: keycloakDefaultRedeemURL,
55+ profileURL: nil,
56+ validateURL: keycloakDefaultValidateURL,
57+ scope: keycloakDefaultScope,
58+ })
45 return &KeycloakProvider{ProviderData: p}
59 return &KeycloakProvider{ProviderData: p}
46}
60}
47
61
providers/keycloak_test.go+15−2
@@ -7,9 +7,9 @@ import (
7 "net/url"
7 "net/url"
8 "testing"
8 "testing"
9
9
10− "github.com/stretchr/testify/assert"
11−
12 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
11+ . "github.com/onsi/gomega"
12+ "github.com/stretchr/testify/assert"
13)
13)
14
14
15func testKeycloakProvider(hostname, group string) *KeycloakProvider {
15func testKeycloakProvider(hostname, group string) *KeycloakProvider {
@@ -65,6 +65,19 @@ func TestKeycloakProviderDefaults(t *testing.T) {
65 assert.Equal(t, "api", p.Data().Scope)
65 assert.Equal(t, "api", p.Data().Scope)
66}
66}
67
67
68+func TestNewKeycloakProvider(t *testing.T) {
69+ g := NewWithT(t)
70+
71+ // Test that defaults are set when calling for a new provider with nothing set
72+ providerData := NewKeycloakProvider(&ProviderData{}).Data()
73+ g.Expect(providerData.ProviderName).To(Equal("Keycloak"))
74+ g.Expect(providerData.LoginURL.String()).To(Equal("https://keycloak.org/oauth/authorize"))
75+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://keycloak.org/oauth/token"))
76+ g.Expect(providerData.ProfileURL.String()).To(Equal(""))
77+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://keycloak.org/api/v3/user"))
78+ g.Expect(providerData.Scope).To(Equal("api"))
79+}
80+
68func TestKeycloakProviderOverrides(t *testing.T) {
81func TestKeycloakProviderOverrides(t *testing.T) {
69 p := NewKeycloakProvider(
82 p := NewKeycloakProvider(
70 &ProviderData{
83 &ProviderData{
providers/linkedin.go+38−21
@@ -18,30 +18,47 @@ type LinkedInProvider struct {
18
18
19var _ Provider = (*LinkedInProvider)(nil)
19var _ Provider = (*LinkedInProvider)(nil)
20
20
21−// NewLinkedInProvider initiates a new LinkedInProvider
21+const (
22−func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
22+ linkedinProviderName = "LinkedIn"
23− p.ProviderName = "LinkedIn"
23+ linkedinDefaultScope = "r_emailaddress r_basicprofile"
24− if p.LoginURL.String() == "" {
24+)
25− p.LoginURL = &url.URL{Scheme: "https",
25+
26− Host: "www.linkedin.com",
26+var (
27− Path: "/uas/oauth2/authorization"}
27+ // Default Login URL for LinkedIn.
28− }
28+ // Pre-parsed URL of https://www.linkedin.com/uas/oauth2/authorization.
29− if p.RedeemURL.String() == "" {
29+ linkedinDefaultLoginURL = &url.URL{
30− p.RedeemURL = &url.URL{Scheme: "https",
30+ Scheme: "https",
31− Host: "www.linkedin.com",
31+ Host: "www.linkedin.com",
32− Path: "/uas/oauth2/accessToken"}
32+ Path: "/uas/oauth2/authorization",
33− }
34− if p.ProfileURL.String() == "" {
35− p.ProfileURL = &url.URL{Scheme: "https",
36− Host: "www.linkedin.com",
37− Path: "/v1/people/~/email-address"}
38 }
33 }
39− if p.ValidateURL.String() == "" {
34+
40− p.ValidateURL = p.ProfileURL
35+ // Default Redeem URL for LinkedIn.
36+ // Pre-parsed URL of https://www.linkedin.com/uas/oauth2/accessToken.
37+ linkedinDefaultRedeemURL = &url.URL{
38+ Scheme: "https",
39+ Host: "www.linkedin.com",
40+ Path: "/uas/oauth2/accessToken",
41 }
41 }
42− if p.Scope == "" {
42+
43− p.Scope = "r_emailaddress r_basicprofile"
43+ // Default Profile URL for LinkedIn.
44+ // Pre-parsed URL of https://www.linkedin.com/v1/people/~/email-address.
45+ linkedinDefaultProfileURL = &url.URL{
46+ Scheme: "https",
47+ Host: "www.linkedin.com",
48+ Path: "/v1/people/~/email-address",
44 }
49 }
50+)
51+
52+// NewLinkedInProvider initiates a new LinkedInProvider
53+func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
54+ p.setProviderDefaults(providerDefaults{
55+ name: linkedinProviderName,
56+ loginURL: linkedinDefaultLoginURL,
57+ redeemURL: linkedinDefaultRedeemURL,
58+ profileURL: linkedinDefaultProfileURL,
59+ validateURL: linkedinDefaultProfileURL,
60+ scope: linkedinDefaultScope,
61+ })
45 return &LinkedInProvider{ProviderData: p}
62 return &LinkedInProvider{ProviderData: p}
46}
63}
47
64
providers/linkedin_test.go+12−13
@@ -8,6 +8,7 @@ import (
8 "testing"
8 "testing"
9
9
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
11+ . "github.com/onsi/gomega"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/assert"
12)
13)
13
14
@@ -44,19 +45,17 @@ func testLinkedInBackend(payload string) *httptest.Server {
44 }))
45 }))
45}
46}
46
47
47−func TestLinkedInProviderDefaults(t *testing.T) {
48+func TestNewLinkedInProvider(t *testing.T) {
48− p := testLinkedInProvider("")
49+ g := NewWithT(t)
49− assert.NotEqual(t, nil, p)
50+
50− assert.Equal(t, "LinkedIn", p.Data().ProviderName)
51+ // Test that defaults are set when calling for a new provider with nothing set
52+ providerData := NewLinkedInProvider(&ProviderData{}).Data()
53+ g.Expect(providerData.ProviderName).To(Equal("LinkedIn"))
51− assert.Equal(t, "https://www.linkedin.com/uas/oauth2/authorization",
54+ g.Expect(providerData.LoginURL.String()).To(Equal("https://www.linkedin.com/uas/oauth2/authorization"))
52− p.Data().LoginURL.String())
53− assert.Equal(t, "https://www.linkedin.com/uas/oauth2/accessToken",
55+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://www.linkedin.com/uas/oauth2/accessToken"))
54− p.Data().RedeemURL.String())
55− assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address",
56− p.Data().ProfileURL.String())
57− assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address",
56+ g.Expect(providerData.ProfileURL.String()).To(Equal("https://www.linkedin.com/v1/people/~/email-address"))
58− p.Data().ValidateURL.String())
57+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://www.linkedin.com/v1/people/~/email-address"))
59− assert.Equal(t, "r_emailaddress r_basicprofile", p.Data().Scope)
58+ g.Expect(providerData.Scope).To(Equal("r_emailaddress r_basicprofile"))
60}
59}
61
60
62func TestLinkedInProviderOverrides(t *testing.T) {
61func TestLinkedInProviderOverrides(t *testing.T) {
providers/logingov.go+36−24
@@ -43,35 +43,47 @@ func randSeq(n int) string {
43 return string(b)
43 return string(b)
44}
44}
45
45
46−// NewLoginGovProvider initiates a new LoginGovProvider
46+const (
47−func NewLoginGovProvider(p *ProviderData) *LoginGovProvider {
47+ loginGovProviderName = "login.gov"
48− p.ProviderName = "login.gov"
48+ loginGovDefaultScope = "email openid"
49+)
49
50
50− if p.LoginURL == nil || p.LoginURL.String() == "" {
51+var (
51− p.LoginURL = &url.URL{
52+ // Default Login URL for LoginGov.
53+ // Pre-parsed URL of https://secure.login.gov/openid_connect/authorize.
54+ loginGovDefaultLoginURL = &url.URL{
52− Scheme: "https",
55+ Scheme: "https",
53− Host: "secure.login.gov",
56+ Host: "secure.login.gov",
54− Path: "/openid_connect/authorize",
57+ Path: "/openid_connect/authorize",
55− }
56 }
58 }
57− if p.RedeemURL == nil || p.RedeemURL.String() == "" {
59+
58− p.RedeemURL = &url.URL{
60+ // Default Redeem URL for LoginGov.
59− Scheme: "https",
60− Host: "secure.login.gov",
61− Path: "/api/openid_connect/token",
61+ // Pre-parsed URL of https://secure.login.gov/api/openid_connect/token.
62− }
62+ loginGovDefaultRedeemURL = &url.URL{
63− }
64− if p.ProfileURL == nil || p.ProfileURL.String() == "" {
65− p.ProfileURL = &url.URL{
66− Scheme: "https",
63+ Scheme: "https",
67− Host: "secure.login.gov",
64+ Host: "secure.login.gov",
68− Path: "/api/openid_connect/userinfo",
65+ Path: "/api/openid_connect/token",
69− }
70 }
66 }
71− if p.Scope == "" {
67+
72− p.Scope = "email openid"
68+ // Default Profile URL for LoginGov.
69+ // Pre-parsed URL of https://graph.loginGov.com/v2.5/me.
70+ loginGovDefaultProfileURL = &url.URL{
71+ Scheme: "https",
72+ Host: "secure.login.gov",
73+ Path: "/api/openid_connect/userinfo",
73 }
74 }
75+)
74
76
77+// NewLoginGovProvider initiates a new LoginGovProvider
78+func NewLoginGovProvider(p *ProviderData) *LoginGovProvider {
79+ p.setProviderDefaults(providerDefaults{
80+ name: loginGovProviderName,
81+ loginURL: loginGovDefaultLoginURL,
82+ redeemURL: loginGovDefaultRedeemURL,
83+ profileURL: loginGovDefaultProfileURL,
84+ validateURL: nil,
85+ scope: loginGovDefaultScope,
86+ })
75 return &LoginGovProvider{
87 return &LoginGovProvider{
76 ProviderData: p,
88 ProviderData: p,
77 Nonce: randSeq(32),
89 Nonce: randSeq(32),
providers/logingov_test.go+12−12
@@ -13,6 +13,7 @@ import (
13 "time"
13 "time"
14
14
15 "github.com/dgrijalva/jwt-go"
15 "github.com/dgrijalva/jwt-go"
16+ . "github.com/onsi/gomega"
16 "github.com/stretchr/testify/assert"
17 "github.com/stretchr/testify/assert"
17 "gopkg.in/square/go-jose.v2"
18 "gopkg.in/square/go-jose.v2"
18)
19)
@@ -65,18 +66,17 @@ func newLoginGovProvider() (l *LoginGovProvider, serverKey *MyKeyData, err error
65 return
66 return
66}
67}
67
68
68−func TestLoginGovProviderDefaults(t *testing.T) {
69+func TestNewLoginGovProvider(t *testing.T) {
69− p, _, err := newLoginGovProvider()
70+ g := NewWithT(t)
70− assert.NotEqual(t, nil, p)
71+
71− assert.NoError(t, err)
72+ // Test that defaults are set when calling for a new provider with nothing set
72− assert.Equal(t, "login.gov", p.Data().ProviderName)
73+ providerData := NewLoginGovProvider(&ProviderData{}).Data()
73− assert.Equal(t, "https://secure.login.gov/openid_connect/authorize",
74+ g.Expect(providerData.ProviderName).To(Equal("login.gov"))
74− p.Data().LoginURL.String())
75− assert.Equal(t, "https://secure.login.gov/api/openid_connect/token",
75+ g.Expect(providerData.LoginURL.String()).To(Equal("https://secure.login.gov/openid_connect/authorize"))
76− p.Data().RedeemURL.String())
77− assert.Equal(t, "https://secure.login.gov/api/openid_connect/userinfo",
76+ g.Expect(providerData.RedeemURL.String()).To(Equal("https://secure.login.gov/api/openid_connect/token"))
78− p.Data().ProfileURL.String())
77+ g.Expect(providerData.ProfileURL.String()).To(Equal("https://secure.login.gov/api/openid_connect/userinfo"))
79− assert.Equal(t, "email openid", p.Data().Scope)
78+ g.Expect(providerData.ValidateURL.String()).To(Equal(""))
79+ g.Expect(providerData.Scope).To(Equal("email openid"))
80}
80}
81
81
82func TestLoginGovProviderOverrides(t *testing.T) {
82func TestLoginGovProviderOverrides(t *testing.T) {
providers/nextcloud.go+3−1
@@ -16,9 +16,11 @@ type NextcloudProvider struct {
16
16
17var _ Provider = (*NextcloudProvider)(nil)
17var _ Provider = (*NextcloudProvider)(nil)
18
18
19+const nextCloudProviderName = "Nextcloud"
20+
19// NewNextcloudProvider initiates a new NextcloudProvider
21// NewNextcloudProvider initiates a new NextcloudProvider
20func NewNextcloudProvider(p *ProviderData) *NextcloudProvider {
22func NewNextcloudProvider(p *ProviderData) *NextcloudProvider {
21− p.ProviderName = "Nextcloud"
23+ p.ProviderName = nextCloudProviderName
22 return &NextcloudProvider{ProviderData: p}
24 return &NextcloudProvider{ProviderData: p}
23}
25}
24
26
providers/provider_data.go+35
@@ -44,3 +44,38 @@ func (p *ProviderData) GetClientSecret() (clientSecret string, err error) {
44 }
44 }
45 return string(fileClientSecret), nil
45 return string(fileClientSecret), nil
46}
46}
47+
48+type providerDefaults struct {
49+ name string
50+ loginURL *url.URL
51+ redeemURL *url.URL
52+ profileURL *url.URL
53+ validateURL *url.URL
54+ scope string
55+}
56+
57+func (p *ProviderData) setProviderDefaults(defaults providerDefaults) {
58+ p.ProviderName = defaults.name
59+ p.LoginURL = defaultURL(p.LoginURL, defaults.loginURL)
60+ p.RedeemURL = defaultURL(p.RedeemURL, defaults.redeemURL)
61+ p.ProfileURL = defaultURL(p.ProfileURL, defaults.profileURL)
62+ p.ValidateURL = defaultURL(p.ValidateURL, defaults.validateURL)
63+
64+ if p.Scope == "" {
65+ p.Scope = defaults.scope
66+ }
67+}
68+
69+// defaultURL will set return a default value if the given value is not set.
70+func defaultURL(u *url.URL, d *url.URL) *url.URL {
71+ if u != nil && u.String() != "" {
72+ // The value is already set
73+ return u
74+ }
75+
76+ // If the default is given, return that
77+ if d != nil {
78+ return d
79+ }
80+ return &url.URL{}
81+}