Skip to content

Error when using custom header name #155

Open
@thomasboni

Description

@thomasboni

Hello,

Following issue #99 I have tried to use a custom header name to get the JWT token.
When we use your module as a classical way (without custom header name) it works perfectly.

When we tried to use a custom header, something breaks, we have an error at each query:

Code:

class CustomAuth(JWTAuthentication):

    def get_header(self, request):
        header = request.META.get('HTTP_X_AUTHORIZATION')
        return header

Settings:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'utils.CustomAuth'
    ),
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=60),
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=7),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,

    'AUTH_HEADER_TYPES': ('JWT', 'Bearer', 'Basic'),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': datetime.timedelta(minutes=60),
    'SLIDING_TOKEN_REFRESH_LIFETIME': datetime.timedelta(days=7),
}

TypeError which occurs at each query:

TypeError at route
'type' object is not iterable
Request Method:	POST
Request URL:	route
Django Version:	2.0.9
Exception Type:	TypeError
Exception Value:	
'type' object is not iterable
Exception Location:	lib/python3.5/site-packages/rest_framework/views.py in get_authenticators, line 274
Python Executable:	bin/python
Python Version:	3.5.2
Python Path:	
[
 'lib/python35.zip',
 'lib/python3.5',
 'lib/python3.5/plat-x86_64-linux-gnu',
 'lib/python3.5/lib-dynload',
 '/usr/lib/python3.5',
 '/usr/lib/python3.5/plat-x86_64-linux-gnu',
 'lib/python3.5/site-packages']
Server time:	Mon, 8 Jul 2019 09:38:19 +0000


Traceback Switch to copy-and-paste view

lib/python3.5/site-packages/django/core/handlers/exception.py in inner
    This decorator is automatically applied to all middleware to ensure that
    no middleware leaks an exception and that the next middleware in the stack
    can rely on getting a response instead of an exception.
    """
    @wraps(get_response)
    def inner(request):
        try:
            response = get_response(request) ...
        except Exception as exc:
            response = response_for_exception(request, exc)
        return response
    return inner
▶ Local vars
Variable	Value
exc	
TypeError("'type' object is not iterable",)
get_response	
<bound method BaseHandler._get_response of <django.core.handlers.wsgi.WSGIHandler object at 0x7fe2ca54a9b0>>
request	
<WSGIRequest: POST 'route'>
lib/python3.5/site-packages/django/core/handlers/base.py in _get_response
                break
        if response is None:
            wrapped_callback = self.make_view_atomic(callback)
            try:
                response = wrapped_callback(request, *callback_args, **callback_kwargs)
            except Exception as e:
                response = self.process_exception_by_middleware(e, request) ...
        # Complain if the view returned None (a common error).
        if response is None:
            if isinstance(callback, types.FunctionType):    # FBV
                view_name = callback.__name__
            else:                                           # CBV
▶ Local vars
Variable	Value
callback	
<function WrappedAPIView at 0x7fe2ca7eee18>
callback_args	
()
callback_kwargs	
{}
middleware_method	
<bound method DebugToolbarMiddleware.process_view of <debug_toolbar.middleware.DebugToolbarMiddleware object at 0x7fe2ca555048>>
request	
<WSGIRequest: POST 'route'>
resolver	
<URLResolver 'diaas.urls' (None:None) '^/'>
resolver_match	
ResolverMatch(func=accounts.views.login, args=(), kwargs={}, url_name=None, app_names=[], namespaces=[])
response	
None
self	
<django.core.handlers.wsgi.WSGIHandler object at 0x7fe2ca54a9b0>
wrapped_callback	
<function WrappedAPIView at 0x7fe2ca7eee18>
lib/python3.5/site-packages/django/core/handlers/base.py in _get_response
            response = middleware_method(request, callback, callback_args, callback_kwargs)
            if response:
                break
        if response is None:
            wrapped_callback = self.make_view_atomic(callback)
            try:
                response = wrapped_callback(request, *callback_args, **callback_kwargs) ...
            except Exception as e:
                response = self.process_exception_by_middleware(e, request)
        # Complain if the view returned None (a common error).
        if response is None:
            if isinstance(callback, types.FunctionType):    # FBV
▶ Local vars
Variable	Value
callback	
<function WrappedAPIView at 0x7fe2ca7eee18>
callback_args	
()
callback_kwargs	
{}
middleware_method	
<bound method DebugToolbarMiddleware.process_view of <debug_toolbar.middleware.DebugToolbarMiddleware object at 0x7fe2ca555048>>
request	
<WSGIRequest: POST 'route'>
resolver	
<URLResolver 'diaas.urls' (None:None) '^/'>
resolver_match	
ResolverMatch(func=accounts.views.login, args=(), kwargs={}, url_name=None, app_names=[], namespaces=[])
response	
None
self	
<django.core.handlers.wsgi.WSGIHandler object at 0x7fe2ca54a9b0>
wrapped_callback	
<function WrappedAPIView at 0x7fe2ca7eee18>
lib/python3.5/site-packages/django/views/decorators/csrf.py in wrapped_view
def csrf_exempt(view_func):
    """Mark a view function as being exempt from the CSRF view protection."""
    # view_func.csrf_exempt = True would also work, but decorators are nicer
    # if they don't have side effects, so return a new function.
    def wrapped_view(*args, **kwargs):
        return view_func(*args, **kwargs) ...
    wrapped_view.csrf_exempt = True
    return wraps(view_func)(wrapped_view)
▶ Local vars
Variable	Value
args	
(<WSGIRequest: POST 'route'>,)
kwargs	
{}
view_func	
<function WrappedAPIView at 0x7fe2ca7eeea0>
lib/python3.5/site-packages/django/views/generic/base.py in view
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs) ...
        view.view_class = cls
        view.view_initkwargs = initkwargs
        # take name and docstring from class
        update_wrapper(view, cls, updated=())
▶ Local vars
Variable	Value
args	
()
cls	
<class 'accounts.views.WrappedAPIView'>
initkwargs	
{}
kwargs	
{}
request	
<WSGIRequest: POST 'route'>
self	
<accounts.views.WrappedAPIView object at 0x7fe2c9a4a4e0>
lib/python3.5/site-packages/rest_framework/views.py in dispatch
    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs) ...
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            self.initial(request, *args, **kwargs)
▶ Local vars
Variable	Value
args	
()
kwargs	
{}
request	
<WSGIRequest: POST 'route'>
self	
<accounts.views.WrappedAPIView object at 0x7fe2c9a4a4e0>
lib/python3.5/site-packages/rest_framework/views.py in initialize_request
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(), ...
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    def initial(self, request, *args, **kwargs):
        """
▶ Local vars
Variable	Value
args	
()
kwargs	
{}
parser_context	
{'args': (),
 'kwargs': {},
 'view': <accounts.views.WrappedAPIView object at 0x7fe2c9a4a4e0>}
request	
<WSGIRequest: POST 'route'>
self	
<accounts.views.WrappedAPIView object at 0x7fe2c9a4a4e0>
lib/python3.5/site-packages/rest_framework/views.py in get_authenticators
        """
        return [parser() for parser in self.parser_classes]
    def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [auth() for auth in self.authentication_classes] ...
    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        return [permission() for permission in self.permission_classes]
▶ Local vars
Variable	Value
self	
<accounts.views.WrappedAPIView object at 0x7fe2c9a4a4e0>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions