Skip to content

Commit d98a037

Browse files
Merge pull request #101 from stlaz/repeat_fetch_2
openshift provider: refetch oauth endpoints on login
2 parents ae529dd + c476fc4 commit d98a037

File tree

6 files changed

+97
-33
lines changed

6 files changed

+97
-33
lines changed

oauthproxy.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,12 @@ func (p *OAuthProxy) redeemCode(host, code string) (s *providers.SessionState, e
318318
return nil, errors.New("missing code")
319319
}
320320
redirectURI := p.GetRedirectURI(host)
321-
s, err = p.provider.Redeem(redirectURI, code)
321+
322+
redeemURL := p.provider.GetRedeemURL()
323+
if redeemURL == nil {
324+
return s, fmt.Errorf("unable to discover the redeeem endpoint")
325+
}
326+
s, err = p.provider.Redeem(redeemURL, redirectURI, code)
322327
if err != nil {
323328
return
324329
}
@@ -606,8 +611,17 @@ func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) {
606611
p.ErrorPage(rw, 500, "Internal Error", err.Error())
607612
return
608613
}
614+
615+
// clear cached endpoints, get fresh ones in case /.well-known/oauth-authorization-server changed its values
616+
p.provider.ClearEndpointsCache()
617+
609618
redirectURI := p.GetRedirectURI(req.Host)
610-
http.Redirect(rw, req, p.provider.GetLoginURL(redirectURI, fmt.Sprintf("%v:%v", nonce, redirect)), 302)
619+
loginURL := p.provider.GetLoginURL()
620+
if loginURL == nil {
621+
p.ErrorPage(rw, 500, "Internal Error", fmt.Sprintf("could not get login endpoint"))
622+
return
623+
}
624+
http.Redirect(rw, req, p.provider.GetLoginRedirectURL(*loginURL, redirectURI, fmt.Sprintf("%v:%v", nonce, redirect)), 302)
611625
}
612626

