diff --git a/conf/defaults.ini b/conf/defaults.ini index 85d0953c6af..15b8927e65a 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -321,6 +321,7 @@ allow_sign_up = true client_id = some_id client_secret = some_secret scopes = user:email +email_attribute_name = email:primary auth_url = token_url = api_url = diff --git a/docs/sources/auth/generic-oauth.md b/docs/sources/auth/generic-oauth.md index bec5a98e04a..802424f180b 100644 --- a/docs/sources/auth/generic-oauth.md +++ b/docs/sources/auth/generic-oauth.md @@ -32,7 +32,14 @@ allowed_domains = mycompany.com mycompany.org allow_sign_up = true ``` -Set api_url to the resource that returns [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo) compatible information. +Set `api_url` to the resource that returns [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo) compatible information. + +Grafana will attempt to determine the user's e-mail address by querying the OAuth provider as described below in the following order until an e-mail address is found: + +1. Check for the presence of an e-mail address via the `email` field encoded in the OAuth `id_token` parameter. +2. Check for the presence of an e-mail address in the `attributes` map encoded in the OAuth `id_token` parameter. By default Grafana will perform a lookup into the attributes map using the `email:primary` key, however, this is configurable and can be adjusted by using the `email_attribute_name` configuration option. +3. Query the `/emails` endpoint of the OAuth provider's API (configured with `api_url`) and check for the presence of an e-mail address marked as a primary address. +4. If no e-mail address is found in steps (1-3), then the e-mail address of the user is set to the empty string. ## Set up OAuth2 with Okta diff --git a/docs/sources/features/datasources/mssql.md b/docs/sources/features/datasources/mssql.md index 6bfcfd807f1..debf771ffb0 100644 --- a/docs/sources/features/datasources/mssql.md +++ b/docs/sources/features/datasources/mssql.md @@ -174,6 +174,8 @@ The resulting table panel: If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must must have a column named `time` that returns either a sql datetime or any numeric datatype representing unix epoch in seconds. You may return a column named `metric` that is used as metric name for the value column. Any column except `time` and `metric` is treated as a value column. If you omit the `metric` column, the name of the value column will be the metric name. You may select multiple value columns, each will have its name as metric. If you return multiple value columns and a column named `metric` then this column is used as prefix for the series name (only available in Grafana 5.3+). +Resultsets of time series queries need to be sorted by time. + **Example database table:** ```sql diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index e13abcf80a2..d713a4b42b7 100644 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -129,6 +129,8 @@ Any column except `time` and `metric` is treated as a value column. You may return a column named `metric` that is used as metric name for the value column. If you return multiple value columns and a column named `metric` then this column is used as prefix for the series name (only available in Grafana 5.3+). +Resultsets of time series queries need to be sorted by time. + **Example with `metric` column:** ```sql diff --git a/docs/sources/features/datasources/postgres.md b/docs/sources/features/datasources/postgres.md index 013d6342634..d67958814dd 100644 --- a/docs/sources/features/datasources/postgres.md +++ b/docs/sources/features/datasources/postgres.md @@ -129,6 +129,8 @@ Any column except `time` and `metric` is treated as a value column. You may return a column named `metric` that is used as metric name for the value column. If you return multiple value columns and a column named `metric` then this column is used as prefix for the series name (only available in Grafana 5.3+). +Resultsets of time series queries need to be sorted by time. + **Example with `metric` column:** ```sql diff --git a/pkg/setting/setting_oauth.go b/pkg/setting/setting_oauth.go index ee2e812415b..93b1ab6f101 100644 --- a/pkg/setting/setting_oauth.go +++ b/pkg/setting/setting_oauth.go @@ -5,6 +5,7 @@ type OAuthInfo struct { Scopes []string AuthUrl, TokenUrl string Enabled bool + EmailAttributeName string AllowedDomains []string HostedDomain string ApiUrl string diff --git a/pkg/social/generic_oauth.go b/pkg/social/generic_oauth.go index 8c02076096d..a97d58334c7 100644 --- a/pkg/social/generic_oauth.go +++ b/pkg/social/generic_oauth.go @@ -20,6 +20,7 @@ type SocialGenericOAuth struct { allowedOrganizations []string apiUrl string allowSignup bool + emailAttributeName string teamIds []int } @@ -264,8 +265,9 @@ func (s *SocialGenericOAuth) extractEmail(data *UserInfoJson) string { return data.Email } - if data.Attributes["email:primary"] != nil { - return data.Attributes["email:primary"][0] + emails, ok := data.Attributes[s.emailAttributeName] + if ok && len(emails) != 0 { + return emails[0] } if data.Upn != "" { diff --git a/pkg/social/social.go b/pkg/social/social.go index 2be71514629..e96b67fe031 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -60,21 +60,22 @@ 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(), - 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(), } if !info.Enabled { @@ -153,6 +154,7 @@ func NewOAuthService() { allowedDomains: info.AllowedDomains, apiUrl: info.ApiUrl, allowSignup: info.AllowSignup, + emailAttributeName: info.EmailAttributeName, teamIds: sec.Key("team_ids").Ints(","), allowedOrganizations: util.SplitString(sec.Key("allowed_organizations").String()), } diff --git a/public/app/plugins/datasource/mssql/partials/query.editor.html b/public/app/plugins/datasource/mssql/partials/query.editor.html index 4b0a46b6412..ba3bb6a4b82 100644 --- a/public/app/plugins/datasource/mssql/partials/query.editor.html +++ b/public/app/plugins/datasource/mssql/partials/query.editor.html @@ -45,6 +45,8 @@ Optional: - If multiple value columns are returned the metric column is used as prefix. - If no column named metric is found the column name of the value column is used as series name +Resultsets of time series queries need to be sorted by time. + Table: - return any set of columns diff --git a/public/app/plugins/datasource/mysql/partials/query.editor.html b/public/app/plugins/datasource/mysql/partials/query.editor.html index 1e829a1175d..1cc21adb22e 100644 --- a/public/app/plugins/datasource/mysql/partials/query.editor.html +++ b/public/app/plugins/datasource/mysql/partials/query.editor.html @@ -45,6 +45,8 @@ Optional: - If multiple value columns are returned the metric column is used as prefix. - If no column named metric is found the column name of the value column is used as series name +Resultsets of time series queries need to be sorted by time. + Table: - return any set of columns diff --git a/public/app/plugins/datasource/postgres/partials/query.editor.html b/public/app/plugins/datasource/postgres/partials/query.editor.html index fd944f4266c..6c3bf02cb51 100644 --- a/public/app/plugins/datasource/postgres/partials/query.editor.html +++ b/public/app/plugins/datasource/postgres/partials/query.editor.html @@ -143,6 +143,8 @@ Optional: - If multiple value columns are returned the metric column is used as prefix. - If no column named metric is found the column name of the value column is used as series name +Resultsets of time series queries need to be sorted by time. + Table: - return any set of columns