Django Admin use JWT

2019-08-21 19:08发布

问题:

Using:

  • Django 1.11
  • Python 3.6
  • DRF with JWT in FE

I understand that the Django admin uses a session, and basic authentication.

What I did so far: Replaced the Django Admin authentication signin page with AWS-Cognito:

  • The user goes to domain/admin/*, redirected to signin in AWS
  • On successful signin the user is redirected to the redirect_uri, leads to a Django View
  • In the view I replace the code with tokens
  • I can't navigate to any Admin page - I am trying to redirect, but that doesn't work since I didn't login() the User
  • Stuck - I would like to associate the User with the fetched tokens and authenticate with every Admin page request, and when the user logs out delete the tokens

What to do next?

  • When I use JWT with the Front End application, every request.META has HTTP_AUTHORIZATION, and uses a suitable backend.
  • I know how to add backends, and potentially leverage the user.backend (I also use Cognito-JWT for other FE portions, so already wrote BE for that)
  • I need to find a way to replace the Django Admin sessions authentication with the fetched token

Thank you!

EDIT:

If I login() the user, and set it to a model backend that I have already I can navigate to any admin page - but using the session that I created when I logged the user in.

I would like to have the user be set to a new model backend, with authentication that uses a token (from Django backend docs):

class MyBackend:
    def authenticate(self, request, token=None):
        # Check the token and return a user.
        ...
  1. How do I make the different Admin pages requests pass the token to the authentication?
  2. Where do I store the token? (I could make a NewUserModel that is 1-1 with the Django User model, and place a token field there)
  3. I am thinking of writing a middleware to capture all requests, and looking into the target URL - if Admin url, add the token to the HTTP_AUTHORIZATION once I fetch the user mentioned in #2 (the user is in every request due to DRF)

EDIT 2

My solution is getting more and more like this stack solution, I would have liked to know if there are any other options, but here is what I did so far:

  1. I made a model that has a 1-1 user field, and a tokens field
  2. As I am fetching/creating the user, I am also saving the tokens on the user's related model from #1 above
  3. I created a middleware that is capturing any request in process_request, and has access to the user. I can see the tokens there as I access the user's related model from #1 above.
  4. I am trying to set the HTTP_AUTHORIZATION header on the request, but cannot do that yet (currently stuck here)
  5. In my backend, I am looking at the incoming request, and trying to fetch the HTTP_AUTHORIZATION - not there yet.

EDIT 3

I ended up just using the Django session as is - once the user authenticates with AWS-Cognito once, it is safe to assume that it is a legitimate User.
Then I just dump the Cognito-JWT, and login() the User.

Note: I am still interested in a solution that would drop the Django session for using the Cognito-JWT, and would love to hear suggestions.