Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is JWT tokens authorization handling possible? #83

Open
41WhiteElephants opened this issue Jan 16, 2024 · 4 comments
Open

Is JWT tokens authorization handling possible? #83

41WhiteElephants opened this issue Jan 16, 2024 · 4 comments

Comments

@41WhiteElephants
Copy link

41WhiteElephants commented Jan 16, 2024

Hey,

I'd like to use webauthn(Fido2) in my app as mfa (second step). App consists of django BE and will consist of FE app (vue probably). That's why we decided to use JWT tokens authorization. Is it possible with this lib? I see everywhere in Readme and code the session based authentication method.
I'm using rest_framework_simplejwt.authentication.JWTAuthentication as DEFAULT_AUTHENTICATION_CLASSES. I tried starting Fido2 device registartion by mfa/fido2/begin_reg endpoint by it looks it's not authenticating user by Bearer token and user is seen in the endpoint as AnonymousUser. In other endpoints the user is properly authenticated by JWT access token
image

@mkalioby
Copy link
Owner

mkalioby commented Jan 17, 2024

Hello,

If you are interested only in webauthn, i think django-passkeys will be easier to integrate.

It already has a JSON interface, so it shall be easier as well to integrate with a frontend framework.

Give it a try, and I can help you to integrate it, and we can merge this in the main library.

To Solve your issue, you can add a middleware that converts the Bearer token to a request.user, or wrap begin_reg with a custom function that does the conversion and call it from your frontend, so django-mfa2 can work as expected.

@41WhiteElephants
Copy link
Author

We decided to use django-mfa2 as it's more mature than django-passkeys and has email OTP feature. I'll try wrapping begin_reg witha custom api endpoint and pass request.user there and write you back if it succeeded. Probably the same is necessary for complete_reg, authenticate_begin and complete_auth right?

@mkalioby
Copy link
Owner

Yes, sure, if you like you can submit a PR.

@41WhiteElephants
Copy link
Author

41WhiteElephants commented Jan 22, 2024

I'll show you how I was able to make JWT auth work with the django-mfa2 code. Maybe other folks will find it helpful how to use JWT with the lib.
I've created WebauthnChallenge model with user FK and a CharField for challenge and assign data from request.session to it. Then in complete registration step I fetch WebauthnChallenge object and assign it to request.session so django-mfa2 code can work as if I were using session based authentication.

I think it's good to think about rewriting of your lib into JWT handling as I believe the most of users will have
a contemporary stack with react/angular/vue based Frontend and I can't remember using session based authentication
in my commercial project. Maybe I'll push a PR with that but I don't have time for it right now.

My wrappers (anonymized)

custom begin registration
`
class BeginDeviceView(APIView):
permission_classes = (IsAuthenticated,)

def get(self, request, *args, **kwargs):
    response = begin_registeration(request)
    challenge = request.session['fido_state']['challenge']
    WebauthnChallenge.objects.create(user=request.user, challenge=challenge)
    return response

`

complete reg
'
class CompleteRegistrationView(APIView):
permission_classes = (IsAuthenticated,)

def post(self, request, *args, **kwargs):
    serializer = MySerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    challenge_obj = WebauthnChallenge.objects.filter(user=request.user).last()
    # transfer data into request.session that django-mfa2 uses
    request.session['fido_state'] = {
        'challenge': challenge_obj.challenge,
        'user_verification': None,
    }
    challenge_obj.delete()
    '''django-mfa2 expects cbor encoded request body, I wasn't able to
    make JWT work with Content-Type': 'application/cbor.
    I also, knowing attestationObject and clientDataJSON are just some  arrays
    representing bytes I don't believe CBOR add any more security to it
    '''

    request.body = cbor.encode({
        'attestationObject': request.data.get('attestationObject'),
        'clientDataJSON': request.data.get('clientDataJSON'),
    })
    response = complete_reg(request)
    response_data = json.loads(response.content.decode('utf-8'))
    if response_data.get('status') == 'ERR':
        # here my workaround to lack of proper status codes handling on exceptions
        # i wrote in issue no 84
        response.status_code = HTTP_400_BAD_REQUEST
    return response'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants