Skip to content
This repository has been archived by the owner on May 26, 2020. It is now read-only.

added setting JWT_PUBLIC_KEY_USING_HEADER_HANDLER #471

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

devsnd
Copy link

@devsnd devsnd commented Feb 26, 2019

added setting JWT_PUBLIC_KEY_USING_HEADER_HANDLER to dynamically fetch public keys based on the header

when setting an import path to a callable into JWT_PUBLIC_KEY_USING_HEADER_HANDLER, it will be called with the JWT header as parameter. This allows to e.g. fetch dynamically changing certificates, like
google does it for example.

…h public keys based on the header

when setting an import path to a callable into JWT_PUBLIC_KEY_USING_HEADER_HANDLER, it will be called
with the JWT header as parameter. This allows to e.g. fetch dynamically changing certificates, like
google does it for example
@devsnd
Copy link
Author

devsnd commented Feb 26, 2019

Dear DRF-JWT developers,

I made this small change that allows to get a public key based on the header of the JWT token. This allows for easy integration with e.g. firebase, as the public keys and certificates are rotated hourly.

Here is some example code of how you could use this:

import requests
from OpenSSL import crypto

def get_public_key_for_payload(unverified_payload):
    kid = unverified_payload['kid']
    certificates = requests.get('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com').json()
    certificate = certificates[kid]
    pubkey = certificate.get_pubkey()
    pem_pubkey = crypto.dump_publickey(crypto.FILETYPE_PEM, pubkey)
    return pem_pubkey

Then you could use this callback to get the right pubkey like this:

JWT_PUBLIC_KEY_USING_HEADER_HANDLER = 'my_package.get_public_key_for_payload'

Please note that you should cache the request based using the kid as cache key in production!

…ttings decorator for tests

By fixing the settings being clobbered by the original APISettings implementation of
restframework, we can now listen to settings changes using the `setting_changed` signal.

This signal is used by the @override_settings decorator. This means that you can now perform
tests that would for example override the JWT_VERIFY_EXPIRATION setting, allowing for testing
without generating new tokens on the fly.
@codecov
Copy link

codecov bot commented Feb 26, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@0a0bd40). Click here to learn what that means.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #471   +/-   ##
=========================================
  Coverage          ?   90.34%           
=========================================
  Files             ?       12           
  Lines             ?      818           
  Branches          ?       29           
=========================================
  Hits              ?      739           
  Misses            ?       66           
  Partials          ?       13
Flag Coverage Δ
#codecov 90.34% <ø> (?)
#dj110 87.04% <ø> (?)
#dj111 87.04% <ø> (?)
#dj18 89.48% <ø> (?)
#dj19 89.48% <ø> (?)
#drf31 89.48% <ø> (?)
#drf32 89.48% <ø> (?)
#drf33 89.48% <ø> (?)
#drf34 90.34% <ø> (?)
#drf35 89.97% <ø> (?)
#drf36 89.97% <ø> (?)
#py27 90.34% <ø> (?)
#py34 89.97% <ø> (?)
#py35 87.04% <ø> (?)
#py36 87.04% <ø> (?)
Impacted Files Coverage Δ
rest_framework_jwt/settings.py 100% <ø> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0a0bd40...9ef21a3. Read the comment docs.

@devsnd
Copy link
Author

devsnd commented Feb 26, 2019

I fixed the JWT_AUTH settings being clobbered by DRF when calling reload on the APISettings object. This means that @override_settings decorators now work properly.

By fixing the settings being clobbered by the original APISettings implementation of
restframework, we can now listen to settings changes using the setting_changed signal.

This signal is used by the @override_settings decorator. This means that you can now perform
tests that would for example override the JWT_VERIFY_EXPIRATION setting, allowing for testing
without generating new tokens on the fly.

E.g. this works now:

@override_settings(JWT_AUTH=dict(settings.JWT_AUTH, JWT_VERIFY_EXPIRATION=False))
def test(self):
    assert can_auth_with_expired_token()

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

Successfully merging this pull request may close these issues.

None yet

3 participants