Pārlūkot izejas kodu

store oauth login error messages in an encrypted cookie

bergquist 7 gadi atpakaļ
vecāks
revīzija
4626f083bb
2 mainītis faili ar 53 papildinājumiem un 10 dzēšanām
  1. 44 3
      pkg/api/login.go
  2. 9 7
      pkg/api/login_oauth.go

+ 44 - 3
pkg/api/login.go

@@ -1,6 +1,8 @@
 package api
 
 import (
+	"encoding/hex"
+	"net/http"
 	"net/url"
 
 	"github.com/grafana/grafana/pkg/api/dtos"
@@ -10,10 +12,12 @@ import (
 	"github.com/grafana/grafana/pkg/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
+	"github.com/grafana/grafana/pkg/util"
 )
 
 const (
-	ViewIndex = "index"
+	ViewIndex            = "index"
+	LoginErrorCookieName = "login_error"
 )
 
 func (hs *HTTPServer) LoginView(c *m.ReqContext) {
@@ -33,8 +37,8 @@ func (hs *HTTPServer) LoginView(c *m.ReqContext) {
 	viewData.Settings["loginHint"] = setting.LoginHint
 	viewData.Settings["disableLoginForm"] = setting.DisableLoginForm
 
-	if loginError, ok := c.Session.Get("loginError").(string); ok {
-		c.Session.Delete("loginError")
+	if loginError, ok := tryGetEncryptedCookie(c, LoginErrorCookieName); ok {
+		deleteCookie(c, LoginErrorCookieName)
 		viewData.Settings["loginError"] = loginError
 	}
 
@@ -141,3 +145,40 @@ func (hs *HTTPServer) Logout(c *m.ReqContext) {
 		c.Redirect(setting.AppSubUrl + "/login")
 	}
 }
+
+func tryGetEncryptedCookie(ctx *m.ReqContext, cookieName string) (string, bool) {
+	cookie := ctx.GetCookie(cookieName)
+	if cookie == "" {
+		return "", false
+	}
+
+	decoded, err := hex.DecodeString(cookie)
+	if err != nil {
+		return "", false
+	}
+
+	decryptedError, err := util.Decrypt([]byte(decoded), setting.SecretKey)
+	return string(decryptedError), err == nil
+}
+
+func deleteCookie(ctx *m.ReqContext, cookieName string) {
+	ctx.SetCookie(cookieName, "", -1, setting.AppSubUrl+"/")
+}
+
+func (hs *HTTPServer) trySetEncryptedCookie(ctx *m.ReqContext, cookieName string, value string, maxAge int) error {
+	encryptedError, err := util.Encrypt([]byte(value), setting.SecretKey)
+	if err != nil {
+		return err
+	}
+
+	http.SetCookie(ctx.Resp, &http.Cookie{
+		Name:     cookieName,
+		MaxAge:   60,
+		Value:    hex.EncodeToString(encryptedError),
+		HttpOnly: true,
+		Path:     setting.AppSubUrl + "/",
+		Secure:   hs.Cfg.LoginCookieSecure,
+	})
+
+	return nil
+}

+ 9 - 7
pkg/api/login_oauth.go

@@ -52,7 +52,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
 	if errorParam != "" {
 		errorDesc := ctx.Query("error_description")
 		oauthLogger.Error("failed to login ", "error", errorParam, "errorDesc", errorDesc)
-		redirectWithError(ctx, login.ErrProviderDeniedRequest, "error", errorParam, "errorDesc", errorDesc)
+		hs.redirectWithError(ctx, login.ErrProviderDeniedRequest, "error", errorParam, "errorDesc", errorDesc)
 		return
 	}
 
@@ -142,7 +142,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
 	userInfo, err := connect.UserInfo(client, token)
 	if err != nil {
 		if sErr, ok := err.(*social.Error); ok {
-			redirectWithError(ctx, sErr)
+			hs.redirectWithError(ctx, sErr)
 		} else {
 			ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
 		}
@@ -153,13 +153,13 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
 
 	// validate that we got at least an email address
 	if userInfo.Email == "" {
-		redirectWithError(ctx, login.ErrNoEmail)
+		hs.redirectWithError(ctx, login.ErrNoEmail)
 		return
 	}
 
 	// validate that the email is allowed to login to grafana
 	if !connect.IsEmailAllowed(userInfo.Email) {
-		redirectWithError(ctx, login.ErrEmailNotAllowed)
+		hs.redirectWithError(ctx, login.ErrEmailNotAllowed)
 		return
 	}
 
@@ -182,9 +182,10 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
 		ExternalUser:  extUser,
 		SignupAllowed: connect.IsSignupAllowed(),
 	}
+
 	err = bus.Dispatch(cmd)
 	if err != nil {
-		redirectWithError(ctx, err)
+		hs.redirectWithError(ctx, err)
 		return
 	}
 
@@ -218,8 +219,9 @@ func hashStatecode(code, seed string) string {
 	return hex.EncodeToString(hashBytes[:])
 }
 
-func redirectWithError(ctx *m.ReqContext, err error, v ...interface{}) {
+func (hs *HTTPServer) redirectWithError(ctx *m.ReqContext, err error, v ...interface{}) {
 	ctx.Logger.Error(err.Error(), v...)
-	ctx.Session.Set("loginError", err.Error())
+	hs.trySetEncryptedCookie(ctx, LoginErrorCookieName, err.Error(), 60)
+
 	ctx.Redirect(setting.AppSubUrl + "/login")
 }