I created a new authentication server and a new token model to avoid the side effect when working with the inline token.
models.py
class ApiKeyToken(models.Model): key = models.CharField(max_length=40, primary_key=True) company = models.ForeignKey(Company) is_active = models.BooleanField(default=True) def save(self, *args, **kwargs): if not self.key: self.key = self.generate_key() return super(ApiKeyToken, self).save(*args, **kwargs) def generate_key(self): return binascii.hexlify(os.urandom(20)).decode() def __unicode__(self): return self.key
authentication.py
class ApiKeyAuthentication(TokenAuthentication): def get_token_from_auth_header(self, auth): auth = auth.split() if not auth or auth[0].lower() != b'api-key': return None if len(auth) == 1: raise AuthenticationFailed('Invalid token header. No credentials provided.') elif len(auth) > 2: raise AuthenticationFailed('Invalid token header. Token string should not contain spaces.') try: return auth[1].decode() except UnicodeError: raise AuthenticationFailed('Invalid token header. Token string should not contain invalid characters.') def authenticate(self, request): auth = get_authorization_header(request) token = self.get_token_from_auth_header(auth) if not token: token = request.GET.get('api-key', request.POST.get('api-key', None)) if token: return self.authenticate_credentials(token) def authenticate_credentials(self, key): try: token = ApiKeyToken.objects.get(key=key) except ApiKeyToken.DoesNotExist: raise AuthenticationFailed('Invalid Api key.') if not token.is_active: raise AuthenticationFailed('Api key inactive or deleted.') user = token.company.users.first()
Then you can request secure api with:
curl http://example.com/api/your-awesome-api.json -H "Authorization: Api-Key {token}"
source share