Jwt authentication not working or showing in log

Even though I’ve turned on debug logs, I’m not seeing any error, info or debug messages about what is wrong with my auth.jwt configuration. And when trying to load the url (either directly in the browser, through an iframe or via curl), all I get is a 302 to the login page. Other posts have shown error messages in the log or json responses with ‘invalid jwt’ error messages. Is there something special I need to do to enable these messages so that I can debug?

  • What Grafana version and what operating system are you using?

I am using docker (compose):

    image: grafana/grafana
      - 3000:3000
      - ./grafana.ini:/etc/grafana/grafana.ini
      - mydata:/var/lib/grafana
      - ~/dev/keys:/etc/grafana/keys

grafana-1 | logger=settings t=2023-04-09T17:14:50.890135366Z level=info msg="Starting Grafana" version=9.4.7 commit=4add91f03d branch=HEAD compiled=2023-03-16T23:56:52Z

  • What are you trying to achieve?
    I would like to embed grafana dashboards in another application without requiring a user to log in to grafana first.

  • How are you trying to achieve it?
    I’ve enabled auth.jwt with the following settings (everything else is left as the default, full ini file included below)

level = debug

allow_embedding = true

enabled = true
enable_login_token = true
url_login = true
header_name = X-Forwarded-Access-Token
username_claim = username
key_file = /etc/grafana/keys/rsa_pub.pem
expect_claims = {}
auto_sign_up = true
  • What happened?

When trying to access in the browser http://grafana.staged-by-discourse.com/d/aDdiwfYVz/mybasicdash?orgId=0&kiosk&auth_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjgxMTMyNjkzLCJpYXQiOjE2ODEwNjA2OTMsImp0aSI6ImU5OTc2MjI3N2U2NjRlMjA4NTA2MjUyMGMyZTgyNDcyIiwidXNlcm5hbWUiOiJhbmRyZXdAbWlyc2t5dGVjaC5jb20ifQ.s93pF6XOsEZGA8uYZ8p3_ZemnNkGQCBcxu9Pnhbc4enkLqdhrSnmcl68rHzr7HCDUScyVdDbWb293iGvgnRmxSN4hFztm9USCGPWpmRaRtuFp1VVsjI6PN78sBVTqY0CjuVy1MaFiwuW7op9OiXoDoRtTgLZlx5igS72LJRHSDt-n0mZS_52VoRGkq4k9RTU2DR42FSrS7IigR3MT1nz_TlQ1TTa4BOXsHUsd__j3LeKEtSpfaKzCuYMXe0JPYZHGH2Z16dzc40_p5XC4ZzMHee8nqZTnH8uRUTrTn8J1O5vvYAS_ot4dGUMOU3TlgD4NUhLOUK9IunZfhjTNIiouA

From within an iframe, I get the same result.

The log message shows:
grafana-1 | logger=context userId=0 orgId=0 uname= t=2023-04-09T17:18:10.407958393Z level=info msg="Request Completed" method=GET path=/d/aDdiwfYVz/mybasicdash status=302 remote_addr= time_ms=11 duration=11.173144ms size=29 referer= handler=/d/:uid/:slug

and the browser gets the response:

HTTP/1.1 302 Found
Cache-Control: no-store
Content-Type: text/html; charset=utf-8
Location: /login
Set-Cookie: redirect_to=%2Fd%2FaDdiwfYVz%2Fmybasicdash%3ForgId%3D0%26kiosk%26auth_token%3DeyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjgxMTMyODYwLCJpYXQiOjE2ODEwNjA4NjAsImp0aSI6ImZjNTJmMDM2NzQwODQ3NDdiYTQyZmIwZjMxZWYzNmEwIiwidXNlcm5hbWUiOiJhbmRyZXdAbWlyc2t5dGVjaC5jb20ifQ.Zj_nJbas_KBtR1Wl0me1zPmB0QPebOQwbIA_bLGk7UKkbKz9lzEld5G_jrIBV2Z91PllpGqTPPhXgzg5KUPreJSyumnc2DDddUugvYJveQzCrlJXgNBAhXL4SKTD0e2HMR4_vH9hjX60ZM1VFOb1NeG5fQkunIdEaosbFGZsKyTofNVrRa-YbgdT1hTXHTbVkBQ-B7az2yPfB3c_3-XSwnpgiBy-adXdppbDAiaVtwFJCo0fDxduM64zTqLHyX42vPZb-JFe4TiqkGDUq6HPwXSt0KEAmrj84MOo9jroUNvsaQdjd5A6TyxP1JuysjxXIErfc-h-UUcmt_SAiq40Dg; Path=/; HttpOnly; SameSite=Lax
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Date: Sun, 09 Apr 2023 17:21:56 GMT
Content-Length: 29

