From e574147b1e59be0366e0e550785efc3c71381330 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Fri, 5 Jul 2019 15:24:52 +0200 Subject: [PATCH] Auth: SAML login button. (#17932) * Auth: SAML login button. * Fixed ts issue --- packages/grafana-runtime/src/config.ts | 1 + pkg/api/login.go | 34 +++++++++++++++-------- pkg/models/saml.go | 5 ++++ public/app/core/controllers/login_ctrl.ts | 1 + public/app/partials/login.html | 4 +++ 5 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 pkg/models/saml.go diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 51d313597e3..0c46072c3ea 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -30,6 +30,7 @@ export class GrafanaBootConfig { authProxyEnabled = false; exploreEnabled = false; ldapEnabled = false; + samlEnabled = false; oauth: any; disableUserSignUp = false; loginHint: any; diff --git a/pkg/api/login.go b/pkg/api/login.go index 975a905853c..fd51a41fbdf 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -11,7 +11,7 @@ import ( "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/middleware" - m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -21,7 +21,7 @@ const ( LoginErrorCookieName = "login_error" ) -func (hs *HTTPServer) LoginView(c *m.ReqContext) { +func (hs *HTTPServer) LoginView(c *models.ReqContext) { viewData, err := hs.setIndexViewData(c) if err != nil { c.Handle(500, "Failed to get settings", err) @@ -38,6 +38,7 @@ func (hs *HTTPServer) LoginView(c *m.ReqContext) { viewData.Settings["loginHint"] = setting.LoginHint viewData.Settings["passwordHint"] = setting.PasswordHint viewData.Settings["disableLoginForm"] = setting.DisableLoginForm + viewData.Settings["samlEnabled"] = isSamlEnabled() if loginError, ok := tryGetEncryptedCookie(c, LoginErrorCookieName); ok { deleteCookie(c, LoginErrorCookieName) @@ -62,7 +63,16 @@ func (hs *HTTPServer) LoginView(c *m.ReqContext) { c.Redirect(setting.AppSubUrl + "/") } -func tryOAuthAutoLogin(c *m.ReqContext) bool { +func isSamlEnabled() bool { + enabledCmd := models.IsSAMLEnabledCommand{} + if err := bus.Dispatch(&enabledCmd); err != nil { + return false + } + + return enabledCmd.Result +} + +func tryOAuthAutoLogin(c *models.ReqContext) bool { if !setting.OAuthAutoLogin { return false } @@ -80,7 +90,7 @@ func tryOAuthAutoLogin(c *m.ReqContext) bool { return false } -func (hs *HTTPServer) LoginAPIPing(c *m.ReqContext) Response { +func (hs *HTTPServer) LoginAPIPing(c *models.ReqContext) Response { if c.IsSignedIn || c.IsAnonymous { return JSON(200, "Logged in") } @@ -88,12 +98,12 @@ func (hs *HTTPServer) LoginAPIPing(c *m.ReqContext) Response { return Error(401, "Unauthorized", nil) } -func (hs *HTTPServer) LoginPost(c *m.ReqContext, cmd dtos.LoginCommand) Response { +func (hs *HTTPServer) LoginPost(c *models.ReqContext, cmd dtos.LoginCommand) Response { if setting.DisableLoginForm { return Error(401, "Login is disabled", nil) } - authQuery := &m.LoginUserQuery{ + authQuery := &models.LoginUserQuery{ ReqContext: c, Username: cmd.User, Password: cmd.Password, @@ -129,7 +139,7 @@ func (hs *HTTPServer) LoginPost(c *m.ReqContext, cmd dtos.LoginCommand) Response return JSON(200, result) } -func (hs *HTTPServer) loginUserWithUser(user *m.User, c *m.ReqContext) { +func (hs *HTTPServer) loginUserWithUser(user *models.User, c *models.ReqContext) { if user == nil { hs.log.Error("user login with nil user") } @@ -142,8 +152,8 @@ func (hs *HTTPServer) loginUserWithUser(user *m.User, c *m.ReqContext) { middleware.WriteSessionCookie(c, userToken.UnhashedToken, hs.Cfg.LoginMaxLifetimeDays) } -func (hs *HTTPServer) Logout(c *m.ReqContext) { - if err := hs.AuthTokenService.RevokeToken(c.Req.Context(), c.UserToken); err != nil && err != m.ErrUserTokenNotFound { +func (hs *HTTPServer) Logout(c *models.ReqContext) { + if err := hs.AuthTokenService.RevokeToken(c.Req.Context(), c.UserToken); err != nil && err != models.ErrUserTokenNotFound { hs.log.Error("failed to revoke auth token", "error", err) } @@ -157,7 +167,7 @@ func (hs *HTTPServer) Logout(c *m.ReqContext) { } } -func tryGetEncryptedCookie(ctx *m.ReqContext, cookieName string) (string, bool) { +func tryGetEncryptedCookie(ctx *models.ReqContext, cookieName string) (string, bool) { cookie := ctx.GetCookie(cookieName) if cookie == "" { return "", false @@ -172,11 +182,11 @@ func tryGetEncryptedCookie(ctx *m.ReqContext, cookieName string) (string, bool) return string(decryptedError), err == nil } -func deleteCookie(ctx *m.ReqContext, cookieName string) { +func deleteCookie(ctx *models.ReqContext, cookieName string) { ctx.SetCookie(cookieName, "", -1, setting.AppSubUrl+"/") } -func (hs *HTTPServer) trySetEncryptedCookie(ctx *m.ReqContext, cookieName string, value string, maxAge int) error { +func (hs *HTTPServer) trySetEncryptedCookie(ctx *models.ReqContext, cookieName string, value string, maxAge int) error { encryptedError, err := util.Encrypt([]byte(value), setting.SecretKey) if err != nil { return err diff --git a/pkg/models/saml.go b/pkg/models/saml.go new file mode 100644 index 00000000000..f19d53048c5 --- /dev/null +++ b/pkg/models/saml.go @@ -0,0 +1,5 @@ +package models + +type IsSAMLEnabledCommand struct { + Result bool +} diff --git a/public/app/core/controllers/login_ctrl.ts b/public/app/core/controllers/login_ctrl.ts index 991ce1146a6..145a5517051 100644 --- a/public/app/core/controllers/login_ctrl.ts +++ b/public/app/core/controllers/login_ctrl.ts @@ -20,6 +20,7 @@ export class LoginCtrl { $scope.oauthEnabled = _.keys(config.oauth).length > 0; $scope.ldapEnabled = config.ldapEnabled; $scope.authProxyEnabled = config.authProxyEnabled; + $scope.samlEnabled = config.samlEnabled; $scope.disableLoginForm = config.disableLoginForm; $scope.disableUserSignUp = config.disableUserSignUp; diff --git a/public/app/partials/login.html b/public/app/partials/login.html index 55bd8060a4f..8acc0527fdb 100644 --- a/public/app/partials/login.html +++ b/public/app/partials/login.html @@ -68,6 +68,10 @@ Sign in with {{oauth.generic_oauth.name}} + + + Sign in with SAML +