Auth: Add org to role mappings support to GitHub integration (#88537)

* wip: add extra tests for verifying current logic

* Add OrgRole mapping and tests

* Update docs

* Clean up

* Update docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md

Co-authored-by: Mihai Doarna <mihai.doarna@grafana.com>

* Update docs with None role

* Apply suggestions from code review

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Fix

* Prettier docs

* Cleanup tests

---------

Co-authored-by: Mihai Doarna <mihai.doarna@grafana.com>
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
pull/88615/head
Misi 12 months ago committed by GitHub
parent e147c58a7b
commit eacf6e0a4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md
  2. 2
      docs/sources/developers/http_api/auth.md
  3. 17
      docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md
  4. 68
      docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md
  5. 50
      docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md
  6. 4
      docs/sources/setup-grafana/configure-security/configure-authentication/jwt/index.md
  7. 40
      docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md
  8. 2
      docs/sources/setup-grafana/configure-security/configure-authentication/saml/index.md
  9. 40
      pkg/login/social/connectors/github_oauth.go
  10. 204
      pkg/login/social/connectors/github_oauth_test.go
  11. 4
      pkg/services/authn/clients/oauth.go

@ -100,7 +100,7 @@ The following list contains role-based access control actions.
| `licensing:delete` | n/a | Delete the license token. |
| `licensing:read` | n/a | Read licensing information. |
| `licensing:write` | n/a | Update the license token. |
| `org.users:write` | `users:*` <br> `users:id:*` | Update the organization role (`Viewer`, `Editor`, or `Admin`) of a user. |
| `org.users:write` | `users:*` <br> `users:id:*` | Update the organization role (`None`, `Viewer`, `Editor`, or `Admin`) of a user. |
| `org.users:add` | `users:*` <br> `users:id:*` | Add a user to an organization or invite a new user to an organization. |
| `org.users:read` | `users:*` <br> `users:id:*` | Get user profiles within an organization. |
| `org.users:remove` | `users:*` <br> `users:id:*` | Remove a user from an organization. |

@ -103,7 +103,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
JSON Body schema:
- **name** – The key name
- **role** – Sets the access level/Grafana Role for the key. Can be one of the following values: `Viewer`, `Editor` or `Admin`.
- **role** – Sets the access level/Grafana Role for the key. Can be one of the following values: `None`, `Viewer`, `Editor` or `Admin`.
- **secondsToLive** – Sets the key expiration in seconds. It is optional. If it is a positive number an expiration date for the key is set. If it is null, zero or is omitted completely (unless `api_key_max_seconds_to_live` configuration option is set) the key will never expire.
Error statuses:

@ -203,10 +203,9 @@ To map the server administrator role, use the `allow_assign_grafana_admin` confi
Refer to [configuration options]({{< relref "#configuration-options" >}}) for more information.
If no valid role is found, the user is assigned the role specified by [the `auto_assign_org_role` option]({{< relref "../../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
This setting denies user access if no role or an invalid role is returned.
You can disable this default role assignment by setting `role_attribute_strict = true`. This setting denies user access if no role or an invalid role is returned after evaluating the `role_attribute_path` and the `org_mapping` expressions.
You can use the `org_attribute_path` and `org_mapping` configuration options to add roles to other orgs. For more information, refer to [Org roles mapping examples]({{< relref "#org-roles-mapping-examples" >}}). If both org role mapping (`org_mapping`) and the regular role mapping (`role_attribute_path`) are specified, then the user will get the highest of the two mapped roles.
You can use the `org_attribute_path` and `org_mapping` configuration options to assign the user to organizations and specify their role. For more information, refer to [Org roles mapping example](#org-roles-mapping-example). If both org role mapping (`org_mapping`) and the regular role mapping (`role_attribute_path`) are specified, then the user will get the highest of the two mapped roles.
To ease configuration of a proper JMESPath expression, go to [JMESPath](http://jmespath.org/) to test and evaluate expressions with custom payloads.
@ -298,11 +297,7 @@ role_attribute_path = "'Viewer'"
skip_org_role_sync = false
```
#### Org roles mapping examples
This section includes examples of configuration settings used for org to role mapping.
##### Map organization roles
#### Org roles mapping example
In this example, the user has been granted the role of a `Viewer` in the `org_foo` org, and the role of an `Editor` in the `org_bar` and `org_baz` orgs.
@ -396,10 +391,10 @@ The following table outlines the various generic OAuth2 configuration options. Y
| `name_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for user name lookup from the user ID token. This name will be used as the user's display name. For more information on how user display name is retrieved, refer to [Configure display name]({{< relref "#configure-display-name" >}}). | |
| `email_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for user email lookup from the user information. For more information on how user email is retrieved, refer to [Configure email address]({{< relref "#configure-email-address" >}}). | |
| `email_attribute_name` | No | Name of the key to use for user email lookup within the `attributes` map of OAuth2 ID token. For more information on how user email is retrieved, refer to [Configure email address]({{< relref "#configure-email-address" >}}). | `email:primary` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `org_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping examples]({{< relref "#org-roles-mapping-examples" >}}). | |
| `org_mapping` | No | List of comma- or space-separated Value:OrgIdOrName:Role mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `Viewer`, `Editor` or `Admin`. For more information on org to role mapping, refer to [Org roles mapping examples]({{< relref "#org-roles-mapping-examples" >}}). | |
| `org_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `org_mapping` | No | List of comma- or space-separated `<ExternalOrgName>:<OrgIdOrName>:<Role>` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `allow_assign_grafana_admin` | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
| `groups_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for user group lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no groups are found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a string array of groups. | |

@ -114,8 +114,9 @@ To map the server administrator role, use the `allow_assign_grafana_admin` confi
Refer to [configuration options]({{< relref "#configuration-options" >}}) for more information.
If no valid role is found, the user is assigned the role specified by [the `auto_assign_org_role` option]({{< relref "../../../configure-grafana#auto_assign_org_role" >}}).
You can disable this default role assignment by setting `role_attribute_strict = true`.
This setting denies user access if no role or an invalid role is returned.
You can disable this default role assignment by setting `role_attribute_strict = true`. This setting denies user access if no role or an invalid role is returned after evaluating the `role_attribute_path` and the `org_mapping` expressions.
You can use the `org_attribute_path` and `org_mapping` configuration options to assign the user to organizations and specify their role. For more information, refer to [Org roles mapping example](#org-roles-mapping-example). If both org role mapping (`org_mapping`) and the regular role mapping (`role_attribute_path`) are specified, then the user will get the highest of the two mapped roles.
To ease configuration of a proper JMESPath expression, go to [JMESPath](http://jmespath.org/) to test and evaluate expressions with custom payloads.
@ -123,6 +124,20 @@ To ease configuration of a proper JMESPath expression, go to [JMESPath](http://j
This section includes examples of JMESPath expressions used for role mapping.
##### Org roles mapping example
The GitHub integration uses the external users' teams in the `org_mapping` configuration to map organizations and roles based on their GitHub team membership.
In this example, the user has been granted the role of a `Viewer` in the `org_foo` organization, and the role of an `Editor` in the `org_bar` and `org_baz` orgs.
The external user is part of the following GitHub teams: `@my-github-organization/my-github-team-1` and `@my-github-organization/my-github-team-2`.
Config:
```ini
org_mapping = @my-github-organization/my-github-team-1:org_foo:Viewer @my-github-organization/my-github-team-2:org_bar:Editor *:org_baz:Editor
```
##### Map roles using GitHub user information
In this example, the user with login `octocat` has been granted the `Admin` role.
@ -202,27 +217,28 @@ To learn more about Team Sync, refer to [Configure team sync]({{< relref "../../
The table below describes all GitHub OAuth configuration options. Like any other Grafana configuration, you can apply these options as environment variables.
| Setting | Required | Description | Default |
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `enabled` | No | Whether GitHub OAuth authentication is allowed. | `false` |
| `name` | No | Name used to refer to the GitHub authentication in the Grafana user interface. | `GitHub` |
| `icon` | No | Icon used for GitHub authentication in the Grafana user interface. | `github` |
| `client_id` | Yes | Client ID provided by your GitHub OAuth app. | |
| `client_secret` | Yes | Client secret provided by your GitHub OAuth app. | |
| `auth_url` | Yes | Authorization endpoint of your GitHub OAuth provider. | `https://github.com/login/oauth/authorize` |
| `token_url` | Yes | Endpoint used to obtain GitHub OAuth access token. | `https://github.com/login/oauth/access_token` |
| `api_url` | Yes | Endpoint used to obtain GitHub user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | `https://api.github.com/user` |
| `scopes` | No | List of comma- or space-separated GitHub OAuth scopes. | `user:email,read:org` |
| `allow_sign_up` | No | Whether to allow new Grafana user creation through GitHub login. If set to `false`, then only existing Grafana users can log in with GitHub OAuth. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the user information obtained from the UserInfo endpoint. If no role is found, Grafana creates a JSON data with `groups` key that maps to GitHub teams obtained from GitHub's [`/api/user/teams`](https://docs.github.com/en/rest/teams/teams#list-teams-for-the-authenticated-user) endpoint, and evaluates the expression using this data. The result of the evaluation should be a valid Grafana role (`Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana role cannot be extracted using `role_attribute_path`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `allow_assign_grafana_admin` | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. | `false` |
| `allowed_organizations` | No | List of comma- or space-separated organizations. User must be a member of at least one organization to log in. | |
| `allowed_domains` | No | List of comma- or space-separated domains. User must belong to at least one domain to log in. | |
| `team_ids` | No | Integer list of team IDs. If set, user has to be a member of one of the given teams to log in. | |
| `tls_skip_verify_insecure` | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | The path to the certificate. | |
| `tls_client_key` | No | The path to the key. | |
| `tls_client_ca` | No | The path to the trusted certificate authority list. | |
| Setting | Required | Description | Default |
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `enabled` | No | Whether GitHub OAuth authentication is allowed. | `false` |
| `name` | No | Name used to refer to the GitHub authentication in the Grafana user interface. | `GitHub` |
| `icon` | No | Icon used for GitHub authentication in the Grafana user interface. | `github` |
| `client_id` | Yes | Client ID provided by your GitHub OAuth app. | |
| `client_secret` | Yes | Client secret provided by your GitHub OAuth app. | |
| `auth_url` | Yes | Authorization endpoint of your GitHub OAuth provider. | `https://github.com/login/oauth/authorize` |
| `token_url` | Yes | Endpoint used to obtain GitHub OAuth access token. | `https://github.com/login/oauth/access_token` |
| `api_url` | Yes | Endpoint used to obtain GitHub user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | `https://api.github.com/user` |
| `scopes` | No | List of comma- or space-separated GitHub OAuth scopes. | `user:email,read:org` |
| `allow_sign_up` | No | Whether to allow new Grafana user creation through GitHub login. If set to `false`, then only existing Grafana users can log in with GitHub OAuth. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the user information obtained from the UserInfo endpoint. If no role is found, Grafana creates a JSON data with `groups` key that maps to GitHub teams obtained from GitHub's [`/api/user/teams`](https://docs.github.com/en/rest/teams/teams#list-teams-for-the-authenticated-user) endpoint, and evaluates the expression using this data. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping](#org-roles-mapping-example). | |
| `role_attribute_strict` | No | et to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping](#org-roles-mapping-example). | `false` |
| `org_mapping` | No | List of comma- or space-separated `<ExternalGitHubTeamName>:<OrgIdOrName>:<Role>` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `allow_assign_grafana_admin` | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. | `false` |
| `allowed_organizations` | No | List of comma- or space-separated organizations. User must be a member of at least one organization to log in. | |
| `allowed_domains` | No | List of comma- or space-separated domains. User must belong to at least one domain to log in. | |
| `team_ids` | No | Integer list of team IDs. If set, user has to be a member of one of the given teams to log in. | |
| `tls_skip_verify_insecure` | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | The path to the certificate. | |
| `tls_client_key` | No | The path to the key. | |
| `tls_client_ca` | No | The path to the trusted certificate authority list. | |

@ -236,28 +236,28 @@ To learn more about Team Sync, refer to [Configure team sync]({{< relref "../../
The table below describes all GitLab OAuth configuration options. Like any other Grafana configuration, you can apply these options as environment variables.
| Setting | Required | Description | Default |
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `enabled` | Yes | Whether GitLab OAuth authentication is allowed. | `false` |
| `client_id` | Yes | Client ID provided by your GitLab OAuth app. | |
| `client_secret` | Yes | Client secret provided by your GitLab OAuth app. | |
| `auth_url` | Yes | Authorization endpoint of your GitLab OAuth provider. If you use your own instance of GitLab instead of gitlab.com, adjust `auth_url` by replacing the `gitlab.com` hostname with your own. | `https://gitlab.com/oauth/authorize` |
| `token_url` | Yes | Endpoint used to obtain GitLab OAuth access token. If you use your own instance of GitLab instead of gitlab.com, adjust `token_url` by replacing the `gitlab.com` hostname with your own. | `https://gitlab.com/oauth/token` |
| `api_url` | No | Grafana uses `<api_url>/user` endpoint to obtain GitLab user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | `https://gitlab.com/api/v4` |
| `name` | No | Name used to refer to the GitLab authentication in the Grafana user interface. | `GitLab` |
| `icon` | No | Icon used for GitLab authentication in the Grafana user interface. | `gitlab` |
| `scopes` | No | List of comma or space-separated GitLab OAuth scopes. | `openid email profile` |
| `allow_sign_up` | No | Whether to allow new Grafana user creation through GitLab login. If set to `false`, then only existing Grafana users can log in with GitLab OAuth. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the GitLab OAuth token. If no role is found, Grafana creates a JSON data with `groups` key that maps to groups obtained from GitLab's `/oauth/userinfo` endpoint, and evaluates the expression using this data. Finally, if a valid role is still not found, the expression is evaluated against the user information retrieved from `api_url/users` endpoint and groups retrieved from `api_url/groups` endpoint. The result of the evaluation should be a valid Grafana role (`Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana role cannot be extracted using `role_attribute_path`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `allow_assign_grafana_admin` | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. | `false` |
| `allowed_domains` | No | List of comma or space-separated domains. User must belong to at least one domain to log in. | |
| `allowed_groups` | No | List of comma or space-separated groups. The user should be a member of at least one group to log in. | |
| `tls_skip_verify_insecure` | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | The path to the certificate. | |
| `tls_client_key` | No | The path to the key. | |
| `tls_client_ca` | No | The path to the trusted certificate authority list. | |
| `use_pkce` | No | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
| `use_refresh_token` | No | Set to `true` to use refresh token and check access token expiration. The `accessTokenExpirationCheck` feature toggle should also be enabled to use refresh token. | `true` |
| Setting | Required | Description | Default |
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `enabled` | Yes | Whether GitLab OAuth authentication is allowed. | `false` |
| `client_id` | Yes | Client ID provided by your GitLab OAuth app. | |
| `client_secret` | Yes | Client secret provided by your GitLab OAuth app. | |
| `auth_url` | Yes | Authorization endpoint of your GitLab OAuth provider. If you use your own instance of GitLab instead of gitlab.com, adjust `auth_url` by replacing the `gitlab.com` hostname with your own. | `https://gitlab.com/oauth/authorize` |
| `token_url` | Yes | Endpoint used to obtain GitLab OAuth access token. If you use your own instance of GitLab instead of gitlab.com, adjust `token_url` by replacing the `gitlab.com` hostname with your own. | `https://gitlab.com/oauth/token` |
| `api_url` | No | Grafana uses `<api_url>/user` endpoint to obtain GitLab user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | `https://gitlab.com/api/v4` |
| `name` | No | Name used to refer to the GitLab authentication in the Grafana user interface. | `GitLab` |
| `icon` | No | Icon used for GitLab authentication in the Grafana user interface. | `gitlab` |
| `scopes` | No | List of comma or space-separated GitLab OAuth scopes. | `openid email profile` |
| `allow_sign_up` | No | Whether to allow new Grafana user creation through GitLab login. If set to `false`, then only existing Grafana users can log in with GitLab OAuth. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the GitLab OAuth token. If no role is found, Grafana creates a JSON data with `groups` key that maps to groups obtained from GitLab's `/oauth/userinfo` endpoint, and evaluates the expression using this data. Finally, if a valid role is still not found, the expression is evaluated against the user information retrieved from `api_url/users` endpoint and groups retrieved from `api_url/groups` endpoint. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana role cannot be extracted using `role_attribute_path`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `allow_assign_grafana_admin` | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. | `false` |
| `allowed_domains` | No | List of comma or space-separated domains. User must belong to at least one domain to log in. | |
| `allowed_groups` | No | List of comma or space-separated groups. The user should be a member of at least one group to log in. | |
| `tls_skip_verify_insecure` | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | The path to the certificate. | |
| `tls_client_key` | No | The path to the key. | |
| `tls_client_ca` | No | The path to the trusted certificate authority list. | |
| `use_pkce` | No | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
| `use_refresh_token` | No | Set to `true` to use refresh token and check access token expiration. The `accessTokenExpirationCheck` feature toggle should also be enabled to use refresh token. | `true` |

@ -192,7 +192,7 @@ expect_claims = {"iss": "https://your-token-issuer", "your-custom-claim": "foo"}
## Roles
Grafana checks for the presence of a role using the [JMESPath](http://jmespath.org/examples.html) specified via the `role_attribute_path` configuration option. The JMESPath is applied to JWT token claims. The result after evaluation of the `role_attribute_path` JMESPath expression should be a valid Grafana role, for example, `Viewer`, `Editor` or `Admin`.
Grafana checks for the presence of a role using the [JMESPath](http://jmespath.org/examples.html) specified via the `role_attribute_path` configuration option. The JMESPath is applied to JWT token claims. The result after evaluation of the `role_attribute_path` JMESPath expression should be a valid Grafana role, for example, `None`, `Viewer`, `Editor` or `Admin`.
The organization that the role is assigned to can be configured using the `X-Grafana-Org-Id` header.
@ -206,7 +206,7 @@ If the `role_attribute_path` property does not return a role, then the user is a
**Basic example:**
In the following example user will get `Editor` as role when authenticating. The value of the property `role` will be the resulting role if the role is a proper Grafana role, i.e. `Viewer`, `Editor` or `Admin`.
In the following example user will get `Editor` as role when authenticating. The value of the property `role` will be the resulting role if the role is a proper Grafana role, i.e. `None`, `Viewer`, `Editor` or `Admin`.
Payload:

@ -240,23 +240,23 @@ To learn more about Team Sync, refer to [Configure Team Sync]({{< relref "../../
The following table outlines the various Okta OIDC configuration options. You can apply these options as environment variables, similar to any other configuration within Grafana.
| Setting | Required | Description | Default |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `enabled` | No | Enables Okta OIDC authentication. | `false` |
| `name` | No | Name that refers to the Okta OIDC authentication from the Grafana user interface. | `Okta` |
| `icon` | No | Icon used for the Okta OIDC authentication in the Grafana user interface. | `okta` |
| `client_id` | Yes | Client ID provided by your Okta OIDC app. | |
| `client_secret` | Yes | Client secret provided by your Okta OIDC app. | |
| `auth_url` | Yes | Authorization endpoint of your Okta OIDC provider. | |
| `token_url` | Yes | Endpoint used to obtain the Okta OIDC access token. | |
| `api_url` | Yes | Endpoint used to obtain user information. | |
| `scopes` | No | List of comma- or space-separated Okta OIDC scopes. | `openid profile email groups` |
| `allow_sign_up` | No | Controls Grafana user creation through the Okta OIDC login. Only existing Grafana users can log in with Okta OIDC if set to `false`. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the Okta OIDC ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana role cannot be extracted using `role_attribute_path`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
| `allowed_groups` | No | List of comma- or space-separated groups. The user should be a member of at least one group to log in. | |
| `allowed_domains` | No | List comma- or space-separated domains. The user should belong to at least one domain to log in. | |
| `use_pkce` | No | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
| `use_refresh_token` | No | Set to `true` to use refresh token and check access token expiration. | `false` |
| Setting | Required | Description | Default |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
| `enabled` | No | Enables Okta OIDC authentication. | `false` |
| `name` | No | Name that refers to the Okta OIDC authentication from the Grafana user interface. | `Okta` |
| `icon` | No | Icon used for the Okta OIDC authentication in the Grafana user interface. | `okta` |
| `client_id` | Yes | Client ID provided by your Okta OIDC app. | |
| `client_secret` | Yes | Client secret provided by your Okta OIDC app. | |
| `auth_url` | Yes | Authorization endpoint of your Okta OIDC provider. | |
| `token_url` | Yes | Endpoint used to obtain the Okta OIDC access token. | |
| `api_url` | Yes | Endpoint used to obtain user information. | |
| `scopes` | No | List of comma- or space-separated Okta OIDC scopes. | `openid profile email groups` |
| `allow_sign_up` | No | Controls Grafana user creation through the Okta OIDC login. Only existing Grafana users can log in with Okta OIDC if set to `false`. | `true` |
| `auto_login` | No | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `role_attribute_path` | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the Okta OIDC ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | |
| `role_attribute_strict` | No | Set to `true` to deny user login if the Grafana role cannot be extracted using `role_attribute_path`. For more information on user role mapping, refer to [Configure role mapping]({{< relref "#configure-role-mapping" >}}). | `false` |
| `skip_org_role_sync` | No | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
| `allowed_groups` | No | List of comma- or space-separated groups. The user should be a member of at least one group to log in. | |
| `allowed_domains` | No | List comma- or space-separated domains. The user should belong to at least one domain to log in. | |
| `use_pkce` | No | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
| `use_refresh_token` | No | Set to `true` to use refresh token and check access token expiration. | `false` |

@ -222,7 +222,7 @@ The table below describes all SAML configuration options. Continue reading below
| `assertion_attribute_role` | No | Friendly name or name of the attribute within the SAML assertion to use as the user roles | |
| `assertion_attribute_org` | No | Friendly name or name of the attribute within the SAML assertion to use as the user organization | |
| `allowed_organizations` | No | List of comma- or space-separated organizations. User should be a member of at least one organization to log in. | |
| `org_mapping` | No | List of comma- or space-separated Organization:OrgId:Role mappings. Organization can be `*` meaning "All users". Role is optional and can have the following values: `Viewer`, `Editor` or `Admin`. | |
| `org_mapping` | No | List of comma- or space-separated Organization:OrgId:Role mappings. Organization can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. | |
| `role_values_none` | No | List of comma- or space-separated roles which will be mapped into the None role | |
| `role_values_editor` | No | List of comma- or space-separated roles which will be mapped into the Editor role | |
| `role_values_admin` | No | List of comma- or space-separated roles which will be mapped into the Admin role | |

@ -13,9 +13,9 @@ import (
"golang.org/x/oauth2"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models/roletype"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/ssosettings"
ssoModels "github.com/grafana/grafana/pkg/services/ssosettings/models"
"github.com/grafana/grafana/pkg/services/ssosettings/validation"
@ -307,37 +307,37 @@ func (s *SocialGithub) UserInfo(ctx context.Context, client *http.Client, token
return nil, fmt.Errorf("error getting user teams: %s", err)
}
teams := convertToGroupList(teamMemberships)
userInfo := &social.BasicUserInfo{
Name: data.Login,
Login: data.Login,
Id: fmt.Sprintf("%d", data.Id),
Email: data.Email,
Groups: convertToGroupList(teamMemberships),
}
var role roletype.RoleType
var isGrafanaAdmin *bool = nil
if s.info.AllowAssignGrafanaAdmin && s.info.SkipOrgRoleSync {
s.log.Debug("AllowAssignGrafanaAdmin and skipOrgRoleSync are both set, Grafana Admin role will not be synced, consider setting one or the other")
}
var directlyMappedRole org.RoleType
if !s.info.SkipOrgRoleSync {
var grafanaAdmin bool
role, grafanaAdmin, err = s.extractRoleAndAdmin(response.Body, teams)
directlyMappedRole, grafanaAdmin, err = s.extractRoleAndAdminOptional(response.Body, userInfo.Groups)
if err != nil {
return nil, err
s.log.Warn("Failed to extract role", "err", err)
}
if s.info.AllowAssignGrafanaAdmin {
isGrafanaAdmin = &grafanaAdmin
userInfo.IsGrafanaAdmin = &grafanaAdmin
}
}
// we skip allowing assignment of GrafanaAdmin if skipOrgRoleSync is present
if s.info.AllowAssignGrafanaAdmin && s.info.SkipOrgRoleSync {
s.log.Debug("AllowAssignGrafanaAdmin and skipOrgRoleSync are both set, Grafana Admin role will not be synced, consider setting one or the other")
userInfo.OrgRoles = s.orgRoleMapper.MapOrgRoles(s.orgMappingCfg, userInfo.Groups, directlyMappedRole)
if s.info.RoleAttributeStrict && len(userInfo.OrgRoles) == 0 {
return nil, errRoleAttributeStrictViolation.Errorf("could not evaluate any valid roles using IdP provided data")
}
}
userInfo := &social.BasicUserInfo{
Name: data.Login,
Login: data.Login,
Id: fmt.Sprintf("%d", data.Id),
Email: data.Email,
Role: role,
Groups: teams,
IsGrafanaAdmin: isGrafanaAdmin,
}
if data.Name != "" {
userInfo.Name = data.Name
}

@ -4,7 +4,6 @@ import (
"context"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
@ -14,6 +13,8 @@ import (
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/ssosettings"
ssoModels "github.com/grafana/grafana/pkg/services/ssosettings/models"
"github.com/grafana/grafana/pkg/services/ssosettings/ssosettingstests"
@ -142,69 +143,76 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
settingAllowGrafanaAdmin bool
settingSkipOrgRoleSync bool
roleAttributePath string
autoAssignOrgRole string
roleAttributeStrict bool
orgMapping []string
want *social.BasicUserInfo
wantErr bool
oAuthExtraInfo map[string]string
}{
{
name: "Basic User info",
name: "should return default role if no role attribute path is set",
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
autoAssignOrgRole: "",
roleAttributePath: "",
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "Viewer",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{1: org.RoleViewer},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "Admin mapping takes precedence over auto assign org role",
roleAttributePath: "[login==octocat] && 'Admin' || 'Viewer'",
userRawJSON: testGHUserJSON,
autoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
name: "should fail when role attribute path is empty and role attribute strict is enabled",
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
roleAttributePath: "",
roleAttributeStrict: true,
wantErr: true,
},
{
name: "admin mapping takes precedence over auto assign org role",
roleAttributePath: "[login==octocat] && 'Admin' || 'Viewer'",
userRawJSON: testGHUserJSON,
settingAutoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "Admin",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{1: org.RoleAdmin},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "Editor mapping via groups",
name: "should map role when role attribute path is set",
roleAttributePath: "contains(groups[*], '@github/justice-league') && 'Editor' || 'Viewer'",
userRawJSON: testGHUserJSON,
autoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "Editor",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{1: org.RoleEditor},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "Should be empty role if setting skipOrgRoleSync is set to true",
name: "should return empty role when skip org role sync is true",
roleAttributePath: "contains(groups[*], '@github/justice-league') && 'Editor' || 'Viewer'",
settingSkipOrgRoleSync: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: nil,
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
@ -219,45 +227,89 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "",
OrgRoles: nil,
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
IsGrafanaAdmin: boolPointer,
},
},
{
name: "fallback to default org role",
roleAttributePath: "",
userRawJSON: testGHUserJSON,
autoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
name: "should fallback to default org role when role attribute path is empty and auto assign org role is set",
roleAttributePath: "",
userRawJSON: testGHUserJSON,
settingAutoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "Editor",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{1: org.RoleEditor},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
// see: https://github.com/grafana/grafana/issues/85916
name: "should check parent team id for team membership",
roleAttributePath: "",
userRawJSON: testGHUserJSON,
autoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
name: "should check parent team id for team membership",
roleAttributePath: "",
userRawJSON: testGHUserJSON,
settingAutoAssignOrgRole: "Editor",
userTeamsRawJSON: testGHUserTeamsJSON,
oAuthExtraInfo: map[string]string{
"team_ids": "99",
},
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "Editor",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{1: org.RoleEditor},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "should map role when only org mapping is set",
orgMapping: []string{"@github/justice-league:Org4:Editor", "*:Org5:Viewer"},
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{4: "Editor", 5: "Viewer"},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "should map role when only org mapping is set and role attribute strict is enabled",
orgMapping: []string{"@github/justice-league:Org4:Editor", "*:Org5:Viewer"},
roleAttributeStrict: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
want: &social.BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
OrgRoles: map[int64]org.RoleType{4: "Editor", 5: "Viewer"},
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "should return error when neither role attribute path nor org mapping evaluates to a role and role attribute strict is enabled",
orgMapping: []string{"@github/avengers:Org4:Editor"},
roleAttributeStrict: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
wantErr: true,
},
{
name: "should return error when neither role attribute path nor org mapping is set and role attribute strict is enabled",
roleAttributeStrict: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -278,15 +330,26 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
}))
defer server.Close()
cfg := &setting.Cfg{
AutoAssignOrgRole: "Viewer", // default role
}
if tt.settingAutoAssignOrgRole != "" {
cfg.AutoAssignOrgRole = tt.settingAutoAssignOrgRole
}
s := NewGitHubProvider(
&social.OAuthInfo{
ApiUrl: server.URL + "/user",
RoleAttributePath: tt.roleAttributePath,
SkipOrgRoleSync: tt.settingSkipOrgRoleSync,
Extra: tt.oAuthExtraInfo,
}, &setting.Cfg{
AutoAssignOrgRole: tt.autoAssignOrgRole,
}, nil, &ssosettingstests.MockService{},
ApiUrl: server.URL + "/user",
RoleAttributePath: tt.roleAttributePath,
RoleAttributeStrict: tt.roleAttributeStrict,
OrgMapping: tt.orgMapping,
SkipOrgRoleSync: tt.settingSkipOrgRoleSync,
Extra: tt.oAuthExtraInfo,
}, cfg,
ProvideOrgRoleMapper(cfg,
&orgtest.FakeOrgService{ExpectedOrgs: []*org.OrgDTO{{ID: 4, Name: "Org4"}, {ID: 5, Name: "Org5"}}}),
&ssosettingstests.MockService{},
featuremgmt.WithFeatures())
token := &oauth2.Token{
@ -294,13 +357,12 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
}
got, err := s.UserInfo(context.Background(), server.Client(), token)
if (err != nil) != tt.wantErr {
t.Errorf("UserInfo() error = %v, wantErr %v", err, tt.wantErr)
if tt.wantErr {
require.Error(t, err)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("UserInfo() got = %v, want %v", got, tt.want)
}
require.EqualValues(t, tt.want, got)
})
}
}

@ -168,8 +168,8 @@ func (c *OAuth) Authenticate(ctx context.Context, r *authn.Request) (*authn.Iden
// This is required to implement OrgRole mapping for OAuth providers step by step
switch c.providerName {
case social.GenericOAuthProviderName:
// Do nothing, GenericOAuthProvider already supports OrgRole mapping
case social.GenericOAuthProviderName, social.GitHubProviderName:
// Do nothing, GenericOAuthProvider and GitHub already supports OrgRole mapping
default:
userInfo.OrgRoles, userInfo.IsGrafanaAdmin, _ = getRoles(c.cfg, func() (org.RoleType, *bool, error) {
return userInfo.Role, userInfo.IsGrafanaAdmin, nil

Loading…
Cancel
Save