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

Customize bearer token in authorization header #467

Closed
tombra4ril opened this issue Jul 26, 2021 · 14 comments
Closed

Customize bearer token in authorization header #467

tombra4ril opened this issue Jul 26, 2021 · 14 comments
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@tombra4ril
Copy link

Hi,
I am using simplejwt for authentication. To authorize users for a particular endpoint the authorization header should contain the bearer token (JWT) followed by the access token but spectacular uses bearer as the default even after specifying "AUTH_HEADER_TYPES": ("JWT",) in simple_jwt configuration in my settings.py file.

Headers sent
curl -X POST "http://localhost:8000/api/v1/auth/test" -H "accept: /" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjI3Mjc0MTYzLCJqdGkiOiIwMjU2NjAyOWViZDg0NDk4OWU2Y2QyMTgwNzc0YTczZ..." -H "X-CSRFToken: lioQLVfM4CLuI2cSVXE1MtXRBeAHYHH6FnlmUGqkKpnqd2PmNFQ9Yrop323tOu6q" -d ""

Expected headers
curl -X POST "http://localhost:8000/api/v1/auth/test" -H "accept: /" -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjI3Mjc0MTYzLCJqdGkiOiIwMjU2NjAyOWViZDg0NDk4OWU2Y2QyMTgwNzc0YTczZ..." -H "X-CSRFToken: lioQLVfM4CLuI2cSVXE1MtXRBeAHYHH6FnlmUGqkKpnqd2PmNFQ9Yrop323tOu6q" -d ""
Thanks for your response in advance.

@tfranzel
Copy link
Owner

Hi,

so we do use the AUTH_HEADER_TYPES:

'bearerFormat': api_settings.AUTH_HEADER_TYPES[0],

Do you use a custom version of rest_framework_simplejwt.authentication.JWTAuthentication? the extension might not be used by default then.

@tombra4ril
Copy link
Author

Thanks for your quick response.
I am using the standard rest_framework_simplejwt, only customizing my own TokenObtainPairView class to obtain the access token and refresh token.

@tfranzel tfranzel added the bug Something isn't working label Jul 26, 2021
@tfranzel
Copy link
Owner

this is indeed a bug. same thing was fixed for DRF's TokenAuthentication but it was forgotten here.

however, the solution to this is not perfect. OpenAPI3 does not directly support customizing "Bearer". When you use non-"Bearer", you will need to put the whole shabang into SwaggerUI, i.e. JWT 1234deadbeef and not just the token. A comment however will document this.

preparing a fix right now.

@tombra4ril
Copy link
Author

Thanks alot.
Adding a non-bearer authentication header type such as JWT before the access token, the swagger ui (drf_spectacular) always prefixed the authorization header with Bearer which will make the authorization header fail because it is now Bearer JWT 1234deadbeef....
So, I just reverted back to using Bearer as the AUTH_HEADER_TYPES in SIMPLE_JWT configuration in settings.py file. This can as well do the job while I wait for the fix.
Thanks alot.

@tfranzel
Copy link
Owner

@tombra4ril yes that was the problem. with this commit "Bearer" is not prefixed anymore, iff it is some other value like "JWT".

@tfranzel tfranzel added the fix confirmation pending issue has been fixed and confirmation from issue reporter is pending label Jul 26, 2021
@tfranzel
Copy link
Owner

closing this issue for now. feel free to comment if anything is missing or not working and we will follow-up.

@tombra4ril
Copy link
Author

@tfranzel sorry for the delay. Was able to install this fix commit and the authorization bug has been fixed, thanks a lot.

@SidneyNiccolson
Copy link

Hi there,

First of great library! We are using FireBase for our authentication (drf_firebase_auth.authentication.FirebaseAuthentication).

In turn we tried to use the bearerFormat as denoted here. Example:

from drf_spectacular.extensions import OpenApiAuthenticationExtension


class FireBaseTokenScheme(OpenApiAuthenticationExtension):
    target_class = "drf_firebase_auth.authentication.FirebaseAuthentication"
    name = "FireBaseTokenAuth"

    def get_security_definition(self, auto_schema):
        return {
            "type": "http",
            "scheme": "bearer",
            "bearerFormat": "JWT",
        }

