#369: Optionally allow skipping authentication for preflight requests
This commit is contained in:
		
							parent
							
								
									af7be2d622
								
							
						
					
					
						commit
						1e7d2a08a3
					
				|  | @ -199,6 +199,7 @@ Usage of oauth2_proxy: | |||
|   -scope="": Oauth scope specification | ||||
|   -signature-key="": GAP-Signature request signature key (algorithm:secretkey) | ||||
|   -skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times) | ||||
|   -skip-auth-preflight=false: bypass authentication for OPTIONAL requests so preflight requests could succeed when using CORS | ||||
|   -skip-provider-button=false: will skip sign-in-page to directly reach the next step: oauth/start | ||||
|   -ssl-insecure-skip-verify: skip validation of certificates presented when using HTTPS | ||||
|   -tls-cert="": path to certificate file | ||||
|  |  | |||
							
								
								
									
										1
									
								
								main.go
								
								
								
								
							
							
						
						
									
										1
									
								
								main.go
								
								
								
								
							|  | @ -39,6 +39,7 @@ func main() { | |||
| 	flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream") | ||||
| 	flagSet.Var(&skipAuthRegex, "skip-auth-regex", "bypass authentication for requests path's that match (may be given multiple times)") | ||||
| 	flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start") | ||||
| 	flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests") | ||||
| 	flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS") | ||||
| 
 | ||||
| 	flagSet.Var(&emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email") | ||||
|  |  | |||
|  | @ -68,6 +68,7 @@ type OAuthProxy struct { | |||
| 	PassAccessToken     bool | ||||
| 	CookieCipher        *cookie.Cipher | ||||
| 	skipAuthRegex       []string | ||||
| 	skipAuthPreflight   bool | ||||
| 	compiledRegex       []*regexp.Regexp | ||||
| 	templates           *template.Template | ||||
| 	Footer              string | ||||
|  | @ -198,6 +199,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | |||
| 		serveMux:           serveMux, | ||||
| 		redirectURL:        redirectURL, | ||||
| 		skipAuthRegex:      opts.SkipAuthRegex, | ||||
| 		skipAuthPreflight:  opts.SkipAuthPreflight, | ||||
| 		compiledRegex:      opts.CompiledRegex, | ||||
| 		SetXAuthRequest:    opts.SetXAuthRequest, | ||||
| 		PassBasicAuth:      opts.PassBasicAuth, | ||||
|  | @ -421,6 +423,11 @@ func (p *OAuthProxy) GetRedirect(req *http.Request) (redirect string, err error) | |||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (p *OAuthProxy) IsWhitelistedRequest(req *http.Request) (ok bool) { | ||||
| 	isPreflightRequestAllowed := p.skipAuthPreflight && req.Method == "OPTIONS" | ||||
| 	return isPreflightRequestAllowed || p.IsWhitelistedPath(req.URL.Path) | ||||
| } | ||||
| 
 | ||||
| func (p *OAuthProxy) IsWhitelistedPath(path string) (ok bool) { | ||||
| 	for _, u := range p.compiledRegex { | ||||
| 		ok = u.MatchString(path) | ||||
|  | @ -445,7 +452,7 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | |||
| 		p.RobotsTxt(rw) | ||||
| 	case path == p.PingPath: | ||||
| 		p.PingPage(rw) | ||||
| 	case p.IsWhitelistedPath(path): | ||||
| 	case p.IsWhitelistedRequest(req): | ||||
| 		p.serveMux.ServeHTTP(rw, req) | ||||
| 	case path == p.SignInPath: | ||||
| 		p.SignIn(rw, req) | ||||
|  |  | |||
|  | @ -641,6 +641,33 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) { | |||
| 	assert.Equal(t, "oauth_user@example.com", pc_test.rw.HeaderMap["X-Auth-Request-Email"][0]) | ||||
| } | ||||
| 
 | ||||
| func TestAuthSkippedForPreflightRequests(t *testing.T) { | ||||
| 	upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		w.WriteHeader(200) | ||||
| 		w.Write([]byte("response")) | ||||
| 	})) | ||||
| 	defer upstream.Close() | ||||
| 
 | ||||
| 	opts := NewOptions() | ||||
| 	opts.Upstreams = append(opts.Upstreams, upstream.URL) | ||||
| 	opts.ClientID = "bazquux" | ||||
| 	opts.ClientSecret = "foobar" | ||||
| 	opts.CookieSecret = "xyzzyplugh" | ||||
| 	opts.SkipAuthPreflight = true | ||||
| 	opts.Validate() | ||||
| 
 | ||||
| 	upstream_url, _ := url.Parse(upstream.URL) | ||||
| 	opts.provider = NewTestProvider(upstream_url, "") | ||||
| 
 | ||||
| 	proxy := NewOAuthProxy(opts, func(string) bool { return false }) | ||||
| 	rw := httptest.NewRecorder() | ||||
| 	req, _ := http.NewRequest("OPTIONS", "/preflight-request", nil) | ||||
| 	proxy.ServeHTTP(rw, req) | ||||
| 
 | ||||
| 	assert.Equal(t, 200, rw.Code) | ||||
| 	assert.Equal(t, "response", rw.Body.String()) | ||||
| } | ||||
| 
 | ||||
| type SignatureAuthenticator struct { | ||||
| 	auth hmacauth.HmacAuth | ||||
| } | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ type Options struct { | |||
| 	PassUserHeaders       bool     `flag:"pass-user-headers" cfg:"pass_user_headers"` | ||||
| 	SSLInsecureSkipVerify bool     `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"` | ||||
| 	SetXAuthRequest       bool     `flag:"set-xauthrequest" cfg:"set_xauthrequest"` | ||||
| 	SkipAuthPreflight     bool     `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"` | ||||
| 
 | ||||
| 	// These options allow for other providers besides Google, with
 | ||||
| 	// potential overrides.
 | ||||
|  | @ -99,6 +100,7 @@ func NewOptions() *Options { | |||
| 		CookieExpire:        time.Duration(168) * time.Hour, | ||||
| 		CookieRefresh:       time.Duration(0), | ||||
| 		SetXAuthRequest:     false, | ||||
| 		SkipAuthPreflight:   false, | ||||
| 		PassBasicAuth:       true, | ||||
| 		PassUserHeaders:     true, | ||||
| 		PassAccessToken:     false, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue