[Django]-Can I mix sessions auth and token auth in one site?

5👍

As you see in the documentation, you can configure multiple authentication backends without any problems. DRF will just try each one of the backends until one says “ok”.

One thing to keep in mind:
If you (for example) provide an invalid JSON-Web-Token then the authentication will immediately fail and other backends will not be tried. Good to see in the source of rest_framework_jwt.

def authenticate(self, request):
    """
    Returns a two-tuple of `User` and token if a valid signature has been
    supplied using JWT-based authentication.  Otherwise returns `None`.
    """
    auth = get_authorization_header(request).split()

    if not auth or auth[0].lower() != b'jwt':
        return None

    if len(auth) == 1:
        msg = 'Invalid JWT header. No credentials provided.'
        raise exceptions.AuthenticationFailed(msg)
    elif len(auth) > 2:
        msg = ('Invalid JWT header. Credentials string '
               'should not contain spaces.')
        raise exceptions.AuthenticationFailed(msg)

    try:
        payload = jwt_decode_handler(auth[1])
    except jwt.ExpiredSignature:
        msg = 'Signature has expired.'
        raise exceptions.AuthenticationFailed(msg)
    except jwt.DecodeError:
        msg = 'Error decoding signature.'
        raise exceptions.AuthenticationFailed(msg)

    user = self.authenticate_credentials(payload)

    return (user, auth[1])
  • return None means the backend saying: “this is not JWT, let the others try
  • raise exceptions.AuthenticationFailed(msg) means: “the user tried JWT, but the he failed it.”

To answer the further questions:

  • no need for doing this in separate applications (but it’s no problem if you want).
  • as you can read in “setting the authentication scheme” you can define global defaults for authentication backends, but you can also override them per View or ViewSet.

Leave a comment