git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #753 from codablock/azure-resource

Pass resource parameter in login url

commit7c4479791c700b8bbef90e8bf93f3e223c61e277 authorNick Meves <nick.meves@greenhouse.io> dateTue 29 Sep 2020, 09:21 (6 years ago) parente9aa7acd046782
7 files changed+63−31
CHANGELOG.md+5 providers/azure.go+9 providers/azure_test.go+7 providers/logingov.go+7−15 providers/logingov_test.go+7 providers/provider_default.go+2−16 providers/util.go+26
CHANGELOG.md+5
@@ -12,9 +12,14 @@
1212## Breaking Changes
1313
1414- [#722](https://github.com/oauth2-proxy/oauth2-proxy/pull/722) When a Redis session store is configured, OAuth2-Proxy will fail to start up unless connection and health checks to Redis pass
15+- [#753](https://github.com/oauth2-proxy/oauth2-proxy/pull/753) A bug in the Azure provider prevented it from properly passing the configured protected `--resource`
16+ via the login url. If this option was used in the past, behavior will change with this release as it will
17+ affect the tokens returned by Azure. In the past, the tokens were always for `https://graph.microsoft.com` (the default)
18+ and will now be for the configured resource (if it exists, otherwise it will run into errors)
1519
1620## Changes since v6.1.1
1721
22+- [#753](https://github.com/oauth2-proxy/oauth2-proxy/pull/753) Pass resource parameter in login url (@codablock)
1823- [#575](https://github.com/oauth2-proxy/oauth2-proxy/pull/575) Stop accepting legacy SHA1 signed cookies (@NickMeves)
1924- [#722](https://github.com/oauth2-proxy/oauth2-proxy/pull/722) Validate Redis configuration options at startup (@NickMeves)
2025- [#791](https://github.com/oauth2-proxy/oauth2-proxy/pull/791) Remove GetPreferredUsername method from provider interface (@NickMeves)
providers/azure.go+9
@@ -210,3 +210,12 @@ func (p *AzureProvider) GetEmailAddress(ctx context.Context, s *sessions.Session
210210
211211 return email, err
212212}
213+
214+func (p *AzureProvider) GetLoginURL(redirectURI, state string) string {
215+ extraParams := url.Values{}
216+ if p.ProtectedResource != nil && p.ProtectedResource.String() != "" {
217+ extraParams.Add("resource", p.ProtectedResource.String())
218+ }
219+ a := makeLoginURL(p.ProviderData, redirectURI, state, extraParams)
220+ return a.String()
221+}
providers/azure_test.go+7
@@ -213,3 +213,10 @@ func TestAzureProviderRedeemReturnsIdToken(t *testing.T) {
213213 assert.Equal(t, timestamp, s.ExpiresOn.UTC())
214214 assert.Equal(t, "refresh1234", s.RefreshToken)
215215}
216+
217+func TestAzureProviderProtectedResourceConfigured(t *testing.T) {
218+ p := testAzureProvider("")
219+ p.ProtectedResource, _ = url.Parse("http://my.resource.test")
220+ result := p.GetLoginURL("https://my.test.app/oauth", "")
221+ assert.Contains(t, result, "resource="+url.QueryEscape("http://my.resource.test"))
222+}
providers/logingov.go+7−15
@@ -225,20 +225,12 @@ func (p *LoginGovProvider) Redeem(ctx context.Context, redirectURL, code string)
225225
226226// GetLoginURL overrides GetLoginURL to add login.gov parameters
227227func (p *LoginGovProvider) GetLoginURL(redirectURI, state string) string {
228− a := *p.LoginURL
229− params, _ := url.ParseQuery(a.RawQuery)
230− params.Set("redirect_uri", redirectURI)
231− params.Set("approval_prompt", p.ApprovalPrompt)
232− params.Add("scope", p.Scope)
233− params.Set("client_id", p.ClientID)
234− params.Set("response_type", "code")
235− params.Add("state", state)
236− acr := p.AcrValues
237− if acr == "" {
238− acr = "http://idmanagement.gov/ns/assurance/loa/1"
239− }
240− params.Add("acr_values", acr)
241− params.Add("nonce", p.Nonce)
242− a.RawQuery = params.Encode()
228+ extraParams := url.Values{}
229+ if p.AcrValues == "" {
230+ acr := "http://idmanagement.gov/ns/assurance/loa/1"
231+ extraParams.Add("acr_values", acr)
232+ }
233+ extraParams.Add("nonce", p.Nonce)
234+ a := makeLoginURL(p.ProviderData, redirectURI, state, extraParams)
243235 return a.String()
244236}
providers/logingov_test.go+7
@@ -289,3 +289,10 @@ func TestLoginGovProviderBadNonce(t *testing.T) {
289289 // The "badfakenonce" in the idtoken above should cause this to error out
290290 assert.Error(t, err)
291291}
292+
293+func TestLoginGovProviderGetLoginURL(t *testing.T) {
294+ p, _, _ := newLoginGovProvider()
295+ result := p.GetLoginURL("http://redirect/", "")
296+ assert.Contains(t, result, "acr_values="+url.QueryEscape("http://idmanagement.gov/ns/assurance/loa/1"))
297+ assert.Contains(t, result, "nonce=fakenonce")
298+}
providers/provider_default.go+2−16
@@ -75,22 +75,8 @@ func (p *ProviderData) Redeem(ctx context.Context, redirectURL, code string) (s
7575
7676// GetLoginURL with typical oauth parameters
7777func (p *ProviderData) GetLoginURL(redirectURI, state string) string {
78− a := *p.LoginURL
79− params, _ := url.ParseQuery(a.RawQuery)
80− params.Set("redirect_uri", redirectURI)
81− if p.AcrValues != "" {
82− params.Add("acr_values", p.AcrValues)
83− }
84− if p.Prompt != "" {
85− params.Set("prompt", p.Prompt)
86− } else { // Legacy variant of the prompt param:
87− params.Set("approval_prompt", p.ApprovalPrompt)
88− }
89− params.Add("scope", p.Scope)
90− params.Set("client_id", p.ClientID)
91− params.Set("response_type", "code")
92− params.Add("state", state)
93− a.RawQuery = params.Encode()
78+ extraParams := url.Values{}
79+ a := makeLoginURL(p, redirectURI, state, extraParams)
9480 return a.String()
9581}
9682
providers/util.go+26
@@ -3,6 +3,7 @@ package providers
33import (
44 "fmt"
55 "net/http"
6+ "net/url"
67)
78
89const (
@@ -29,3 +30,28 @@ func makeOIDCHeader(accessToken string) http.Header {
2930 }
3031 return makeAuthorizationHeader(tokenTypeBearer, accessToken, extraHeaders)
3132}
33+
34+func makeLoginURL(p *ProviderData, redirectURI, state string, extraParams url.Values) url.URL {
35+ a := *p.LoginURL
36+ params, _ := url.ParseQuery(a.RawQuery)
37+ params.Set("redirect_uri", redirectURI)
38+ if p.AcrValues != "" {
39+ params.Add("acr_values", p.AcrValues)
40+ }
41+ if p.Prompt != "" {
42+ params.Set("prompt", p.Prompt)
43+ } else { // Legacy variant of the prompt param:
44+ params.Set("approval_prompt", p.ApprovalPrompt)
45+ }
46+ params.Add("scope", p.Scope)
47+ params.Set("client_id", p.ClientID)
48+ params.Set("response_type", "code")
49+ params.Add("state", state)
50+ for n, p := range extraParams {
51+ for _, v := range p {
52+ params.Add(n, v)
53+ }
54+ }
55+ a.RawQuery = params.Encode()
56+ return a
57+}