authentication.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. from __future__ import unicode_literals
  2. import base64
  3. from rest_framework import exceptions, HTTP_HEADER_ENCODING
  4. from rest_framework.authtoken.models import Token
  5. from rest_framework.authentication import BaseAuthentication, get_authorization_header, authenticate
  6. from desecapi.models import Domain
  7. class BasicTokenAuthentication(BaseAuthentication):
  8. """
  9. HTTP Basic authentication that uses username and token.
  10. Clients should authenticate by passing the username and the token as a
  11. password in the "Authorization" HTTP header, according to the HTTP
  12. Basic Authentication Scheme
  13. Authorization: Basic dXNlcm5hbWU6dG9rZW4=
  14. For username "username" and password "token".
  15. """
  16. model = Token
  17. """
  18. A custom token model may be used, but must have the following properties.
  19. * key -- The string identifying the token
  20. * user -- The user to which the token belongs
  21. """
  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. try:
  35. user, key = base64.b64decode(basic).decode(HTTP_HEADER_ENCODING).split(':')
  36. token = self.model.objects.get(key=key)
  37. except:
  38. raise exceptions.AuthenticationFailed('Invalid basic auth token')
  39. if not token.user.is_active:
  40. raise exceptions.AuthenticationFailed('User inactive or deleted')
  41. if user:
  42. try:
  43. Domain.objects.get(owner=token.user.pk, name=user)
  44. except:
  45. raise exceptions.AuthenticationFailed('Invalid username')
  46. return token.user, token
  47. def authenticate_header(self, request):
  48. return 'Basic'
  49. class URLParamAuthentication(BaseAuthentication):
  50. """
  51. Authentication against username/password as provided in URL parameters.
  52. """
  53. model = Token
  54. def authenticate(self, request):
  55. """
  56. Returns a `User` if a correct username and password have been supplied
  57. using URL parameters. Otherwise returns `None`.
  58. """
  59. if not 'username' in request.query_params:
  60. msg = 'No username URL parameter provided.'
  61. raise exceptions.AuthenticationFailed(msg)
  62. if not 'password' in request.query_params:
  63. msg = 'No password URL parameter provided.'
  64. raise exceptions.AuthenticationFailed(msg)
  65. return self.authenticate_credentials(request.query_params['username'], request.query_params['password'])
  66. def authenticate_credentials(self, userid, key):
  67. try:
  68. token = self.model.objects.get(key=key)
  69. except self.model.DoesNotExist:
  70. raise exceptions.AuthenticationFailed('Invalid token')
  71. if not token.user.is_active:
  72. raise exceptions.AuthenticationFailed('User inactive or deleted')
  73. return token.user, token