1

Go a specific solution looking like this

High-level view

In Django as as you can see from my previous effort, got a specific endpoint

#urls.py
path('api/token/', MyTokenObtainPairView.as_view(), name='token_obtain'),

#views.py
class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

When I POST with an existing user like

Response given

I get a response where it's possible to see an access token similar to this

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwOTE0MTk4LCJqdGkiOiJhZDZmNzZhZjFmOGU0ZWJlOGI2Y2Y5YjQ4MGQzZjY2MiIsInVzZXJfaWQiOjExLCJpYXQiOjE1OTA5MTc0OTgsInVzZXIiOiJ0aWFnbyIsImRhdGUiOiIyMDIwLTA1LTMxIn0.-5U9P-WWmhlOenzCvc6b7_71Tz17LyNxe_DOMwwqH4RqrNsilVukEcZWFRGupLHRZjIvPya2QJGpiju9ujzQuw

How can I append the JWT as the "x-my-jwt" header to the upstream POST request?

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
  • 1
    You mean, from the client-side how to use that token in the header you are saying? well, that depends on the client-side app or framework i guess – gmc Jun 06 '20 at 10:29
  • @gmc Using Postman I can send that token as authorization bearer and that works fine. What would like is to append the JWT as the "x-my-jwt" header to the upstream POST request – Tiago Martins Peres Jun 06 '20 at 11:28
  • @TiagoMartinsPeres李大仁 what do you mean by upstream POST? Is that request from server code to another server or it's from some client making a request to your web server? – sonus21 Jun 07 '20 at 20:08
  • @sonus21 the HTTP proxy takes the POST request and appends the JWT. The upstream POST endpoint can be any dummy endpoint. – Tiago Martins Peres Jun 07 '20 at 20:35
  • 2
    @TiagoMartinsPeres李大仁: Usually Django creates the JWT and sends it back to the 'client' (bowser, mobile app, ...), the client 'saves' the JWT temporarily and sends it back with new requests. Your question is quite unclear what you mean by 'append' and 'upstream POST request'. – Maurice Meyer Jun 08 '20 at 00:26
  • @MauriceMeyer by append I mean of we check the header, it should have the token in it. Then, as we're looking at a request, then the client is upstream, and the server is downstream. – Tiago Martins Peres Jun 08 '20 at 01:30
  • @TiagoMartinsPeres李大仁 what type of proxy server is that? Have you read about the header rewrite, it should be possible to achieve using header rewrite. – sonus21 Jun 08 '20 at 04:01
  • @sonus21 the images shows - reverse proxy. Yes, did read about it yet didn't find a way to send that JWT (hence the question here). – Tiago Martins Peres Jun 08 '20 at 07:31
  • So, what you want is for nginx to check the Authorization header of the incoming request and, if it has the token, then wrote the content in a new header called 'x-my-jwt' ? – gmc Jun 08 '20 at 08:03
  • @gmc not necessarily the Authorization header but that could be one take to it yes – Tiago Martins Peres Jun 08 '20 at 08:37

2 Answers2

4
+---------+      +----------+           +--------+       +----------+
|         |      |          |           |        |       |          |
| Browser |----->|  Nginx   |---------->|Gunicorn| ----->|Django App|
|         |      |          |           |        |       |          |
+---------+      +----------+           +--------+       +----------+

Browser requests for the Access token at /api/token Response:

{
     "access" : "TOKENXYZ",
     "user" : "user",
     "date" : "2020-06-08",
}

Django Rest framework authenticator requires Authorization header to be present and that should have a prefix like Bearer, so you should set Authorization and x-my-jwt headers in the API call.

From browse, if you're using jQuery then do something like this.

$.ajax({
    type: 'POST',
    url: url,
    headers: {
        "x-my-jwt":"TOKEN_XYZ",
        "Authorization" : "Bearer TOKEN_XYZ"
    }
}).done(function(data) { 
    alert(data);
});

If you are making API call from your Django App to other Django App server that requires JWT tokens then set headers using requests library as

headers = {
   "x-my-jwt":"TOKEN_XYZ",
   "Authorization":"Bearer TOKEN_XYZ"
}
r = requests.post(url, data=payload, headers=headers)

You can also do header rewrite at the Nginx level if you want. in that case, you need to set the Authorization header. Authorization header is the same as the access token you have received in api/token call with a prefix Bearer. If you do not want Bearer in the my-jwt token then remove the Bearer component,

proxy_set_header X-my-jwt $http_authorization;
sonus21
  • 5,178
  • 2
  • 23
  • 48
  • `add_header` won't work, because `X-my-jwt` header will be added to nginx response. OP wants to add header to the upstream request, `proxy_set_header` should be used for this case (assuming his backend is not a fastcgi/uwsgi/etc). – Ivan Shatsky Jun 11 '20 at 10:15
  • Oh, yes we need to use set proxy set header. – sonus21 Jun 11 '20 at 10:21
1

According to this definition:

if you are looking at a request, then the client is upstream, and the server is downstream; in contrast, if you are looking at a response, then the client is downstream, and the server is upstream.

having the token in localStorage or as a state in Redux, we can send it with each request. depends on how the clientside framework is handling the requests or with Nginx

location some-location {
  add_header X-my-jwt $http_authorization;      
}

Nginx Reference

Naqib Hakimi
  • 874
  • 4
  • 15