I have a React + DRF web app that has JWT authentication, in which I use djangorestframework-simplejwt.
I store access and refresh tokens in the localStorage. Is it possible to use these tokens to authenticate in Grafana? If yes, how can I do that? When I navigate to /grafana (with nginx help), I would like to see that my user in my app to be logged in to the Grafana, by creating the user for Grafana if necessary.
Let me explain all of the details for those who seek a solution to the problem of using common JWT for their app and Grafana. You can skip the beginning if you only care about Grafana side only:
React side:
// read token value from local storage
const refToken = localStorage.getItem("refresh_token");
window.location.href = `/grafana/login/?mytoken=${refToken}`;
Django REST Framework side (djangorestframework-simplejwt):
jwcrypto
. I set SIGNING_KEY
with the contents of the private key .pem and set VERIFYING_KEY
with the contents of the public key .pem.from jwcrypto import jwk
import uuid
keyid = str(uuid.uuid4())
key = jwk.JWK.generate(kty='RSA', alg='RS256', size=2048, kid=keyid, use='sig')
# export to PEM files
priv_pem = key.export_to_pem(private_key=True, password=None)
pub_pem = key.export_to_pem()
with open("rsa_pub.pem", "wb") as f:
f.write(pub_pem)
with open("rsa.pem", "wb") as f:
f.write(priv_pem)
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'SIGNING_KEY': open("/path/to/folder/which/has/keys/rsa.pem").read(),
'VERIFYING_KEY': open("/path/to/folder/which/has/keys/rsa_pub.pem").read(),
'ALGORITHM': 'RS256',
'USER_ID_FIELD': 'username',
'USER_ID_CLAIM': 'username',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
}
Grafana side:
To make sure that this is working, you need to create users with same username for the Grafana. Otherwise you will get Invalid JWT
response. auto_sign_up
setting is not working for the JWT authentication yet.
Then I added these configurations for Grafana container. header_name
can be any string and but you need to use it in nginx side too:
version: "3"
services:
...
...
grafana:
image: grafana/grafana:8.2.2
volumes:
- ...
- "/path/to/folder/which/has/keys:/key_set"
environment:
- "GF_SERVER_ROOT_URL=/grafana/"
- "GF_SERVER_SERVE_FROM_SUB_PATH=true"
- "GF_AUTH_PROXY_ENABLED=true"
- "GF_AUTH_PROXY_ENABLE_LOGIN_TOKEN=true"
- "GF_AUTH_JWT_ENABLED=true"
- "GF_AUTH_JWT_HEADER_NAME=X-JWT-Assertion"
- "GF_AUTH_JWT_USERNAME_CLAIM=username"
- "GF_AUTH_JWT_KEY_FILE=/key_set/rsa_pub.pem"
Nginx side:
location /grafana/ {
try_files /dev/null @proxy_grafana;
}
location /grafana/login/ {
try_files /dev/null @proxy_grafana_login;
}
location @proxy_grafana {
...
proxy_pass http://grafana:3000;
}
location @proxy_grafana_login {
...
proxy_set_header X-JWT-Assertion "${arg_mytoken}";
proxy_pass http://grafana:3000;
}