613627
func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {

options.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,6 @@ func (o *Options) Validate(p providers.Provider) error {
153153
if len(o.Scope) == 0 {
154154
o.Scope = defaults.Scope
155155
}
156-
if len(o.LoginURL) == 0 && defaults.LoginURL != nil {
157-
o.LoginURL = defaults.LoginURL.String()
158-
}
159-
if len(o.RedeemURL) == 0 && defaults.RedeemURL != nil {
160-
o.RedeemURL = defaults.RedeemURL.String()
161-
}
162156
if len(o.ValidateURL) == 0 && defaults.ValidateURL != nil {
163157
o.ValidateURL = defaults.ValidateURL.String()
164158
}
@@ -318,8 +312,9 @@ func (o *Options) validateProvider(provider providers.Provider) []string {
318312
ClientSecret: o.ClientSecret,
319313
ApprovalPrompt: o.ApprovalPrompt,
320314
}
321-
data.LoginURL, msgs = parseURL(o.LoginURL, "login", msgs)
322-
data.RedeemURL, msgs = parseURL(o.RedeemURL, "redeem", msgs)
315+
data.ConfigLoginURL, msgs = parseURL(o.LoginURL, "login", msgs)
316+
data.ConfigRedeemURL, msgs = parseURL(o.RedeemURL, "redeem", msgs)
317+
323318
data.ProfileURL, msgs = parseURL(o.ProfileURL, "profile", msgs)
324319
data.ValidateURL, msgs = parseURL(o.ValidateURL, "validate", msgs)
325320
if len(msgs) != 0 {

providers/openshift/provider.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ func (p *OpenShiftProvider) ReviewUser(name, accessToken, host string) error {
441441
}
442442

443443
// Copied up only to set a different client CA
444-
func (p *OpenShiftProvider) Redeem(redirectURL, code string) (s *providers.SessionState, err error) {
444+
func (p *OpenShiftProvider) Redeem(redeemURL *url.URL, redirectURL, code string) (s *providers.SessionState, err error) {
445445
if code == "" {
446446
err = errors.New("missing code")
447447
return
@@ -462,7 +462,7 @@ func (p *OpenShiftProvider) Redeem(redirectURL, code string) (s *providers.Sessi
462462
}
463463

464464
var req *http.Request
465-
req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode()))
465+
req, err = http.NewRequest("POST", redeemURL.String(), bytes.NewBufferString(params.Encode()))
466466
if err != nil {
467467
return
468468
}
@@ -481,7 +481,7 @@ func (p *OpenShiftProvider) Redeem(redirectURL, code string) (s *providers.Sessi
481481
}
482482

483483
if resp.StatusCode != 200 {
484-
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body)
484+
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, redeemURL.String(), body)
485485
return
486486
}
487487

@@ -510,6 +510,33 @@ func (p *OpenShiftProvider) Redeem(redirectURL, code string) (s *providers.Sessi
510510
return
511511
}
512512

513+
func (p *OpenShiftProvider) GetLoginURL() *url.URL {
514+
if !emptyURL(p.ConfigLoginURL) {
515+
return p.ConfigLoginURL
516+
}
517+
518+
if emptyURL(p.LoginURL) {
519+
// clear the endpoints so that we get all the newly discovered endpoints for all
520+
p.ClearEndpointsCache()
521+
discoverOpenShiftOAuth(p.ProviderData, p.Client)
522+
}
523+
return p.LoginURL
524+
}
525+
526+
func (p *OpenShiftProvider) GetRedeemURL() *url.URL {
527+
if !emptyURL(p.ConfigRedeemURL) {
528+
return p.ConfigRedeemURL
529+
}
530+
531+
if emptyURL(p.RedeemURL) {
532+
// clear the endpoints so that we get all the newly discovered endpoints
533+
p.ClearEndpointsCache()
534+
discoverOpenShiftOAuth(p.ProviderData, p.Client)
535+
}
536+
return p.RedeemURL
537+
}
538+
539+
// discoverOpenshiftOAuth sets the LoginURL and RedeemURL of the supplied ProviderData if they are unset or empty
513540
func discoverOpenShiftOAuth(provider *providers.ProviderData, client *http.Client) error {
514541
wellKnownAuthorization := getKubeAPIURLWithPath("/.well-known/oauth-authorization-server")
515542
log.Printf("Performing OAuth discovery against %s", wellKnownAuthorization)

providers/provider_data.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@ import (
55
)
66

77
type ProviderData struct {
8-
ProviderName string
9-
ClientID string
10-
ClientSecret string
11-
LoginURL *url.URL
12-
RedeemURL *url.URL
8+
ProviderName string
9+
ClientID string
10+
ClientSecret string
11+
// LoginURL, RedeemURL are cached in runtime, only set/unset
12+
// them in cache-related methods
13+
LoginURL *url.URL
14+
RedeemURL *url.URL
15+
// Config* attributes are attributes that are set in options and override
16+
// the cached attributes above
17+
ConfigLoginURL *url.URL
18+
ConfigRedeemURL *url.URL
19+
ValidateURL *url.URL
1320
ProfileURL *url.URL
1421
ProtectedResource *url.URL
15-
ValidateURL *url.URL
1622
Scope string
1723
ApprovalPrompt string
1824
}

providers/provider_default.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/openshift/oauth-proxy/cookie"
1313
)
1414

15-
func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) {
15+
func (p *ProviderData) Redeem(redeemURL *url.URL, redirectURL, code string) (s *SessionState, err error) {
1616
if code == "" {
1717
err = errors.New("missing code")
1818
return
@@ -29,7 +29,7 @@ func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err er
2929
}
3030

3131
var req *http.Request
32-
req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode()))
32+
req, err = http.NewRequest("POST", redeemURL.String(), bytes.NewBufferString(params.Encode()))
3333
if err != nil {
3434
return
3535
}
@@ -48,7 +48,7 @@ func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err er
4848
}
4949

