From 052772ea2ee9dbfb95b8a75c8437ab2a4bd7ed82 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Tue, 18 Dec 2018 13:48:25 +0200 Subject: [PATCH 1/6] Register BrokenAuthHeaderProviders if needed --- pkg/social/social.go | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/pkg/social/social.go b/pkg/social/social.go index 8918507f3b9..da827deaa03 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -63,28 +63,34 @@ func NewOAuthService() { for _, name := range allOauthes { sec := setting.Raw.Section("auth." + name) info := &setting.OAuthInfo{ - ClientId: sec.Key("client_id").String(), - ClientSecret: sec.Key("client_secret").String(), - Scopes: util.SplitString(sec.Key("scopes").String()), - AuthUrl: sec.Key("auth_url").String(), - TokenUrl: sec.Key("token_url").String(), - ApiUrl: sec.Key("api_url").String(), - Enabled: sec.Key("enabled").MustBool(), - EmailAttributeName: sec.Key("email_attribute_name").String(), - AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()), - HostedDomain: sec.Key("hosted_domain").String(), - AllowSignup: sec.Key("allow_sign_up").MustBool(), - Name: sec.Key("name").MustString(name), - TlsClientCert: sec.Key("tls_client_cert").String(), - TlsClientKey: sec.Key("tls_client_key").String(), - TlsClientCa: sec.Key("tls_client_ca").String(), - TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(), + ClientId: sec.Key("client_id").String(), + ClientSecret: sec.Key("client_secret").String(), + Scopes: util.SplitString(sec.Key("scopes").String()), + AuthUrl: sec.Key("auth_url").String(), + TokenUrl: sec.Key("token_url").String(), + ApiUrl: sec.Key("api_url").String(), + Enabled: sec.Key("enabled").MustBool(), + EmailAttributeName: sec.Key("email_attribute_name").String(), + AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()), + HostedDomain: sec.Key("hosted_domain").String(), + AllowSignup: sec.Key("allow_sign_up").MustBool(), + Name: sec.Key("name").MustString(name), + TlsClientCert: sec.Key("tls_client_cert").String(), + TlsClientKey: sec.Key("tls_client_key").String(), + TlsClientCa: sec.Key("tls_client_ca").String(), + TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(), + BrokenAuthHeaderProvider: sec.Key("broken_auth_header_provider").MustBool(), } if !info.Enabled { continue } + // handle the clients that do not properly support Basic auth headers and require passing client_id/client_secret via POST payload + if info.BrokenAuthHeaderProvider { + oauth2.RegisterBrokenAuthHeaderProvider(info.TokenUrl) + } + if name == "grafananet" { name = grafanaCom } From 54b73025dc5e504e07e290991d9d9ff7ef62d204 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Tue, 18 Dec 2018 13:50:37 +0200 Subject: [PATCH 2/6] Add OAuth provider flag to indicate if it's broken --- pkg/setting/setting_oauth.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/pkg/setting/setting_oauth.go b/pkg/setting/setting_oauth.go index 93b1ab6f101..aab80f6a05e 100644 --- a/pkg/setting/setting_oauth.go +++ b/pkg/setting/setting_oauth.go @@ -1,20 +1,21 @@ package setting type OAuthInfo struct { - ClientId, ClientSecret string - Scopes []string - AuthUrl, TokenUrl string - Enabled bool - EmailAttributeName string - AllowedDomains []string - HostedDomain string - ApiUrl string - AllowSignup bool - Name string - TlsClientCert string - TlsClientKey string - TlsClientCa string - TlsSkipVerify bool + ClientId, ClientSecret string + Scopes []string + AuthUrl, TokenUrl string + Enabled bool + EmailAttributeName string + AllowedDomains []string + HostedDomain string + ApiUrl string + AllowSignup bool + Name string + TlsClientCert string + TlsClientKey string + TlsClientCa string + TlsSkipVerify bool + BrokenAuthHeaderProvider bool } type OAuther struct { From 08c12313fe5d349742f10615add0c3ff59f4ae23 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Tue, 18 Dec 2018 13:51:17 +0200 Subject: [PATCH 3/6] Update sample and default configs --- conf/defaults.ini | 1 + conf/sample.ini | 1 + 2 files changed, 2 insertions(+) diff --git a/conf/defaults.ini b/conf/defaults.ini index 2ef2ad7942a..47f6a64eb8b 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -335,6 +335,7 @@ tls_skip_verify_insecure = false tls_client_cert = tls_client_key = tls_client_ca = +broken_auth_header_provider = false #################################### Basic Auth ########################## [auth.basic] diff --git a/conf/sample.ini b/conf/sample.ini index ba65727dc4b..b73ab850bbf 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -283,6 +283,7 @@ log_queries = ;tls_client_cert = ;tls_client_key = ;tls_client_ca = +;broken_auth_header_provider = false #################################### Grafana.com Auth #################### [auth.grafana_com] From 3aa24b3afa3a348c7ed3594757f307b283f0f840 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Wed, 19 Dec 2018 14:59:33 +0200 Subject: [PATCH 4/6] Rename the setting and add description --- conf/defaults.ini | 2 +- conf/sample.ini | 5 ++++- pkg/social/social.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 47f6a64eb8b..97c87edb8b2 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -335,7 +335,7 @@ tls_skip_verify_insecure = false tls_client_cert = tls_client_key = tls_client_ca = -broken_auth_header_provider = false +send_client_credentials_via_post = false #################################### Basic Auth ########################## [auth.basic] diff --git a/conf/sample.ini b/conf/sample.ini index b73ab850bbf..473e4e8450c 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -283,7 +283,10 @@ log_queries = ;tls_client_cert = ;tls_client_key = ;tls_client_ca = -;broken_auth_header_provider = false + +; Set to true to enable sending client_id and client_secret via POST body instead of Basic authentication HTTP header +; This might be required if the OAuth provider is not RFC6749 compliant, only supporting credentials passed via POST payload +;send_client_credentials_via_post = false #################################### Grafana.com Auth #################### [auth.grafana_com] diff --git a/pkg/social/social.go b/pkg/social/social.go index da827deaa03..0349a271865 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -79,7 +79,7 @@ func NewOAuthService() { TlsClientKey: sec.Key("tls_client_key").String(), TlsClientCa: sec.Key("tls_client_ca").String(), TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(), - BrokenAuthHeaderProvider: sec.Key("broken_auth_header_provider").MustBool(), + BrokenAuthHeaderProvider: sec.Key("send_client_credentials_via_post").MustBool(), } if !info.Enabled { From e8823f71b0ec9ad13eed1247788bd27fc59236f7 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Wed, 19 Dec 2018 15:29:49 +0200 Subject: [PATCH 5/6] Add documentation --- docs/sources/auth/generic-oauth.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/sources/auth/generic-oauth.md b/docs/sources/auth/generic-oauth.md index 6fa6531fc98..c3c44426ba7 100644 --- a/docs/sources/auth/generic-oauth.md +++ b/docs/sources/auth/generic-oauth.md @@ -17,7 +17,7 @@ can find examples using Okta, BitBucket, OneLogin and Azure. This callback URL must match the full HTTP address that you use in your browser to access Grafana, but with the prefix path of `/login/generic_oauth`. -You may have to set the `root_url` option of `[server]` for the callback URL to be +You may have to set the `root_url` option of `[server]` for the callback URL to be correct. For example in case you are serving Grafana behind a proxy. Example config: @@ -209,6 +209,17 @@ allowed_organizations = token_url = https://.my.centrify.com/OAuth2/Token/ ``` +## Set up OAuth2 with non-compliant providers + +Some OAuth2 providers might not support `client_id` and `client_secret` passed via Basic Authentication HTTP header, which +results in `invalid_client` error. To allow Grafana to authenticate via these type of providers, the client identifiers must be +send via POST body, which can be enabled via the following settings: + + ```bash + [auth.generic_oauth] + send_client_credentials_via_post = true + ``` +
From eb517a3791e079e53c69bbe2c5581a38ddfc1ba1 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Wed, 19 Dec 2018 15:36:45 +0200 Subject: [PATCH 6/6] Update field name --- pkg/setting/setting_oauth.go | 30 +++++++++++++++--------------- pkg/social/social.go | 36 ++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pkg/setting/setting_oauth.go b/pkg/setting/setting_oauth.go index aab80f6a05e..f0a3beccb44 100644 --- a/pkg/setting/setting_oauth.go +++ b/pkg/setting/setting_oauth.go @@ -1,21 +1,21 @@ package setting type OAuthInfo struct { - ClientId, ClientSecret string - Scopes []string - AuthUrl, TokenUrl string - Enabled bool - EmailAttributeName string - AllowedDomains []string - HostedDomain string - ApiUrl string - AllowSignup bool - Name string - TlsClientCert string - TlsClientKey string - TlsClientCa string - TlsSkipVerify bool - BrokenAuthHeaderProvider bool + ClientId, ClientSecret string + Scopes []string + AuthUrl, TokenUrl string + Enabled bool + EmailAttributeName string + AllowedDomains []string + HostedDomain string + ApiUrl string + AllowSignup bool + Name string + TlsClientCert string + TlsClientKey string + TlsClientCa string + TlsSkipVerify bool + SendClientCredentialsViaPost bool } type OAuther struct { diff --git a/pkg/social/social.go b/pkg/social/social.go index 0349a271865..60099a028d6 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -63,23 +63,23 @@ func NewOAuthService() { for _, name := range allOauthes { sec := setting.Raw.Section("auth." + name) info := &setting.OAuthInfo{ - ClientId: sec.Key("client_id").String(), - ClientSecret: sec.Key("client_secret").String(), - Scopes: util.SplitString(sec.Key("scopes").String()), - AuthUrl: sec.Key("auth_url").String(), - TokenUrl: sec.Key("token_url").String(), - ApiUrl: sec.Key("api_url").String(), - Enabled: sec.Key("enabled").MustBool(), - EmailAttributeName: sec.Key("email_attribute_name").String(), - AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()), - HostedDomain: sec.Key("hosted_domain").String(), - AllowSignup: sec.Key("allow_sign_up").MustBool(), - Name: sec.Key("name").MustString(name), - TlsClientCert: sec.Key("tls_client_cert").String(), - TlsClientKey: sec.Key("tls_client_key").String(), - TlsClientCa: sec.Key("tls_client_ca").String(), - TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(), - BrokenAuthHeaderProvider: sec.Key("send_client_credentials_via_post").MustBool(), + ClientId: sec.Key("client_id").String(), + ClientSecret: sec.Key("client_secret").String(), + Scopes: util.SplitString(sec.Key("scopes").String()), + AuthUrl: sec.Key("auth_url").String(), + TokenUrl: sec.Key("token_url").String(), + ApiUrl: sec.Key("api_url").String(), + Enabled: sec.Key("enabled").MustBool(), + EmailAttributeName: sec.Key("email_attribute_name").String(), + AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()), + HostedDomain: sec.Key("hosted_domain").String(), + AllowSignup: sec.Key("allow_sign_up").MustBool(), + Name: sec.Key("name").MustString(name), + TlsClientCert: sec.Key("tls_client_cert").String(), + TlsClientKey: sec.Key("tls_client_key").String(), + TlsClientCa: sec.Key("tls_client_ca").String(), + TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(), + SendClientCredentialsViaPost: sec.Key("send_client_credentials_via_post").MustBool(), } if !info.Enabled { @@ -87,7 +87,7 @@ func NewOAuthService() { } // handle the clients that do not properly support Basic auth headers and require passing client_id/client_secret via POST payload - if info.BrokenAuthHeaderProvider { + if info.SendClientCredentialsViaPost { oauth2.RegisterBrokenAuthHeaderProvider(info.TokenUrl) }