authentication.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import base64
  2. from rest_framework import exceptions, HTTP_HEADER_ENCODING
  3. from rest_framework.authentication import BaseAuthentication, get_authorization_header
  4. from desecapi.models import Token
  5. from rest_framework.authentication import TokenAuthentication as RestFrameworkTokenAuthentication
  6. class TokenAuthentication(RestFrameworkTokenAuthentication):
  7. model = Token
  8. class BasicTokenAuthentication(BaseAuthentication):
  9. """
  10. HTTP Basic authentication that uses username and token.
  11. Clients should authenticate by passing the username and the token as a
  12. password in the "Authorization" HTTP header, according to the HTTP
  13. Basic Authentication Scheme
  14. Authorization: Basic dXNlcm5hbWU6dG9rZW4=
  15. For username "username" and password "token".
  16. """
  17. # A custom token model may be used, but must have the following properties.
  18. #
  19. # * key -- The string identifying the token
  20. # * user -- The user to which the token belongs
  21. model = Token
  22. def authenticate(self, request):
  23. auth = get_authorization_header(request).split()
  24. if not auth or auth[0].lower() != b'basic':
  25. return None
  26. if len(auth) == 1:
  27. msg = 'Invalid basic auth token header. No credentials provided.'
  28. raise exceptions.AuthenticationFailed(msg)
  29. elif len(auth) > 2:
  30. msg = 'Invalid basic auth token header. Basic authentication string should not contain spaces.'
  31. raise exceptions.AuthenticationFailed(msg)
  32. return self.authenticate_credentials(auth[1])
  33. def authenticate_credentials(self, basic):
  34. invalid_token_message = 'Invalid basic auth token'
  35. try:
  36. user, key = base64.b64decode(basic).decode(HTTP_HEADER_ENCODING).split(':')
  37. token = self.model.objects.get(key=key)
  38. except Exception:
  39. raise exceptions.AuthenticationFailed(invalid_token_message)
  40. if not token.user.is_active:
  41. raise exceptions.AuthenticationFailed(invalid_token_message)
  42. return token.user, token
  43. def authenticate_header(self, request):
  44. return 'Basic'
  45. class URLParamAuthentication(BaseAuthentication):
  46. """
  47. Authentication against username/password as provided in URL parameters.
  48. """
  49. model = Token
  50. def authenticate(self, request):
  51. """
  52. Returns a `User` if a correct username and password have been supplied
  53. using URL parameters. Otherwise returns `None`.
  54. """
  55. if 'username' not in request.query_params:
  56. msg = 'No username URL parameter provided.'
  57. raise exceptions.AuthenticationFailed(msg)
  58. if 'password' not in request.query_params:
  59. msg = 'No password URL parameter provided.'
  60. raise exceptions.AuthenticationFailed(msg)
  61. return self.authenticate_credentials(request.query_params['username'], request.query_params['password'])
  62. def authenticate_credentials(self, _, key):
  63. try:
  64. token = self.model.objects.get(key=key)
  65. except self.model.DoesNotExist:
  66. raise exceptions.AuthenticationFailed('badauth')
  67. if not token.user.is_active:
  68. raise exceptions.AuthenticationFailed('badauth')
  69. return token.user, token