package api import ( "net/url" "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/metrics" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) const ( ViewIndex = "index" ) func (hs *HTTPServer) LoginView(c *m.ReqContext) { viewData, err := hs.setIndexViewData(c) if err != nil { c.Handle(500, "Failed to get settings", err) return } enabledOAuths := make(map[string]interface{}) for key, oauth := range setting.OAuthService.OAuthInfos { enabledOAuths[key] = map[string]string{"name": oauth.Name} } viewData.Settings["oauth"] = enabledOAuths viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp viewData.Settings["loginHint"] = setting.LoginHint viewData.Settings["disableLoginForm"] = setting.DisableLoginForm if loginError, ok := c.Session.Get("loginError").(string); ok { c.Session.Delete("loginError") viewData.Settings["loginError"] = loginError } if tryOAuthAutoLogin(c) { return } //if !hs.tryLoginUsingRememberCookie(c) { c.HTML(200, ViewIndex, viewData) return //} // if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 { // c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/") // c.Redirect(redirectTo) // return // } // c.Redirect(setting.AppSubUrl + "/") } func tryOAuthAutoLogin(c *m.ReqContext) bool { if !setting.OAuthAutoLogin { return false } oauthInfos := setting.OAuthService.OAuthInfos if len(oauthInfos) != 1 { log.Warn("Skipping OAuth auto login because multiple OAuth providers are configured.") return false } for key := range setting.OAuthService.OAuthInfos { redirectUrl := setting.AppSubUrl + "/login/" + key log.Info("OAuth auto login enabled. Redirecting to " + redirectUrl) c.Redirect(redirectUrl, 307) return true } return false } func (hs *HTTPServer) tryLoginUsingRememberCookie(c *m.ReqContext) bool { // Check auto-login. uname := c.GetCookie(setting.CookieUserName) if len(uname) == 0 { return false } isSucceed := false defer func() { if !isSucceed { log.Trace("auto-login cookie cleared: %s", uname) c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/") c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/") return } }() userQuery := m.GetUserByLoginQuery{LoginOrEmail: uname} if err := bus.Dispatch(&userQuery); err != nil { return false } user := userQuery.Result // validate remember me cookie signingKey := user.Rands + user.Password if len(signingKey) < 10 { c.Logger.Error("Invalid user signingKey") return false } if val, _ := c.GetSuperSecureCookie(signingKey, setting.CookieRememberName); val != user.Login { return false } isSucceed = true hs.loginUserWithUser(user, c) return true } func (hs *HTTPServer) LoginAPIPing(c *m.ReqContext) { if !hs.tryLoginUsingRememberCookie(c) { c.JsonApiErr(401, "Unauthorized", nil) return } c.JsonOK("Logged in") } func (hs *HTTPServer) LoginPost(c *m.ReqContext, cmd dtos.LoginCommand) Response { if setting.DisableLoginForm { return Error(401, "Login is disabled", nil) } authQuery := &m.LoginUserQuery{ ReqContext: c, Username: cmd.User, Password: cmd.Password, IpAddress: c.Req.RemoteAddr, } if err := bus.Dispatch(authQuery); err != nil { if err == login.ErrInvalidCredentials || err == login.ErrTooManyLoginAttempts { return Error(401, "Invalid username or password", err) } return Error(500, "Error while trying to authenticate user", err) } user := authQuery.User hs.loginUserWithUser(user, c) result := map[string]interface{}{ "message": "Logged in", } if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 { result["redirectUrl"] = redirectTo c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/") } metrics.M_Api_Login_Post.Inc() return JSON(200, result) } func (hs *HTTPServer) loginUserWithUser(user *m.User, c *m.ReqContext) { if user == nil { hs.log.Error("User login with nil user") } err := hs.AuthTokenService.UserAuthenticatedHook(user, c) if err != nil { hs.log.Error("User auth hook failed", "error", err) } } func (hs *HTTPServer) Logout(c *m.ReqContext) { hs.AuthTokenService.UserSignedOutHook(c) if setting.SignoutRedirectUrl != "" { c.Redirect(setting.SignoutRedirectUrl) } else { c.Redirect(setting.AppSubUrl + "/login") } }