Auth Proxy Authentication

    1. [
    2. {
    3. "id":1,
    4. "name":"",
    5. "login":"admin",
    6. "email":"admin@localhost",
    7. "isAdmin":true
    8. }
    9. ]

    We can then send a second request to the /api/user method which will return the details of the logged in user. We will use this request to show how Grafana automatically adds the new user we specify to the system. Here we create a new user called “anthony”.

    1. curl -H "X-WEBAUTH-USER: anthony" http://localhost:3000/api/user
    2. {
    3. "email":"anthony",
    4. "name":"",
    5. "login":"anthony",
    6. "theme":"",
    7. "orgId":1,
    8. "isGrafanaAdmin":false
    9. }

    I’ll demonstrate how to use Apache for authenticating users. In this example we use BasicAuth with Apache’s text file based authentication handler, i.e. htpasswd files. However, any available Apache authentication capabilities could be used.

    In this example we use Apache as a reverse proxy in front of Grafana. Apache handles the Authentication of users before forwarding requests to the Grafana backend service.

    Apache configuration

    1. <VirtualHost *:80>
    2. ServerAdmin webmaster@authproxy
    3. ServerName authproxy
    4. ErrorLog "logs/authproxy-error_log"
    5. CustomLog "logs/authproxy-access_log" common
    6. <Proxy *>
    7. AuthType Basic
    8. AuthName GrafanaAuthProxy
    9. AuthBasicProvider file
    10. AuthUserFile /etc/apache2/grafana_htpasswd
    11. Require valid-user
    12. RewriteEngine On
    13. RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
    14. RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
    15. </Proxy>
    16. RequestHeader unset Authorization
    17. ProxyRequests Off
    18. ProxyPass / http://localhost:3000/
    19. ProxyPassReverse / http://localhost:3000/
    20. </VirtualHost>
    • The first four lines of the virtualhost configuration are standard, so we won’t go into detail on what they do.

    • The last 3 lines are then just standard reverse proxy configuration to direct all authenticated requests to our Grafana server running on port 3000.

    For this example, we use the official Grafana Docker image available at .

    • Create a file grafana.ini with the following contents

    Launch the Grafana container, using our custom grafana.ini to replace /etc/grafana/grafana.ini. We don’t expose any ports for this container as it will only be connected to by our Apache container.

    1. docker run -i -v $(pwd)/grafana.ini:/etc/grafana/grafana.ini --name grafana grafana/grafana

    For this example we use the official Apache docker image available at

    • Create a file httpd.conf with the following contents
    1. ServerRoot "/usr/local/apache2"
    2. Listen 80
    3. LoadModule mpm_event_module modules/mod_mpm_event.so
    4. LoadModule authn_core_module modules/mod_authn_core.so
    5. LoadModule authz_host_module modules/mod_authz_host.so
    6. LoadModule authz_user_module modules/mod_authz_user.so
    7. LoadModule authz_core_module modules/mod_authz_core.so
    8. LoadModule auth_basic_module modules/mod_auth_basic.so
    9. LoadModule log_config_module modules/mod_log_config.so
    10. LoadModule env_module modules/mod_env.so
    11. LoadModule headers_module modules/mod_headers.so
    12. LoadModule unixd_module modules/mod_unixd.so
    13. LoadModule rewrite_module modules/mod_rewrite.so
    14. LoadModule proxy_module modules/mod_proxy.so
    15. LoadModule proxy_http_module modules/mod_proxy_http.so
    16. <IfModule unixd_module>
    17. User daemon
    18. Group daemon
    19. </IfModule>
    20. ServerAdmin you@example.com
    21. <Directory />
    22. AllowOverride none
    23. Require all denied
    24. </Directory>
    25. DocumentRoot "/usr/local/apache2/htdocs"
    26. ErrorLog /proc/self/fd/2
    27. LogLevel error
    28. <IfModule log_config_module>
    29. LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    30. LogFormat "%h %l %u %t \"%r\" %>s %b" common
    31. <IfModule logio_module>
    32. LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    33. </IfModule>
    34. CustomLog /proc/self/fd/1 common
    35. </IfModule>
    36. <Proxy *>
    37. AuthType Basic
    38. AuthName GrafanaAuthProxy
    39. AuthBasicProvider file
    40. AuthUserFile /tmp/htpasswd
    41. Require valid-user
    42. RewriteEngine On
    43. RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
    44. RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
    45. RequestHeader unset Authorization
    46. ProxyRequests Off
    47. ProxyPass / http://grafana:3000/
    48. ProxyPassReverse / http://grafana:3000/
    • Create a htpasswd file. We create a new user anthony with the password password

      1. htpasswd -bc htpasswd anthony password
    • Launch the httpd container using our custom httpd.conf and our htpasswd file. The container will listen on port 80, and we create a link to the grafana container so that this container can resolve the hostname grafana to the Grafana container’s IP address.

    With our Grafana and Apache containers running, you can now connect to and log in using the username/password we created in the htpasswd file.

    To support the feature, auth proxy allows optional headers to map additional user attributes. The specific attribute to support team sync is Groups.

    1. # Optionally define more headers to sync other user attributes
    2. headers = "Groups:X-WEBAUTH-GROUPS"

    You use the X-WEBAUTH-GROUPS header to send the team information for each user. Specifically, the set of Grafana’s group IDs that the user belongs to.

    First, we need to set up the mapping between your authentication provider and Grafana. Follow to add groups to a team within Grafana.

    Once that’s done. You can verify your mappings by querying the API.

    1. curl -H "X-WEBAUTH-USER: admin" http://localhost:3000/api/teams/search
    2. {
    3. "totalCount": 2,
    4. "teams": [
    5. {
    6. "id": 1,
    7. "orgId": 1,
    8. "name": "Core",
    9. "email": "core@grafana.com",
    10. "avatarUrl": "/avatar/327a5353552d2dc3966e2e646908f540",
    11. "memberCount": 1,
    12. "permission": 0
    13. },
    14. {
    15. "id": 2,
    16. "orgId": 1,
    17. "name": "Loki",
    18. "email": "loki@grafana.com",
    19. "avatarUrl": "/avatar/102f937d5344d33fdb37b65d430f36ef",
    20. "memberCount": 0,
    21. "permission": 0
    22. }
    23. ],
    24. "page": 1,
    25. "perPage": 1000
    26. }
    27. # Then, query the groups for that particular team. In our case, the Loki team which has an ID of "2".
    28. curl -H "X-WEBAUTH-USER: admin" http://localhost:3000/api/teams/2/groups
    29. [
    30. {
    31. "orgId": 1,
    32. "teamId": 2,
    33. "groupId": "lokiTeamOnExternalSystem"
    34. }
    35. ]

    Finally, whenever Grafana receives a request with a header of X-WEBAUTH-GROUPS: lokiTeamOnExternalSystem, the user under authentication will be placed into the specified team. Placement in multiple teams is supported by using comma-separated values e.g. lokiTeamOnExternalSystem,CoreTeamOnExternalSystem.

    1. curl -H "X-WEBAUTH-USER: leonard" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" http://localhost:3000/dashboards/home
    2. {
    3. "meta": {
    4. "isHome": true,
    5. "canSave": false,
    6. ...
    7. }

    With this, the user leonard will be automatically placed into the Loki team as part of Grafana authentication.

    Learn more about Team Sync

    With enable_login_token set to true Grafana will, after successful auth proxy header validation, assign the user a login token and cookie. You only have to configure your auth proxy to provide headers for the /login route. Requests via other routes will be authenticated using the cookie.