| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	"net/url" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/dtos" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/bus" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/log" | 
					
						
							| 
									
										
										
										
											2015-07-15 16:08:23 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/login" | 
					
						
							| 
									
										
										
										
											2015-03-23 03:14:00 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/metrics" | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	m "github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2018-03-07 06:59:45 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/session" | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | 	ViewIndex = "index" | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 17:26:42 +08:00
										 |  |  | func (hs *HTTPServer) LoginView(c *m.ReqContext) { | 
					
						
							|  |  |  | 	viewData, err := hs.setIndexViewData(c) | 
					
						
							| 
									
										
										
										
											2015-11-20 16:43:10 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-01-27 17:09:54 +08:00
										 |  |  | 		c.Handle(500, "Failed to get settings", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 21:10:50 +08:00
										 |  |  | 	enabledOAuths := make(map[string]interface{}) | 
					
						
							|  |  |  | 	for key, oauth := range setting.OAuthService.OAuthInfos { | 
					
						
							|  |  |  | 		enabledOAuths[key] = map[string]string{"name": oauth.Name} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	viewData.Settings["oauth"] = enabledOAuths | 
					
						
							| 
									
										
										
										
											2015-11-20 16:43:10 +08:00
										 |  |  | 	viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp | 
					
						
							| 
									
										
										
										
											2015-12-15 00:28:57 +08:00
										 |  |  | 	viewData.Settings["loginHint"] = setting.LoginHint | 
					
						
							| 
									
										
										
										
											2016-09-28 21:27:08 +08:00
										 |  |  | 	viewData.Settings["disableLoginForm"] = setting.DisableLoginForm | 
					
						
							| 
									
										
										
										
											2015-01-28 17:26:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 21:32:51 +08:00
										 |  |  | 	if loginError, ok := c.Session.Get("loginError").(string); ok { | 
					
						
							| 
									
										
										
										
											2017-03-23 22:26:13 +08:00
										 |  |  | 		c.Session.Delete("loginError") | 
					
						
							| 
									
										
										
										
											2017-02-01 21:32:51 +08:00
										 |  |  | 		viewData.Settings["loginError"] = loginError | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 22:16:48 +08:00
										 |  |  | 	if tryOAuthAutoLogin(c) { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 	if !tryLoginUsingRememberCookie(c) { | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | 		c.HTML(200, ViewIndex, viewData) | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 		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 + "/") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 22:16:48 +08:00
										 |  |  | 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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-08 00:54:50 +08:00
										 |  |  | func tryLoginUsingRememberCookie(c *m.ReqContext) bool { | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	// Check auto-login.
 | 
					
						
							|  |  |  | 	uname := c.GetCookie(setting.CookieUserName) | 
					
						
							|  |  |  | 	if len(uname) == 0 { | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user := userQuery.Result | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 	// validate remember me cookie
 | 
					
						
							| 
									
										
										
										
											2018-08-21 19:30:39 +08:00
										 |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isSucceed = true | 
					
						
							|  |  |  | 	loginUserWithUser(user, c) | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | func LoginAPIPing(c *m.ReqContext) { | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 	if !tryLoginUsingRememberCookie(c) { | 
					
						
							|  |  |  | 		c.JsonApiErr(401, "Unauthorized", nil) | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 15:25:00 +08:00
										 |  |  | 	c.JsonOK("Logged in") | 
					
						
							| 
									
										
										
										
											2015-01-27 17:09:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-08 00:54:50 +08:00
										 |  |  | func LoginPost(c *m.ReqContext, cmd dtos.LoginCommand) Response { | 
					
						
							| 
									
										
										
										
											2017-03-18 04:35:05 +08:00
										 |  |  | 	if setting.DisableLoginForm { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(401, "Login is disabled", nil) | 
					
						
							| 
									
										
										
										
											2017-03-18 04:35:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 03:50:07 +08:00
										 |  |  | 	authQuery := &m.LoginUserQuery{ | 
					
						
							|  |  |  | 		ReqContext: c, | 
					
						
							|  |  |  | 		Username:   cmd.User, | 
					
						
							|  |  |  | 		Password:   cmd.Password, | 
					
						
							|  |  |  | 		IpAddress:  c.Req.RemoteAddr, | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 03:50:07 +08:00
										 |  |  | 	if err := bus.Dispatch(authQuery); err != nil { | 
					
						
							| 
									
										
										
										
											2018-01-26 17:41:41 +08:00
										 |  |  | 		if err == login.ErrInvalidCredentials || err == login.ErrTooManyLoginAttempts { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(401, "Invalid username or password", err) | 
					
						
							| 
									
										
										
										
											2015-06-04 15:34:42 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Error while trying to authenticate user", err) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-10 17:10:48 +08:00
										 |  |  | 	user := authQuery.User | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-20 01:01:04 +08:00
										 |  |  | 	loginUserWithUser(user, c) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	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+"/") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-06 17:23:52 +08:00
										 |  |  | 	metrics.M_Api_Login_Post.Inc() | 
					
						
							| 
									
										
										
										
											2015-03-23 03:14:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, result) | 
					
						
							| 
									
										
										
										
											2015-06-04 15:34:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-08 00:54:50 +08:00
										 |  |  | func loginUserWithUser(user *m.User, c *m.ReqContext) { | 
					
						
							| 
									
										
										
										
											2015-01-20 01:01:04 +08:00
										 |  |  | 	if user == nil { | 
					
						
							|  |  |  | 		log.Error(3, "User login with nil user") | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-21 17:10:59 +08:00
										 |  |  | 	c.Resp.Header().Del("Set-Cookie") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 19:38:38 +08:00
										 |  |  | 	days := 86400 * setting.LogInRememberDays | 
					
						
							| 
									
										
										
										
											2016-03-08 00:26:31 +08:00
										 |  |  | 	if days > 0 { | 
					
						
							|  |  |  | 		c.SetCookie(setting.CookieUserName, user.Login, days, setting.AppSubUrl+"/") | 
					
						
							| 
									
										
										
										
											2017-04-25 21:29:44 +08:00
										 |  |  | 		c.SetSuperSecureCookie(user.Rands+user.Password, setting.CookieRememberName, user.Login, days, setting.AppSubUrl+"/") | 
					
						
							| 
									
										
										
										
											2016-03-08 00:26:31 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-15 19:38:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-07 06:59:45 +08:00
										 |  |  | 	c.Session.RegenerateId(c.Context) | 
					
						
							|  |  |  | 	c.Session.Set(session.SESS_KEY_USERID, user.Id) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-08 00:54:50 +08:00
										 |  |  | func Logout(c *m.ReqContext) { | 
					
						
							| 
									
										
										
										
											2015-01-27 19:05:23 +08:00
										 |  |  | 	c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/") | 
					
						
							|  |  |  | 	c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/") | 
					
						
							| 
									
										
										
										
											2018-03-07 06:59:45 +08:00
										 |  |  | 	c.Session.Destory(c.Context) | 
					
						
							| 
									
										
										
										
											2018-05-27 20:52:50 +08:00
										 |  |  | 	if setting.SignoutRedirectUrl != "" { | 
					
						
							|  |  |  | 		c.Redirect(setting.SignoutRedirectUrl) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		c.Redirect(setting.AppSubUrl + "/login") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } |