diff --git a/README.md b/README.md index e9138d60..0168f2ee 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ oauth2_proxy A reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain or group. -[![Build Status](https://secure.travis-ci.org/bitly/oauth2_proxy.png?branch=master)](http://travis-ci.org/bitly/oauth2_proxy) +[![Build Status](https://secure.travis-ci.org/bitly/oauth2_proxy.svg?branch=master)](http://travis-ci.org/bitly/oauth2_proxy) ![Sign In Page](https://cloud.githubusercontent.com/assets/45028/4970624/7feb7dd8-6886-11e4-93e0-c9904af44ea8.png) @@ -161,7 +161,7 @@ To authorize by email domain use `--email-domain=yourcompany.com`. To authorize `oauth2_proxy` can be configured via [config file](#config-file), [command line options](#command-line-options) or [environment variables](#environment-variables). -To generate a strong cookie secret use `python -c 'import os,base64; print base64.b64encode(os.urandom(16))'` +To generate a strong cookie secret use `python -c 'import os,base64; print base64.urlsafe_b64encode(os.urandom(16))'` ### Config File diff --git a/oauthproxy.go b/oauthproxy.go index 61a78742..a101d81c 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -491,7 +491,11 @@ func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { p.SaveSession(rw, req, session) http.Redirect(rw, req, redirect, 302) } else { - p.SignInPage(rw, req, 200) + if p.SkipProviderButton { + p.OAuthStart(rw, req) + } else { + p.SignInPage(rw, req, http.StatusOK) + } } } diff --git a/oauthproxy_test.go b/oauthproxy_test.go index a0bcc5c1..43e165a2 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -3,9 +3,6 @@ package main import ( "crypto" "encoding/base64" - "github.com/18F/hmacauth" - "github.com/bitly/oauth2_proxy/providers" - "github.com/bmizerany/assert" "io" "io/ioutil" "log" @@ -17,6 +14,10 @@ import ( "strings" "testing" "time" + + "github.com/18F/hmacauth" + "github.com/bitly/oauth2_proxy/providers" + "github.com/bmizerany/assert" ) func init() { @@ -359,26 +360,30 @@ func TestDoNotForwardAccessTokenUpstream(t *testing.T) { } type SignInPageTest struct { - opts *Options - proxy *OAuthProxy - sign_in_regexp *regexp.Regexp + opts *Options + proxy *OAuthProxy + sign_in_regexp *regexp.Regexp + sign_in_provider_regexp *regexp.Regexp } const signInRedirectPattern = `` +const signInSkipProvider = `>Found<` -func NewSignInPageTest() *SignInPageTest { +func NewSignInPageTest(skipProvider bool) *SignInPageTest { var sip_test SignInPageTest sip_test.opts = NewOptions() sip_test.opts.CookieSecret = "foobar" sip_test.opts.ClientID = "bazquux" sip_test.opts.ClientSecret = "xyzzyplugh" + sip_test.opts.SkipProviderButton = skipProvider sip_test.opts.Validate() sip_test.proxy = NewOAuthProxy(sip_test.opts, func(email string) bool { return true }) sip_test.sign_in_regexp = regexp.MustCompile(signInRedirectPattern) + sip_test.sign_in_provider_regexp = regexp.MustCompile(signInSkipProvider) return &sip_test } @@ -391,7 +396,7 @@ func (sip_test *SignInPageTest) GetEndpoint(endpoint string) (int, string) { } func TestSignInPageIncludesTargetRedirect(t *testing.T) { - sip_test := NewSignInPageTest() + sip_test := NewSignInPageTest(false) const endpoint = "/some/random/endpoint" code, body := sip_test.GetEndpoint(endpoint) @@ -409,7 +414,7 @@ func TestSignInPageIncludesTargetRedirect(t *testing.T) { } func TestSignInPageDirectAccessRedirectsToRoot(t *testing.T) { - sip_test := NewSignInPageTest() + sip_test := NewSignInPageTest(false) code, body := sip_test.GetEndpoint("/oauth2/sign_in") assert.Equal(t, 200, code) @@ -423,6 +428,34 @@ func TestSignInPageDirectAccessRedirectsToRoot(t *testing.T) { } } +func TestSignInPageSkipProvider(t *testing.T) { + sip_test := NewSignInPageTest(true) + const endpoint = "/some/random/endpoint" + + code, body := sip_test.GetEndpoint(endpoint) + assert.Equal(t, 302, code) + + match := sip_test.sign_in_provider_regexp.FindStringSubmatch(body) + if match == nil { + t.Fatal("Did not find pattern in body: " + + signInSkipProvider + "\nBody:\n" + body) + } +} + +func TestSignInPageSkipProviderDirect(t *testing.T) { + sip_test := NewSignInPageTest(true) + const endpoint = "/sign_in" + + code, body := sip_test.GetEndpoint(endpoint) + assert.Equal(t, 302, code) + + match := sip_test.sign_in_provider_regexp.FindStringSubmatch(body) + if match == nil { + t.Fatal("Did not find pattern in body: " + + signInSkipProvider + "\nBody:\n" + body) + } +} + type ProcessCookieTest struct { opts *Options proxy *OAuthProxy diff --git a/options.go b/options.go index 70fbec5a..4f460698 100644 --- a/options.go +++ b/options.go @@ -126,9 +126,6 @@ func parseURL(to_parse string, urltype string, msgs []string) (*url.URL, []strin func (o *Options) Validate() error { msgs := make([]string, 0) - if len(o.Upstreams) < 1 { - msgs = append(msgs, "missing setting: upstream") - } if o.CookieSecret == "" { msgs = append(msgs, "missing setting: cookie-secret") } @@ -139,7 +136,8 @@ func (o *Options) Validate() error { msgs = append(msgs, "missing setting: client-secret") } if o.AuthenticatedEmailsFile == "" && len(o.EmailDomains) == 0 && o.HtpasswdFile == "" { - msgs = append(msgs, "missing setting for email validation: email-domain or authenticated-emails-file required.\n use email-domain=* to authorize all email addresses") + msgs = append(msgs, "missing setting for email validation: email-domain or authenticated-emails-file required."+ + "\n use email-domain=* to authorize all email addresses") } o.redirectURL, msgs = parseURL(o.RedirectURL, "redirect", msgs) @@ -147,14 +145,13 @@ func (o *Options) Validate() error { for _, u := range o.Upstreams { upstreamURL, err := url.Parse(u) if err != nil { - msgs = append(msgs, fmt.Sprintf( - "error parsing upstream=%q %s", - upstreamURL, err)) + msgs = append(msgs, fmt.Sprintf("error parsing upstream: %s", err)) + } else { + if upstreamURL.Path == "" { + upstreamURL.Path = "/" + } + o.proxyURLs = append(o.proxyURLs, upstreamURL) } - if upstreamURL.Path == "" { - upstreamURL.Path = "/" - } - o.proxyURLs = append(o.proxyURLs, upstreamURL) } for _, u := range o.SkipAuthRegex { diff --git a/options_test.go b/options_test.go index 3d97beb7..5292e0ff 100644 --- a/options_test.go +++ b/options_test.go @@ -35,7 +35,6 @@ func TestNewOptions(t *testing.T) { assert.NotEqual(t, nil, err) expected := errorMsg([]string{ - "missing setting: upstream", "missing setting: cookie-secret", "missing setting: client-id", "missing setting: client-secret"}) diff --git a/providers/internal_util.go b/providers/internal_util.go index 6d853ab8..b396993b 100644 --- a/providers/internal_util.go +++ b/providers/internal_util.go @@ -57,7 +57,7 @@ func validateToken(p Provider, access_token string, header http.Header) bool { } resp, err := api.RequestUnparsedResponse(endpoint, header) if err != nil { - log.Printf("GET %s", endpoint) + log.Printf("GET %s", stripToken(endpoint)) log.Printf("token validation request failed: %s", err) return false }