git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #370 from idntfy/master

#369: Optionally allow skipping authentication for preflight requests

commit120a47a526772a9d4b6d7abc0f88b1feef65f051 authorJehiah Czebotar <jehiah@gmail.com> dateFri 7 Apr 2017, 09:20 (10 years ago) parentaf7be2d1e7d2a0
5 files changed+39−1
README.md+1 main.go+1 oauthproxy.go+8−1 oauthproxy_test.go+27 options.go+2
README.md+1
@@ -199,6 +199,7 @@ Usage of oauth2_proxy:
199199 -scope="": Oauth scope specification
200200 -signature-key="": GAP-Signature request signature key (algorithm:secretkey)
201201 -skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times)
202+ -skip-auth-preflight=false: bypass authentication for OPTIONAL requests so preflight requests could succeed when using CORS
202203 -skip-provider-button=false: will skip sign-in-page to directly reach the next step: oauth/start
203204 -ssl-insecure-skip-verify: skip validation of certificates presented when using HTTPS
204205 -tls-cert="": path to certificate file
main.go+1
@@ -39,6 +39,7 @@ func main() {
3939 flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream")
4040 flagSet.Var(&skipAuthRegex, "skip-auth-regex", "bypass authentication for requests path's that match (may be given multiple times)")
4141 flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start")
42+ flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
4243 flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS")
4344
4445 flagSet.Var(&emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email")
oauthproxy.go+8−1
@@ -68,6 +68,7 @@ type OAuthProxy struct {
6868 PassAccessToken bool
6969 CookieCipher *cookie.Cipher
7070 skipAuthRegex []string
71+ skipAuthPreflight bool
7172 compiledRegex []*regexp.Regexp
7273 templates *template.Template
7374 Footer string
@@ -198,6 +199,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
198199 serveMux: serveMux,
199200 redirectURL: redirectURL,
200201 skipAuthRegex: opts.SkipAuthRegex,
202+ skipAuthPreflight: opts.SkipAuthPreflight,
201203 compiledRegex: opts.CompiledRegex,
202204 SetXAuthRequest: opts.SetXAuthRequest,
203205 PassBasicAuth: opts.PassBasicAuth,
@@ -421,6 +423,11 @@ func (p *OAuthProxy) GetRedirect(req *http.Request) (redirect string, err error)
421423 return
422424}
423425
426+func (p *OAuthProxy) IsWhitelistedRequest(req *http.Request) (ok bool) {
427+ isPreflightRequestAllowed := p.skipAuthPreflight && req.Method == "OPTIONS"
428+ return isPreflightRequestAllowed || p.IsWhitelistedPath(req.URL.Path)
429+}
430+
424431func (p *OAuthProxy) IsWhitelistedPath(path string) (ok bool) {
425432 for _, u := range p.compiledRegex {
426433 ok = u.MatchString(path)
@@ -445,7 +452,7 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
445452 p.RobotsTxt(rw)
446453 case path == p.PingPath:
447454 p.PingPage(rw)
448− case p.IsWhitelistedPath(path):
455+ case p.IsWhitelistedRequest(req):
449456 p.serveMux.ServeHTTP(rw, req)
450457 case path == p.SignInPath:
451458 p.SignIn(rw, req)
oauthproxy_test.go+27
@@ -641,6 +641,33 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
641641 assert.Equal(t, "oauth_user@example.com", pc_test.rw.HeaderMap["X-Auth-Request-Email"][0])
642642}
643643
644+func TestAuthSkippedForPreflightRequests(t *testing.T) {
645+ upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
646+ w.WriteHeader(200)
647+ w.Write([]byte("response"))
648+ }))
649+ defer upstream.Close()
650+
651+ opts := NewOptions()
652+ opts.Upstreams = append(opts.Upstreams, upstream.URL)
653+ opts.ClientID = "bazquux"
654+ opts.ClientSecret = "foobar"
655+ opts.CookieSecret = "xyzzyplugh"
656+ opts.SkipAuthPreflight = true
657+ opts.Validate()
658+
659+ upstream_url, _ := url.Parse(upstream.URL)
660+ opts.provider = NewTestProvider(upstream_url, "")
661+
662+ proxy := NewOAuthProxy(opts, func(string) bool { return false })
663+ rw := httptest.NewRecorder()
664+ req, _ := http.NewRequest("OPTIONS", "/preflight-request", nil)
665+ proxy.ServeHTTP(rw, req)
666+
667+ assert.Equal(t, 200, rw.Code)
668+ assert.Equal(t, "response", rw.Body.String())
669+}
670+
644671type SignatureAuthenticator struct {
645672 auth hmacauth.HmacAuth
646673}
options.go+2
@@ -58,6 +58,7 @@ type Options struct {
5858 PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"`
5959 SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
6060 SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest"`
61+ SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
6162
6263 // These options allow for other providers besides Google, with
6364 // potential overrides.
@@ -99,6 +100,7 @@ func NewOptions() *Options {
99100 CookieExpire: time.Duration(168) * time.Hour,
100101 CookieRefresh: time.Duration(0),
101102 SetXAuthRequest: false,
103+ SkipAuthPreflight: false,
102104 PassBasicAuth: true,
103105 PassUserHeaders: true,
104106 PassAccessToken: false,