From f49b4d35f225b4f342edb3df6ce099cf97fb662f Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:11:27 +0200 Subject: [PATCH] OAuth: Add custom unauthorized message option in configuration (#93717) * read custom message from config * Read error key from bootdata * oopsie * Remove console.log * Update docs and sample/default inis * Add default key value to the config --- conf/defaults.ini | 3 +++ conf/sample.ini | 3 +++ .../setup-grafana/configure-grafana/_index.md | 4 ++++ pkg/api/login_oauth.go | 6 ++---- pkg/setting/setting.go | 3 +++ public/app/core/components/Login/LoginCtrl.tsx | 12 +++++++++++- public/locales/en-US/grafana.json | 3 +++ public/locales/pseudo-LOCALE/grafana.json | 3 +++ 8 files changed, 32 insertions(+), 5 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index c29619e741e..8baa6296110 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -582,6 +582,9 @@ oauth_auto_login = false # OAuth state max age cookie duration in seconds. Defaults to 600 seconds. oauth_state_cookie_max_age = 600 +# Sets a custom oAuth error message. This is useful if you need to point the users to a specific location for support. +oauth_login_error_message = oauth.login.error + # Minimum wait time in milliseconds for the server lock retry mechanism. # The server lock retry mechanism is used to prevent multiple Grafana instances from # simultaneously refreshing OAuth tokens. This mechanism waits at least this amount diff --git a/conf/sample.ini b/conf/sample.ini index aa74245e2c1..099de883121 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -583,6 +583,9 @@ # Deprecated, use auto_login option for specific provider instead. ;oauth_auto_login = false +# Sets a custom oAuth error message. This is useful if you need to point the users to a specific location for support. +;oauth_login_error_message = oauth.login.error + # OAuth state max age cookie duration in seconds. Defaults to 600 seconds. ;oauth_state_cookie_max_age = 600 diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index a0089a233fe..de2e43e06c3 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -964,6 +964,10 @@ This setting is ignored if multiple OAuth providers are configured. Default is ` How many seconds the OAuth state cookie lives before being deleted. Default is `600` (seconds) Administrators can increase this if they experience OAuth login state mismatch errors. +### oauth_login_error_message + +A custom error message for when users are unauthorized. Default is a key for an internationalized phrase in the frontend, `Login provider denied login request`. + ### oauth_refresh_token_server_lock_min_wait_ms Minimum wait time in milliseconds for the server lock retry mechanism. Default is `1000` (milliseconds). The server lock retry mechanism is used to prevent multiple Grafana instances from simultaneously refreshing OAuth tokens. This mechanism waits at least this amount of time before retrying to acquire the server lock. diff --git a/pkg/api/login_oauth.go b/pkg/api/login_oauth.go index 1fb9aaa3ce3..f59b09045a3 100644 --- a/pkg/api/login_oauth.go +++ b/pkg/api/login_oauth.go @@ -1,8 +1,7 @@ package api import ( - "errors" - + "github.com/grafana/grafana/pkg/apimachinery/errutil" "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/middleware/cookies" "github.com/grafana/grafana/pkg/services/authn" @@ -21,8 +20,7 @@ func (hs *HTTPServer) OAuthLogin(reqCtx *contextmodel.ReqContext) { if errorParam := reqCtx.Query("error"); errorParam != "" { errorDesc := reqCtx.Query("error_description") hs.log.Error("failed to login ", "error", errorParam, "errorDesc", errorDesc) - - hs.redirectWithError(reqCtx, errors.New("login provider denied login request"), "error", errorParam, "errorDesc", errorDesc) + hs.redirectWithError(reqCtx, errutil.Unauthorized("oauth.login", errutil.WithPublicMessage(hs.Cfg.OAuthLoginErrorMessage)).Errorf("Login provider denied login request")) return } diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 306ccff0392..935254f907d 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -263,6 +263,7 @@ type Cfg struct { // OAuth OAuthAutoLogin bool + OAuthLoginErrorMessage string OAuthCookieMaxAge int OAuthAllowInsecureEmailLookup bool OAuthRefreshTokenServerLockMinWaitMs int64 @@ -1621,6 +1622,8 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) { cfg.Logger.Warn("[Deprecated] The oauth_auto_login configuration setting is deprecated. Please use auto_login inside auth provider section instead.") } + // Default to the translation key used in the frontend + cfg.OAuthLoginErrorMessage = valueAsString(auth, "oauth_login_error_message", "oauth.login.error") cfg.OAuthCookieMaxAge = auth.Key("oauth_state_cookie_max_age").MustInt(600) cfg.OAuthRefreshTokenServerLockMinWaitMs = auth.Key("oauth_refresh_token_server_lock_min_wait_ms").MustInt64(1000) cfg.SignoutRedirectUrl = valueAsString(auth, "signout_redirect_url", "") diff --git a/public/app/core/components/Login/LoginCtrl.tsx b/public/app/core/components/Login/LoginCtrl.tsx index a8612613173..1a8a1abfd5b 100644 --- a/public/app/core/components/Login/LoginCtrl.tsx +++ b/public/app/core/components/Login/LoginCtrl.tsx @@ -51,7 +51,8 @@ export class LoginCtrl extends PureComponent { isLoggingIn: false, isChangingPassword: false, showDefaultPasswordWarning: false, - loginErrorMessage: config.loginError, + // oAuth unauthorized sets the redirect error message in the bootdata, hence we need to check the key here + loginErrorMessage: getBootDataErrMessage(config.loginError), }; } @@ -178,3 +179,12 @@ function getErrorMessage(err: FetchError