Package: django-rest-microservice
django-rest-microserviceThis package is built on thedjangorestframework-simplejwtpackage, which provides
some JWT authentication mechanisms withDjango REST framework.
This package offers the following features:Provides refresh cookie in HttpOnly cookie, and access token in response body, for better security
when implemented properly with SPA.Provides an easier approach to customizing token claims than the standard mechanism described in
djangorestframework-simplejwt documentation.Provides a mechanism for authentication with a third-party IDP, before issuing internal JWT to your users.Currently, supports authentication with AWS Cognito using OAuth 2 Code Grant with PKCE for best security practices.InstallationInstall package to environment:pip install django-rest-microserviceIn the main urls.py, include the default package url routes:fromdjango.urlsimportpath,includeurlpatterns=[path("auth/",include("rest_framework_microservice.urls"))]In Django settings, include the following:INSTALLED_APPS=[...,'rest_framework_microservice',]REST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':('rest_framework_simplejwt.authentication.JWTTokenUserAuthentication',)}For log off / token black listing feature to work, you also need to include the following in django settings:INSTALLED_APPS=[...,'rest_framework_simplejwt.token_blacklist']and then run django migrations.REST API endpoints{{domain}}/auth/sign-in/Sign in directly against Django backend using username and password, retrieves access token and response body and
refresh token as HttpOnly cookie. The response body also contains a CSRF_token, which matches the same token set
in the HttpOnly cookie.curl --location --request POST '127.0.0.1:8000/auth/sign-in/' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "admin",
    "password": "admin"
}'{{domain}}/auth/social-exchange/Submits JWT tokens from an IDP (AWS Cognito), and in exchange for JWT tokens issue by Django server.
This will create a Django user if it does not already exist in the database. The response is the same assign-inendpoint above.curl --location --request POST '127.0.0.1:8000/auth/social-exchange/' \
--header 'Authorization: Bearer jwt_token_string \
--header 'Content-Type: application/json' \
--data-raw '{
    "id_token": "id_token_from_idp",
    "access_token": "access_token_from_idp",
    "refresh_token": "refresh_token_from_idp",
    "expires_in": 300,
    "token_type": "Bearer"
}'{{domain}}/auth/refresh/This endpoint accepts the refresh token and csrf token in HttpOnly cookies, and return an access token in response body.curl --location --request POST '127.0.0.1:8000/auth/refresh/' \
--header 'Authorization: Bearer jwt_token_string \
--header 'Content-Type: application/json' \
--data-raw '{
    "CSRF_token": "csrf_token"
}'{{domain}}/auth/logoff/This endpoint requiresrest_framework_simplejwt.token_blacklistto have been installed.
Call this endpoint to blacklist the current refresh token.curl --location --request POST '127.0.0.1:8000/auth/logoff/' \
--header 'Authorization: Bearer jwt_token_string \
--header 'Content-Type: application/json' \
--data-raw '{
    "CSRF_token": "csrf_token"
}'SettingsSettings are specified in Django settings.py underREST_FRAMEWORK_MICROSERVICE, the defaults are
the following:REST_FRAMEWORK_MICROSERVICE={"REFRESH_COOKIE_NAME":"refresh_cookie","REFRESH_COOKIE_PATH":"/auth","IDP":{"PROVIDER":"aws","REGION":"us-west-2","USER_POOL":"us-west-2_abcdefg","CLIENT_ID":"abcdefg",},"CUSTOM_TOKEN_USER_ATTRIBUTES":[],"CUSTOM_TOKEN_CALLABLE_ATTRIBUTES":[],"COOKIE_SALT":"extra","USER_SERIALIZER_CLASS":None,"USER_MODEL_UUID_FIELD":None,}REFRESH_COOKIE_NAMEName of refresh cookie to set in HTTP header.REFRESH_COOKIE_PATHURL path of refresh cookie, this should be a string that starts with a slash, ie: "/auth". This path
needs to match the path of authentication endpoint path set in urls.py.IDPA dictionary containing IDP attributes:PROVIDER: a string identifying what IDP backend to use, defaults to'aws'(Currently only AWS Cognito is supported.)REGION: user pool region.USER_POOL: user pool identifier used with the IDP.CLIENT_ID: IDP client id for your application.CUSTOM_TOKEN_USER_ATTRIBUTESThe list of Django user attributes to be copied to token as claims. i.e.:['is_active',].CUSTOM_TOKEN_CALLABLE_ATTRIBUTESThis is used to customize claims which cannot be done by simply usingCUSTOM_TOKEN_USER_ATTRIBUTESsetting.
This should be a list of dictionaries containingattr_nameandattr_getter.
i.e. :[{'attr_name': 'preferences', 'attr_getter': 'my_module.some_file.get_user_preferences'}, ...]The function specified inattr_gettershould accept an argument of a Django user instance.COOKIE_SALTSalt to be used when signing cookie.USER_SERIALIZER_CLASSDefaults to None. If specified, the default view serializers will try to add a user object representing the user.
The content of the user object is defined byUSER_SERIALIZER_CLASS.USER_MODEL_UUID_FIELDDefaults to None. Used to specify a field on the Django user model that can be used to store UUID from IDP.Customizing token claimsYou can include additional user attributes in the token claims by specifying them
in theCUSTOM_TOKEN_USER_ATTRIBUTES.You can also specify functions to return the value for custom claims by usingCUSTOM_TOKEN_CALLABLE_ATTRIBUTES.# settings.pyREST_FRAMEWORK_MICROSERVICE={...,'CUSTOM_TOKEN_CALLABLE_ATTRIBUTES':[{'attr_name':'user_services','attr_getter':'my_module.token_claims.get_user_subscribed_services'}]}# my_module.token_claims.pydefget_user_subscribed_services(user):returnuser.subscribed_servicesIf you are usingdjangorestframework-simplejwtversion <= 5.0.0, you will also need to extend therest_framework_simplejwt.models.TokenUserto include the additional claims. This is only applicable when usingolder versions.fromfunctoolsimportcached_propertyfromrest_framework_simplejwt.modelsimportTokenUserclassCustomTokenUser(TokenUser):"""Extend TokenUser and adds custom attributes to be pulled from TokenUser.This class should be specified in Django settings SIMPLE_JWT.TOKEN_USER_CLASS"""@cached_propertydeffirst_name(self):returnself.token.get('first_name',None)and include the following Django setting:SIMPLE_JWT={'TOKEN_USER_CLASS':'microservice.models.CustomTokenUser'}Third-party IDPThis package currently supports Cognito as an identity provider.
You can use AWS Cognito Userpool to enable social authentication.
Screenshot below for an example of setting up Cognito with Google sign in.AWS Cognito Userpool configurationsGoogle OAuth configurations