Actual response:
curl -X 'GET'
'http://127.0.0.1:8000/batch/'
-H 'accept: application/json'
-H 'Authorization: Bearer 1234'
-H 'X-CSRFToken: lioQLVfM4CLuI2cSVXE1MtXRBeAHYHH6FnlmUGqkKpnqd2PmNFQ9Yrop323tOu6q'

Expected response:
curl -X 'GET'
'http://127.0.0.1:8000/batch/'
-H 'accept: application/json'
-H 'Authorization: JWT 1234'
-H 'X-CSRFToken: lioQLVfM4CLuI2cSVXE1MtXRBeAHYHH6FnlmUGqkKpnqd2PmNFQ9Yrop323tOu6q'

The only way I was able to make it functional was in the following way:

from django.utils.translation import gettext_lazy as _
from drf_spectacular.extensions import OpenApiAuthenticationExtension


class FireBaseTokenScheme(OpenApiAuthenticationExtension):
    target_class = "drf_firebase_auth.authentication.FirebaseAuthentication"
    name = "FireBaseTokenAuth"

    def get_security_definition(self, auto_schema):
        return {
            "type": "apiKey",
            "in": "header",
            "name": "Authorization",
            "description": _('Token-based authentication with required prefix "%s"')
            % "JWT",
        }

However it seems that this is not ideal and more of a workaround. I see the ticket is closed, but not sure how I can specify the bearerFormat correctly for JWT using FireBase auth. Thanks in advance.

@tfranzel
Copy link
Owner

Hi @SidneyNiccolson, so bearerFormat: is actually non-functional and purely for documentation purposes. it does not specify the the prefix keyword in the header. this certainly confused me the first go round.

the documentation suggests this and SwaggerUI actually implements it like that. afaik there is no way to specify a hard-coded prefix in OpenAPI 3.0.3 other than Bearer. That workaround is the only working solution i am aware of.

you can try this yourself with https://editor.swagger.io/. the last time i tried fiddling around with bearerFormat, it had zero effect. feel free to suggest a better solution 😄

@deepakkumhar
Copy link

deepakkumhar commented Jun 17, 2022

hello,
how can i change name of security (exmple-jwtauth to breareauth) in Django swagger spectacular???

@tfranzel
Copy link
Owner

@deepakkumhar it depends on which lib you are using: rest_framework_jwt or rest_framework_simplejwt. generally you would override the existing extension with higher priority and change the name. just put that extension where the interpreter sees it at least once.

from drf_spectacular.contrib.rest_framework_simplejwt import SimpleJWTScheme

class CustomSimpleJWTScheme(SimpleJWTScheme):
    name = 'breareauth'
    priority = 1

or

from drf_spectacular.contrib.rest_framework_jwt import JWTScheme

class CustomJWTScheme(JWTScheme):
    name = 'breareauth'
    priority = 1

@deepakkumhar
Copy link

deepakkumhar commented Jul 8, 2022

@deepakkumhar it depends on which lib you are using: rest_framework_jwt or rest_framework_simplejwt. generally you would override the existing extension with higher priority and change the name. just put that extension where the interpreter sees it at least once.

from drf_spectacular.contrib.rest_framework_simplejwt import SimpleJWTScheme

class CustomSimpleJWTScheme(SimpleJWTScheme):
    name = 'breareauth'
    priority = 1

or

from drf_spectacular.contrib.rest_framework_jwt import JWTScheme

class CustomJWTScheme(JWTScheme):
    name = 'breareauth'
    priority = 1

thank you 👍

@deepakkumhar
Copy link

@tfranzel
how can i remove or hide auto generate schema in drf_spectacular like my enum field generating separate schema so i want to remove it.
,i am using Django rest framework for api

@deepakkumhar
Copy link

how can i remove or hide auto generate schema in drf_spectacular like my enum field generating separate schema so i want to remove it.
,i am using Django rest framework for api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

4 participants