Giter Site home page Giter Site logo

Comments (6)

arnuschky avatar arnuschky commented on July 28, 2024

I think I figured out how to do this; what works and what doesn't work.

I got api1 running using DRF-JWT. api2 now needs to verify authtokens coming from api1. I therefore use asymetric signing, install api1's public key on api2 and can now accept and verify authtokens issues by api1 - as it should be in a proper claims-based architecture. Logically, api2 only defines the decode_handler and ignores the encode_handler and payload_handlers.

What doesn't work is that Django needs a user object in it's internal user table for permissions to work (if I understood correctly). I figured that I would need to change the code so that the DRF-JWT can be run in "federated" mode. In that case, all the attributes of the user are included in the JWT, as is the group (if defined). api2 would then create the user's object on the fly, using the data from the token. If a group is given in the JWT, it must be defined.

That way, authentication and role association is done at the auth server (api1), while detailed authorization is done at each endpoint (api2 in this case) depending on the user's group.

Is this remotely sane? I am not very experienced with Django and auth frameworks, so I would appreciate a cross-check.

from django-rest-framework-jwt.

jpadilla avatar jpadilla commented on July 28, 2024

Hey @arnuschky this is great stuff. We're thinking of doing something like this, so we'll eventually have to take a look at some sane approach. The part that I think we both are a bit confused is what to do on api2 regarding users. I know that with Django you could set another whole DB that is used specifically for User objects, but that would be coupling the two systems. Another approach would be creating the user objects on the fly like you say, or having some kind of webhook system on api1 that notifies all other systems about changes to user, those systems would then create or update user objects on their side.

Let's definitely keep this thread updated with whatever progress we make. It will definitely make an interesting blog post and follow up on JWT and SSO.

from django-rest-framework-jwt.

arnuschky avatar arnuschky commented on July 28, 2024

Yes, it would obviously be preferable not to create anything in the DB, and just create user objects on the fly. Both APIs would still need to share the same model, but that shouldn't be a problem. My concern is mostly: if the user object is complex, I think it's not very sane to send all the user's data in every request. That means, going further than username, id, email and group is already a stretch IMHO. But I see no other way. (If absolutely required, api2 could do a REST GET on the user object if needed... But that seems like a nasty and would still couple the two systems)

I'll have a go at this one of these days.

from django-rest-framework-jwt.

lst7788 avatar lst7788 commented on July 28, 2024

Hi @arnuschky, is it possible to give an example of how you use asymmetric signing and install api1's public key on api2? I am stuck with this issue. API1 authentication works fine. However when accessing api2 with the same token in HTTP Authorization header, it always returns 403 Permission Denied. Don't know how to verify the auth token in api2. Could you please help? Thanks.

from django-rest-framework-jwt.

arnuschky avatar arnuschky commented on July 28, 2024

@lst7788: The example below should work. There are two APIs, api1 allows you to retrieve a JWT token that can be used to authenticate against both APIs. Note: both APIs need to share the same public key and user database.

In api1/settings.py:

JWT_AUTH = {
   'JWT_ENCODE_HANDLER': 'userdb.jwt_settings.jwt_encode_handler',
   'JWT_DECODE_HANDLER': 'userdb.jwt_settings.jwt_decode_handler',
   'JWT_PAYLOAD_HANDLER': 'userdb.jwt_settings.jwt_payload_handler'
}

In api1/jwt_settins.py:

import datetime
import jwt
import Crypto.PublicKey.RSA

pubKeyFile = open('path/public_key.pem','r')
pubKey = Crypto.PublicKey.RSA.importKey(pubKeyFile.read())
privKeyFile = open('path/private_key.pem','r')
privKey = Crypto.PublicKey.RSA.importKey(privKeyFile.read())

def jwt_payload_handler(user):
   return {
      'user_id': user.id,
      'email': user.email,
      'username': user.get_username(),
      # NOTE: for debugging, we made tokes valid for 1 hour
      'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=3600)
   }

def jwt_encode_handler(payload):
   return jwt.encode(
      payload,
      privKey,
      'RS256'
   ).decode('utf-8')

def jwt_decode_handler(token):
   return jwt.decode(
      token,
      pubKey,
      True,
      True,
      0
   )

In api2/settings.py:

JWT_AUTH = {
   'JWT_DECODE_HANDLER': 'userdb.jwt_settings.jwt_decode_handler'
  }

In api2/jwt_settins.py:

import datetime
import jwt
import Crypto.PublicKey.RSA

pubKeyFile = open('path/public_key.pem','r')
pubKey = Crypto.PublicKey.RSA.importKey(pubKeyFile.read())

def jwt_decode_handler(token):
   return jwt.decode(
      token,
      pubKey,
      True,
      True,
      0
   )

Let me know if this works. I had to scrap that project shortly after I figured out this part, so it never went into production. :|

from django-rest-framework-jwt.

lst7788 avatar lst7788 commented on July 28, 2024

@arnuschky , my issue is different and much simpler. I didn't do the Authorization right with the token retrieved. It is ok now, but thanks for your reply and your example. I believe it will help me when I come to that situation. :)

from django-rest-framework-jwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.