2016-02-15 2 views
1

Прямо сейчас у меня есть API, который находится на сервере, который также выдает токены доступа. API создан из Django Rest Framework и защищен OAuth2TokenAuthentication от django-oauth-toolkit, в то время как это работает нормально, но аутентификация выполняется с использованием токена, хранящегося локально.Структура Django rest OAuth2Authentication на сервере ресурсов на сервере Auth

class OAuth2Authentication(BaseAuthentication): 
    """ 
    OAuth 2 authentication backend using `django-oauth-toolkit` 

    """ 
    www_authenticate_realm = 'api' 

    def authenticate(self, request): 
     """ 
     Returns two-tuple of (user, token) if authentication succeeds, or None otherwise. 

     """ 
     oauthlib_core = get_oauthlib_core() 
     valid, r = oauthlib_core.verify_request(request, scopes=[]) 
     if valid: 
      return r.user, r.access_token 
     else: 
      return None 

    def authenticate_header(self, request): 
     """ 
     Bearer is the only finalized type currently 

     """ 
     return 'Bearer realm="{}"'.format(self.www_authenticate_realm) 

Я хотел бы разделить сервер на 2 сервера, проверка подлинности сервера и ресурсов сервера, так что сервис, на котором размещается API не нужно иметь символический механизм хранения. Как видно из приведенного выше кода, r.access_token является образцом экземпляра AccessToken.

Я не уверен, что это лучший способ, чтобы изменить проверку подлинности API для проверки на сервер удаленно (возможно, есть письменный пакет уже?)

Я был поиск в Интернете о лексемах валидаций, таких как this one, хотя он предлагает некоторые идеи, но, похоже, не достаточно определен для моей проблемы.

ответ

0

Мне удалось разработать доказательство концепции: создать конечную точку API на сервере аутентификации для проверки токенов и создания нового класса проверки подлинности, то, что она делает, - это переслать проверку подлинности маркера на сервер аутентификации, чтобы проверить токен, ответ сервера аутентификации включает в себя как токен, так и информацию пользователя, поэтому сервер ресурсов имеет возможность создать пользователя в своей локальной базе данных для создания сеанса пользователя.

class TokenIntrospectSerializer(ModelSerializer): 
    user = UserSerializer() 

    class Meta: 
     model = AccessToken 


class IntrospectView(APIView): 
    """ 
    An API view that introspect a given token 
    """ 
    serializer_class = TokenIntrospectSerializer 
    authentication_classes = [] 
    permission_classes = [] 

    def get(self, request, *args, **kwargs): 
     oauthlib_core = get_oauthlib_core() 
     valid, r = oauthlib_core.verify_request(request, scopes=[]) 
     if not valid: 
      raise APIException('Invalid token') 
     return Response(TokenIntrospectSerializer(r.access_token).data) 

Новый класс аутентификации на стороне RS.

class OAuth2RSAuthentication(BaseAuthentication): 
    """ 
    Forwards token to Authentication Server to validate the token 
    """ 

    class TokenObject(object): 
     """ 
     Inner class code borrowed from AccessToken model 
     provides necessary methods for Permission class to use 
     """ 
     scope = "" 
     token = "" 
     def __init__(self, token, scope): 
      self.token = token 
      self.scope = scope 

     def is_valid(self, scopes=None): 
      return self.allow_scopes(scopes) 

     def allow_scopes(self, scopes): 
      if not scopes: 
       return True 

      provided_scopes = set(self.scope.split()) 
      resource_scopes = set(scopes) 

      return resource_scopes.issubset(provided_scopes) 

    def authenticate(self, request): 
     # TODO Caching 
     oauthlib_core = get_oauthlib_core() 

     _, r = oauthlib_core.verify_request(request, scopes=[]) 
     result = requests.get("{}/api/token".format(settings.GOCONNECT_BASE_URL), params={'access_token': r.access_token}).json() 
     if 'user' in result: 
      user_data = result['user'] 
      user, created = User.objects.update_or_create(defaults=user_data, uuid=user_data['uuid']) 
      if user: 
       return user, self.TokenObject(result['token'], result['scope']) 
     return None 
Смежные вопросы