diff --git a/README.md b/README.md index e6798a4..3021481 100644 --- a/README.md +++ b/README.md @@ -90,17 +90,20 @@ An example [oauth2_proxy.cfg](contrib/oauth2_proxy.cfg.example) config file is i Usage of oauth2_proxy: -authenticated-emails-file="": authenticate against emails via file (one per line) -client-id="": the OAuth Client ID: ie: "123456.apps.googleusercontent.com" - -client-secret="": the Client Secret + -client-secret="": the OAuth Client Secret -config="": path to config file -cookie-domain="": an optional cookie domain to force cookies to (ie: .yourcompany.com)* -cookie-expire=168h0m0s: expire timeframe for cookie -cookie-httponly=true: set HttpOnly cookie flag -cookie-https-only=true: set secure (HTTPS) cookies (deprecated. use --cookie-secure setting) + -cookie-key="_oauth2proxy": the name of the cookie that the oauth_proxy creates -cookie-refresh=0: refresh the cookie when less than this much time remains before expiration; 0 to disable -cookie-secret="": the seed string for secure cookies -cookie-secure=true: set secure (HTTPS) cookie flag -custom-templates-dir="": path to custom html templates -display-htpasswd-form=true: display username / password login form if an htpasswd file is provided + -github-org="": restrict logins to members of this organisation + -github-team="": restrict logins to members of this team -google-apps-domain=: authenticate against the given Google apps domain (may be given multiple times) -htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption -http-address="127.0.0.1:4180": [http://]: or unix:// to listen on for HTTP clients @@ -110,6 +113,7 @@ Usage of oauth2_proxy: -pass-host-header=true: pass the request Host Header to upstream -profile-url="": Profile access endpoint -provider="": Oauth provider (defaults to Google) + -proxy-prefix="/oauth2": the url root path that this proxy should be nested under (e.g. //sign_in) -redeem-url="": Token redemption endpoint -redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback" -request-logging=true: Log requests to stdout diff --git a/contrib/oauth2_proxy.cfg.example b/contrib/oauth2_proxy.cfg.example index 77d8bb3..1abc7b5 100644 --- a/contrib/oauth2_proxy.cfg.example +++ b/contrib/oauth2_proxy.cfg.example @@ -47,6 +47,7 @@ # custom_templates_dir = "" ## Cookie Settings +## Key - the cookie name ## Secret - the seed string for secure cookies; should be 16, 24, or 32 bytes ## for use with an AES cipher when cookie_refresh or pass_access_token ## is set @@ -57,6 +58,7 @@ ## Refresh revalidated the OAuth token to ensure it is still valid. ie: 24h ## Secure - secure cookies are only sent by the browser of a HTTPS connection (recommended) ## HttpOnly - httponly cookies are not readable by javascript (recommended) +# cookie_key = "_oauth2proxy" # cookie_secret = "" # cookie_domain = "" # cookie_expire = "168h" diff --git a/main.go b/main.go index 8c13822..0349352 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,9 @@ func main() { flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -s\" for SHA encryption") flagSet.Bool("display-htpasswd-form", true, "display username / password login form if an htpasswd file is provided") flagSet.String("custom-templates-dir", "", "path to custom html templates") + flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. //sign_in)") + flagSet.String("cookie-key", "_oauth2proxy", "the name of the cookie that the oauth_proxy creates") flagSet.String("cookie-secret", "", "the seed string for secure cookies") flagSet.String("cookie-domain", "", "an optional cookie domain to force cookies to (ie: .yourcompany.com)*") flagSet.Duration("cookie-expire", time.Duration(168)*time.Hour, "expire timeframe for cookie") diff --git a/oauthproxy.go b/oauthproxy.go index 06742a5..bfd4268 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -19,12 +19,6 @@ import ( "github.com/bitly/oauth2_proxy/providers" ) -const robotsPath = "/robots.txt" -const pingPath = "/ping" -const signInPath = "/oauth2/sign_in" -const oauthStartPath = "/oauth2/start" -const oauthCallbackPath = "/oauth2/callback" - type OauthProxy struct { CookieSeed string CookieKey string @@ -35,6 +29,12 @@ type OauthProxy struct { CookieRefresh time.Duration Validator func(string) bool + RobotsPath string + PingPath string + SignInPath string + OauthStartPath string + OauthCallbackPath string + redirectUrl *url.URL // the url to receive requests at provider providers.Provider oauthLoginUrl *url.URL // to redirect the user to @@ -42,6 +42,7 @@ type OauthProxy struct { oauthScope string clientID string clientSecret string + ProxyPrefix string SignInMessage string HtpasswdFile *HtpasswdFile DisplayHtpasswdForm bool @@ -106,7 +107,7 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { } redirectUrl := opts.redirectUrl - redirectUrl.Path = oauthCallbackPath + redirectUrl.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix) log.Printf("OauthProxy configured for %s", opts.ClientID) domain := opts.CookieDomain @@ -131,7 +132,7 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { } return &OauthProxy{ - CookieKey: "_oauthproxy", + CookieKey: opts.CookieKey, CookieSeed: opts.CookieSecret, CookieDomain: opts.CookieDomain, CookieSecure: opts.CookieSecure, @@ -140,8 +141,15 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { CookieRefresh: opts.CookieRefresh, Validator: validator, + RobotsPath: "/robots.txt", + PingPath: "/ping", + SignInPath: fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), + OauthStartPath: fmt.Sprintf("%s/start", opts.ProxyPrefix), + OauthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), + clientID: opts.ClientID, clientSecret: opts.ClientSecret, + ProxyPrefix: opts.ProxyPrefix, oauthScope: opts.provider.Data().Scope, provider: opts.provider, oauthLoginUrl: opts.provider.Data().LoginUrl, @@ -300,7 +308,7 @@ func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code rw.WriteHeader(code) redirect_url := req.URL.RequestURI() - if redirect_url == signInPath { + if redirect_url == p.SignInPath { redirect_url = "/" } @@ -310,12 +318,14 @@ func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code CustomLogin bool Redirect string Version string + ProxyPrefix string }{ ProviderName: p.provider.Data().ProviderName, SignInMessage: p.SignInMessage, CustomLogin: p.displayCustomLoginForm(), Redirect: redirect_url, Version: VERSION, + ProxyPrefix: p.ProxyPrefix, } p.templates.ExecuteTemplate(rw, "sign_in.html", t) } @@ -365,12 +375,12 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { var email string var access_token string - if req.URL.Path == robotsPath { + if req.URL.Path == p.RobotsPath { p.RobotsTxt(rw) return } - if req.URL.Path == pingPath { + if req.URL.Path == p.PingPath { p.PingPage(rw) return } @@ -384,7 +394,7 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } - if req.URL.Path == signInPath { + if req.URL.Path == p.SignInPath { redirect, err := p.GetRedirect(req) if err != nil { p.ErrorPage(rw, 500, "Internal Error", err.Error()) @@ -400,7 +410,7 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } return } - if req.URL.Path == oauthStartPath { + if req.URL.Path == p.OauthStartPath { redirect, err := p.GetRedirect(req) if err != nil { p.ErrorPage(rw, 500, "Internal Error", err.Error()) @@ -409,7 +419,7 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { http.Redirect(rw, req, p.GetLoginURL(req.Host, redirect), 302) return } - if req.URL.Path == oauthCallbackPath { + if req.URL.Path == p.OauthCallbackPath { // finish the oauth cycle err := req.ParseForm() if err != nil { diff --git a/options.go b/options.go index 4c1ccce..476ed26 100644 --- a/options.go +++ b/options.go @@ -12,6 +12,7 @@ import ( // Configuration Options that can be set by Command Line Flag, or Config File type Options struct { + ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy-prefix"` HttpAddress string `flag:"http-address" cfg:"http_address"` RedirectUrl string `flag:"redirect-url" cfg:"redirect_url"` ClientID string `flag:"client-id" cfg:"client_id" env:"OAUTH2_PROXY_CLIENT_ID"` @@ -25,6 +26,7 @@ type Options struct { DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form"` CustomTemplatesDir string `flag:"custom-templates-dir" cfg:"custom_templates_dir"` + CookieKey string `flag:"cookie-key" cfg:"cookie_key" env:"OAUTH2_PROXY_COOKIE_KEY"` CookieSecret string `flag:"cookie-secret" cfg:"cookie_secret" env:"OAUTH2_PROXY_COOKIE_SECRET"` CookieDomain string `flag:"cookie-domain" cfg:"cookie_domain" env:"OAUTH2_PROXY_COOKIE_DOMAIN"` CookieExpire time.Duration `flag:"cookie-expire" cfg:"cookie_expire" env:"OAUTH2_PROXY_COOKIE_EXPIRE"` @@ -59,8 +61,10 @@ type Options struct { func NewOptions() *Options { return &Options{ + ProxyPrefix: "/oauth2", HttpAddress: "127.0.0.1:4180", DisplayHtpasswdForm: true, + CookieKey: "_oauthproxy", CookieHttpsOnly: true, CookieSecure: true, CookieHttpOnly: true, diff --git a/templates.go b/templates.go index b72a656..c752273 100644 --- a/templates.go +++ b/templates.go @@ -110,7 +110,7 @@ func getTemplates() *template.Template {