the decoded jwt:

{'token_type': 'access', 'exp': 1681132693, 'iat': 1681060693, 'jti': 'e99762277e664e2085062520c2e82472', 'username': 'andrew@redacted.com'}
  • What did you expect to happen?

I was expecting to receive a 200 response and have the dashboard requested displayed. And I was expecting to see debug with a “Parsing JSON Web Token” message. Or I was expecting to see JWT error messages in the log.

  • Did you receive any errors in the Grafana UI or in related logs? If so, please tell us exactly what they were.
grafana-1   | logger=context userId=0 orgId=0 uname= t=2023-04-09T17:27:39.68145325Z level=info msg="Request Completed" method=GET path=/d/aDdiwfYVz/mybasicdash status=302 remote_addr= time_ms=12 duration=12.336072ms size=29 referer= handler=/d/:uid/:slug
grafana-1   | logger=infra.kvstore.sql t=2023-04-09T17:27:39.735457095Z level=debug msg="kvstore value not found" orgId=0 namespace=serviceaccounts key=hideApiKeys
grafana-1   | logger=ngalert.scheduler t=2023-04-09T17:27:40.012768444Z level=debug msg="Alert rules fetched" rulesCount=0 foldersCount=0 updatedRules=0
  • Did you follow any online instructions? If so, what is the URL?

I followed the instructions here: Configure JWT Authentication | Grafana documentation and What's new in Grafana v9.1 | Grafana documentation

I have also tried using the jwt token in the header using nginx by adding to docker compose:

    image: nginx
      - 9090:9090
      - ./mysite.conf:/etc/nginx/conf.d/mysite.conf

with the nginx configuration of

server {
    listen       9090;
    listen  [::]:9090;
    server_name  grafana.local;

    location / {
        proxy_set_header X-Forwarded-Access-Token "${arg_mytoken}";
        proxy_pass   http://grafana:3000;


with this line in /etc/hosts   grafana.local

Did you ever get this to work? I’m stuck with something very similar

I also have this issue when following this guide Securing Grafana with Pomerium | Pomerium

Not sure what to do about it :frowning:

Here’s the Grafana code that’s executed when processing JWT before anything is logged:

In my case, I had an error in the header name; it must be an exact match.


I know this is late, but I struggled with getting JWT setup as well and haven’t seen answers to questions like this here.

In your situation, the token you have in the url:

appears to be lacking a sub claim/attribute on it. And the JWT implementation at the moment silently ignores tokens that don’t have the sub claim right now. More details on my response to this person:

hope this sheds light on this for others that come across this post.

EDIT: so one thing to ensure is the tokens you’re using should have a sub claim on them.

1 Like

Generally, you should to use openid scope, when you are generating token - sub is OIDC claim Final: OpenID Connect Core 1.0 incorporating errata set 1 + use ID token (where sub should be available) and not access token (it sub may be available there).


I’m guessing the poster generated a super basic JWT manually and just left that out as they appear to be using username instead which is holding their “subject”.

However, some folks are stuck with custom/home grown JWT implementations which sometimes deviate from standards for various reasons only applicable to their situation.

These sorts of things happen sometimes. Debug logs indicating why something is getting ignored helps tremendously. Just saying. (A debug log, which exists but is not reachable, would have saved me hours of troubleshooting this specific problem in my recent experience. I eventually had to fall back to reading source code. At least I got to get familiar with go syntax. :sweat_smile: )

1 Like