5050
if resp.StatusCode != 200 {
51-
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body)
51+
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, redeemURL.String(), body)
5252
return
5353
}
5454

@@ -77,19 +77,17 @@ func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err er
7777
return
7878
}
7979

80-
// GetLoginURL with typical oauth parameters
81-
func (p *ProviderData) GetLoginURL(redirectURI, state string) string {
82-
var a url.URL
83-
a = *p.LoginURL
84-
params, _ := url.ParseQuery(a.RawQuery)
80+
// GetLoginRedirectURL with typical oauth parameters
81+
func (p *ProviderData) GetLoginRedirectURL(loginURL url.URL, redirectURI, state string) string {
82+
params, _ := url.ParseQuery(loginURL.RawQuery)
8583
params.Set("redirect_uri", redirectURI)
8684
params.Set("approval_prompt", p.ApprovalPrompt)
8785
params.Add("scope", p.Scope)
8886
params.Set("client_id", p.ClientID)
8987
params.Set("response_type", "code")
9088
params.Add("state", state)
91-
a.RawQuery = params.Encode()
92-
return a.String()
89+
loginURL.RawQuery = params.Encode()
90+
return loginURL.String()
9391
}
9492

9593
// CookieForSession serializes a session state for storage in a cookie
@@ -106,7 +104,7 @@ func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) {
106104
return "", errors.New("not implemented")
107105
}
108106

109-
func (p *ProviderData) ReviewUser(name, accessToken, host string) (error) {
107+
func (p *ProviderData) ReviewUser(name, accessToken, host string) error {
110108
return nil
111109
}
112110

@@ -128,3 +126,23 @@ func (p *ProviderData) ValidateSessionState(s *SessionState) bool {
128126
func (p *ProviderData) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
129127
return false, nil
130128
}
129+
130+
func (p *ProviderData) GetLoginURL() *url.URL {
131+
if !(p.ConfigLoginURL == nil || p.ConfigLoginURL.String() == "") {
132+
return p.ConfigLoginURL
133+
}
134+
135+
return p.LoginURL
136+
}
137+
138+
func (p *ProviderData) GetRedeemURL() *url.URL {
139+
if !(p.ConfigRedeemURL == nil || p.ConfigRedeemURL.String() == "") {
140+
return p.ConfigRedeemURL
141+
}
142+
return p.RedeemURL
143+
}
144+
145+
func (p *ProviderData) ClearEndpointsCache() {
146+
p.LoginURL = nil
147+
p.RedeemURL = nil
148+
}

providers/providers.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,27 @@ package providers
33
import (
44
"errors"
55
"net/http"
6+
"net/url"
67

78
"github.com/openshift/oauth-proxy/cookie"
89
)
910

1011
type Provider interface {
1112
Data() *ProviderData
1213

13-
ReviewUser(name, accessToken, host string) (error)
14+
ReviewUser(name, accessToken, host string) error
1415
GetEmailAddress(*SessionState) (string, error)
15-
Redeem(string, string) (*SessionState, error)
16+
Redeem(*url.URL, string, string) (*SessionState, error)
1617
ValidateGroup(string) bool
1718
ValidateSessionState(*SessionState) bool
18-
GetLoginURL(redirectURI, finalRedirect string) string
19+
GetLoginRedirectURL(loginURL url.URL, redirectURI, state string) string
1920
RefreshSessionIfNeeded(*SessionState) (bool, error)
2021
SessionFromCookie(string, *cookie.Cipher) (*SessionState, error)
2122
CookieForSession(*SessionState, *cookie.Cipher) (string, error)
2223
ValidateRequest(*http.Request) (*SessionState, error)
24+
GetLoginURL() *url.URL
25+
GetRedeemURL() *url.URL
26+
ClearEndpointsCache()
2327
}
2428

2529
// ErrPermissionDenied may be returned from Redeem() to indicate the user is not allowed to login.

0 commit comments

Comments
 (0)