@@ -213,6 +213,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
213213 trustedIPs: trustedIPs,
214214 Banner: opts.Banner,
215215 Footer: opts.Footer,
216+ SignInMessage: buildSignInMessage(opts),
216217
217218 basicAuthValidator: basicAuthValidator,
218219 displayHtpasswdForm: basicAuthValidator != nil,
@@ -255,6 +256,24 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
255256 return chain
256257}
257258
259+func buildSignInMessage(opts *options.Options) string {
260+ var msg string
261+ if len(opts.Banner) >= 1 {
262+ if opts.Banner == "-" {
263+ msg = ""
264+ } else {
265+ msg = opts.Banner
266+ }
267+ } else if len(opts.EmailDomains) != 0 && opts.AuthenticatedEmailsFile == "" {
268+ if len(opts.EmailDomains) > 1 {
269+ msg = fmt.Sprintf("Authenticate using one of the following domains: %v", strings.Join(opts.EmailDomains, ", "))
270+ } else if opts.EmailDomains[0] != "*" {
271+ msg = fmt.Sprintf("Authenticate using %v", opts.EmailDomains[0])
272+ }
273+ }
274+ return msg
275+}
276+
258277// GetRedirectURI returns the redirectURL that the upstream OAuth Provider will
259278// redirect clients to once authenticated
260279func (p *OAuthProxy) GetRedirectURI(host string) string {
@@ -363,8 +382,13 @@ func (p *OAuthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *s
363382
364383// RobotsTxt disallows scraping pages from the OAuthProxy
365384func (p *OAuthProxy) RobotsTxt(rw http.ResponseWriter) {
385+ _, err := fmt.Fprintf(rw, "User-agent: *\nDisallow: /")
386+ if err != nil {
387+ logger.Printf("Error writing robots.txt: %v", err)
388+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
389+ return
390+ }
366391 rw.WriteHeader(http.StatusOK)
367− fmt.Fprintf(rw, "User-agent: *\nDisallow: /")
368392}
369393
370394// ErrorPage writes an error response
@@ -379,19 +403,28 @@ func (p *OAuthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, m
379403 Message: message,
380404 ProxyPrefix: p.ProxyPrefix,
381405 }
382− p.templates.ExecuteTemplate(rw, "error.html", t)
406+ err := p.templates.ExecuteTemplate(rw, "error.html", t)
407+ if err != nil {
408+ logger.Printf("Error rendering error.html template: %v", err)
409+ http.Error(rw, "Internal Server Error", http.StatusInternalServerError)
410+ }
383411}
384412
385413// SignInPage writes the sing in template to the response
386414func (p *OAuthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) {
387415 prepareNoCache(rw)
388− p.ClearSessionCookie(rw, req)
416+ err := p.ClearSessionCookie(rw, req)
417+ if err != nil {
418+ logger.Printf("Error clearing session cookie: %v", err)
419+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
420+ return
421+ }
389422 rw.WriteHeader(code)
390423
391424 redirectURL, err := p.GetRedirect(req)
392425 if err != nil {
393− logger.Printf("Error obtaining redirect: %s", err.Error())
394− p.ErrorPage(rw, 500, "Internal Error", err.Error())
426+ logger.Printf("Error obtaining redirect: %v", err)
427+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
395428 return
396429 }
397430
@@ -399,6 +432,8 @@ func (p *OAuthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code
399432 redirectURL = "/"
400433 }
401434
435+ // We allow unescaped template.HTML since it is user configured options
436+ /* #nosec G203 */
402437 t := struct {
403438 ProviderName string
404439 SignInMessage template.HTML
@@ -419,11 +454,15 @@ func (p *OAuthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code
419454 if p.providerNameOverride != "" {
420455 t.ProviderName = p.providerNameOverride
421456 }
422− p.templates.ExecuteTemplate(rw, "sign_in.html", t)
457+ err = p.templates.ExecuteTemplate(rw, "sign_in.html", t)
458+ if err != nil {
459+ logger.Printf("Error rendering sign_in.html template: %v", err)
460+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
461+ }
423462}
424463
425464// ManualSignIn handles basic auth logins to the proxy
426−func (p *OAuthProxy) ManualSignIn(rw http.ResponseWriter, req *http.Request) (string, bool) {
465+func (p *OAuthProxy) ManualSignIn(req *http.Request) (string, bool) {
427466 if req.Method != "POST" || p.basicAuthValidator == nil {
428467 return "", false
429468 }
@@ -627,15 +666,20 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
627666func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) {
628667 redirect, err := p.GetRedirect(req)
629668 if err != nil {
630− logger.Printf("Error obtaining redirect: %s", err.Error())
631− p.ErrorPage(rw, 500, "Internal Error", err.Error())
669+ logger.Printf("Error obtaining redirect: %v", err)
670+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
632671 return
633672 }
634673
635− user, ok := p.ManualSignIn(rw, req)
674+ user, ok := p.ManualSignIn(req)
636675 if ok {
637676 session := &sessionsapi.SessionState{User: user}
638− p.SaveSession(rw, req, session)
677+ err = p.SaveSession(rw, req, session)
678+ if err != nil {
679+ logger.Printf("Error saving session: %v", err)
680+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
681+ return
682+ }
639683 http.Redirect(rw, req, redirect, http.StatusFound)
640684 } else {
641685 if p.SkipProviderButton {
@@ -663,18 +707,27 @@ func (p *OAuthProxy) UserInfo(rw http.ResponseWriter, req *http.Request) {
663707 }
664708 rw.Header().Set("Content-Type", "application/json")
665709 rw.WriteHeader(http.StatusOK)
666− json.NewEncoder(rw).Encode(userInfo)
710+ err = json.NewEncoder(rw).Encode(userInfo)
711+ if err != nil {
712+ logger.Printf("Error encoding user info: %v", err)
713+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
714+ }
667715}
668716
669717// SignOut sends a response to clear the authentication cookie
670718func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) {
671719 redirect, err := p.GetRedirect(req)
672720 if err != nil {
673− logger.Printf("Error obtaining redirect: %s", err.Error())
674− p.ErrorPage(rw, 500, "Internal Error", err.Error())
721+ logger.Printf("Error obtaining redirect: %v", err)
722+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
723+ return
724+ }
725+ err = p.ClearSessionCookie(rw, req)
726+ if err != nil {
727+ logger.Printf("Error clearing session cookie: %v", err)
728+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
675729 return
676730 }
677− p.ClearSessionCookie(rw, req)
678731 http.Redirect(rw, req, redirect, http.StatusFound)
679732}
680733
@@ -683,15 +736,15 @@ func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) {
683736 prepareNoCache(rw)
684737 nonce, err := encryption.Nonce()
685738 if err != nil {
686− logger.Printf("Error obtaining nonce: %s", err.Error())
687− p.ErrorPage(rw, 500, "Internal Error", err.Error())
739+ logger.Printf("Error obtaining nonce: %v", err)
740+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
688741 return
689742 }
690743 p.SetCSRFCookie(rw, req, nonce)
691744 redirect, err := p.GetRedirect(req)
692745 if err != nil {
693− logger.Printf("Error obtaining redirect: %s", err.Error())
694− p.ErrorPage(rw, 500, "Internal Error", err.Error())
746+ logger.Printf("Error obtaining redirect: %v", err)
747+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
695748 return
696749 }
697750 redirectURI := p.GetRedirectURI(req.Host)
@@ -706,42 +759,42 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
706759 // finish the oauth cycle
707760 err := req.ParseForm()
708761 if err != nil {
709− logger.Printf("Error while parsing OAuth2 callback: %s" + err.Error())
710− p.ErrorPage(rw, 500, "Internal Error", err.Error())
762+ logger.Printf("Error while parsing OAuth2 callback: %v", err)
763+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
711764 return
712765 }
713766 errorString := req.Form.Get("error")
714767 if errorString != "" {
715− logger.Printf("Error while parsing OAuth2 callback: %s ", errorString)
716− p.ErrorPage(rw, 403, "Permission Denied", errorString)
768+ logger.Printf("Error while parsing OAuth2 callback: %s", errorString)
769+ p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", errorString)
717770 return
718771 }
719772
720773 session, err := p.redeemCode(req.Context(), req.Host, req.Form.Get("code"))
721774 if err != nil {
722− logger.Printf("Error redeeming code during OAuth2 callback: %s ", err.Error())
723− p.ErrorPage(rw, 500, "Internal Error", "Internal Error")
775+ logger.Printf("Error redeeming code during OAuth2 callback: %v", err)
776+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Internal Error")
724777 return
725778 }
726779
727780 s := strings.SplitN(req.Form.Get("state"), ":", 2)
728781 if len(s) != 2 {
729782 logger.Printf("Error while parsing OAuth2 state: invalid length")
730− p.ErrorPage(rw, 500, "Internal Error", "Invalid State")
783+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Invalid State")
731784 return
732785 }
733786 nonce := s[0]
734787 redirect := s[1]
735788 c, err := req.Cookie(p.CSRFCookieName)
736789 if err != nil {
737− logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: unable too obtain CSRF cookie")
738− p.ErrorPage(rw, 403, "Permission Denied", err.Error())
790+ logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: unable to obtain CSRF cookie")
791+ p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", err.Error())
739792 return
740793 }
741794 p.ClearCSRFCookie(rw, req)
742795 if c.Value != nonce {
743− logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: csrf token mismatch, potential attack")
744− p.ErrorPage(rw, 403, "Permission Denied", "csrf failed")
796+ logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: CSRF token mismatch, potential attack")
797+ p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", "CSRF Failed")
745798 return
746799 }
747800
@@ -754,14 +807,14 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
754807 logger.PrintAuthf(session.Email, req, logger.AuthSuccess, "Authenticated via OAuth2: %s", session)
755808 err := p.SaveSession(rw, req, session)
756809 if err != nil {
757− logger.Printf("%s %s", remoteAddr, err)
758− p.ErrorPage(rw, 500, "Internal Error", "Internal Error")
810+ logger.Printf("Error saving session state for %s: %v", remoteAddr, err)
811+ p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
759812 return
760813 }
761814 http.Redirect(rw, req, redirect, http.StatusFound)
762815 } else {
763816 logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: unauthorized")
764− p.ErrorPage(rw, 403, "Permission Denied", "Invalid Account")
817+ p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", "Invalid Account")
765818 }
766819}
767820
@@ -837,7 +890,10 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
837890 if session != nil && session.Email != "" && !p.Validator(session.Email) {
838891 logger.Printf(session.Email, req, logger.AuthFailure, "Invalid authentication via session: removing session %s", session)
839892 // Invalid session, clear it
840− p.ClearSessionCookie(rw, req)
893+ err := p.ClearSessionCookie(rw, req)
894+ if err != nil {
895+ logger.Printf("Error clearing session cookie: %v", err)
896+ }
841897 return nil, ErrNeedsLogin
842898 }
843899