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

Error when using custom header name #155

Open
thomasboni opened this issue Sep 3, 2019 · 1 comment
Open

Error when using custom header name #155

thomasboni opened this issue Sep 3, 2019 · 1 comment

Comments

@thomasboni
Copy link

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>
@thomasboni thomasboni changed the title Usage of custom Authorization header Error when using custom Authorization header Sep 3, 2019
@thomasboni thomasboni changed the title Error when using custom Authorization header Error when using custom header name Sep 3, 2019
@azolson
Copy link

azolson commented Apr 27, 2023

i had the same error when i was subclassing the authentication class....

it ended up being an extremely easy fix for me:

in settings, ensure that there is a comma when specifying the authentication class:

Before:

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

After:

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

(note the introduction of a , after utils.CustomAuth

Hope this helps!

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