prosource

Facebook Auth with AngularJS 및 장고 REST 프레임워크

probook 2023. 2. 8. 18:06
반응형

Facebook Auth with AngularJS 및 장고 REST 프레임워크

Angular를 사용하여 SPA 어플리케이션을 개발 중입니다.서버에 대해 Django 백엔드를 사용하는 JS.SPA에서 서버와 통신하는 방법은 django-rest-framework입니다.facebook(google과 twitter도)을 사용하여 인증을 하고 싶습니다.이 토픽을 많이 읽었는데, 클라이언트 SPA 측에서 자동 인증을 하고 있는 OAuth.io과 서버 측에서 인증을 하고 있는 python-social-auth를 발견했습니다.

그래서 현재 클라이언트 인증만 가지고 있고, 앱은 facebook(OAuth.io)에 접속하여 정상적으로 로그인하고 있습니다.이 프로세스는 access_token을 반환하고 API에 요청을 합니다.API는 이 사용자를 로그인하거나 지정된 토큰으로 이 사용자의 계정을 생성해야 하며 이 부분은 작동하지 않습니다.python-social-auth 사용에 대한 완전한 튜토리얼이 없기 때문에 제가 뭔가 놓쳤거나..나도 몰라..

그래서 내가 가지고 있는 몇 가지 암호:

SPA 측:이것은 OAuth.io과의 접속으로, 액세스 토큰을 취득하고 있기 때문에 동작하고 있습니다.그러면 rest API에 요청을 해야 합니다. 백엔드는 '페이스북', '구글', '트위터'입니다.

OAuth.initialize('my-auth-code-for-oauthio');
OAuth.popup(backend, function(error, result) {
    //handle error with error
    //use result.access_token in your API request

    var token = 'Token ' + result.access_token;
    var loginPromise = $http({
         method:'POST', 
         url: 'api-token/login/' + backend + '/', 
         headers: {'Authorization': token}});

         loginPromise.success(function () {
             console.log('Succeess');
         });
         loginPromise.error(function (result) {
             console.log('error');
         });
});

settings.py의 서버에서 설치된 앱, 템플릿 컨텍스트 프리프로세서, 일부 인증 백엔드에 소셜 플러그인을 추가했습니다.이것이 내 파일입니다.

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    ...,
    'rest_framework',
    'rest_framework.authtoken',
    'api',
    'social.apps.django_app.default',
    'social'
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
                               "django.core.context_processors.debug",
                               "django.core.context_processors.i18n",
                               "django.core.context_processors.media",
                               "django.core.context_processors.static",
                               "django.core.context_processors.request",
                               "django.contrib.messages.context_processors.messages",
                               'social.apps.django_app.context_processors.backends',
                               'social.apps.django_app.context_processors.login_redirect',)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

SOCIAL_AUTH_FACEBOOK_KEY = 'key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'secret'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

AUTHENTICATION_BACKENDS = (
      'social.backends.open_id.OpenIdAuth',
      'social.backends.facebook.FacebookOAuth2',
      'social.backends.facebook.FacebookAppOAuth',
      'social.backends.google.GoogleOpenId',
      'social.backends.google.GoogleOAuth2',
      'social.backends.google.GoogleOAuth',
      'social.backends.twitter.TwitterOAuth',
      'django.contrib.auth.backends.ModelBackend',
  )

API의 views.py에는 다음과 같은 정보가 있습니다(여기서 찾았습니다).

from django.contrib.auth.models import User, Group
from rest_framework import viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, parsers, renderers
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import api_view, throttle_classes
from social.apps.django_app.utils import strategy
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
    renderer_classes = (renderers.JSONRenderer,)
    serializer_class = AuthTokenSerializer
    model = Token

    # Accept backend as a parameter and 'auth' for a login / pass
    def post(self, request, backend):
        serializer = self.serializer_class(data=request.DATA)

        if backend == 'auth':
            if serializer.is_valid():
                token, created = Token.objects.get_or_create(user=serializer.object['user'])
                return Response({'token': token.key})
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        else:
            # Here we call PSA to authenticate like we would if we used PSA on server side.
            user = register_by_access_token(request, backend)

            # If user is active we get or create the REST token and send it back with user data
            if user and user.is_active:
                token, created = Token.objects.get_or_create(user=user)
                return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})

@strategy()
def register_by_access_token(request, backend):
    backend = request.strategy.backend
    user = request.user
    user = backend._do_auth(
        access_token=request.GET.get('access_token'),
        user=user.is_authenticated() and user or None
    )
    return user

마지막으로 URL에 루트가 있습니다.py:

...
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
url(r'^api-token/login/(?P<backend>[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P<backend>[^/]+)/', views.register_by_access_token),
...

인증을 시도할 때마다 OAuth.io이 작동하고 api에 대한 rqest가 반환됩니다.

상세: "잘못된 토큰"

python-social-auth 설정에서 누락되었거나 모든 것을 잘못하고 있는 것 같습니다.그래서 아이디어나 도움이 되고 싶은 사람이 있으면 좋겠습니다.

다음 행을 GetAuthToken 클래스에 추가합니다.

authentication_classes = ()

오류 {"detail": "Invalid token"}이(가) 사라집니다.

여기 그 이유가 있다...

요청에 다음 헤더가 포함되어 있습니다.

Authorization: Token yourAccessToken

rest_displays는 정의되어 있습니다.인증이 필요합니다.DEFAULT_AUTHENTICATION_CLASSES 토큰 인증

이 Django를 기반으로 토큰을 전달한 경우 토큰 인증을 수행하려고 합니다.facebook용 액세스 토큰으로 django *_token 데이터베이스에 존재하지 않기 때문에 실패합니다.따라서 유효하지 않은 토큰 오류입니다.이 경우 이 뷰에 TokenAuthentication을 사용하지 않도록 Django에게 지시하기만 하면 됩니다.

참고:

GetAuthToken 포스트 메서드가 실행되기 전에 코드 실행이 중지되었기 때문에 추가 오류가 발생할 수 있습니다.개인적으로 당신의 코드를 확인하려고 할 때 오류가 발생했습니다.

'DjangoStrategy' object has no attribute 'backend'

backend = request.strategy.backend

로 변경하여 해결했습니다.

uri = ''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)

또한 register_by_access_token 함수는 참조한 블로그의 작업 코드와 일치하지 않으므로 갱신해야 합니다.블로그 작성자가 최신 코드를 여기에 올렸습니다.사용하시는 버전에서는 인증 헤더에서 토큰을 꺼내지 않습니다.이것은, Facebook등의 서드 파티의 인증에 필요한 토큰입니다.

네, 해결됐습니다.설정이 올바르지 않으므로 권한을 추가해야 합니다.

 REST_FRAMEWORK = {
     # Use hyperlinked styles by default.
     # Only used if the `serializer_class` attribute is not set on a view.
     'DEFAULT_MODEL_SERIALIZER_CLASS':
         'rest_framework.serializers.HyperlinkedModelSerializer',

     # Use Django's standard `django.contrib.auth` permissions,
     # or allow read-only access for unauthenticated users.
     'DEFAULT_PERMISSION_CLASSES': [
         'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
     ]
 }

파이프라인에 대한 정보:

 SOCIAL_AUTH_PIPELINE = (
     'social.pipeline.social_auth.social_details',
     'social.pipeline.social_auth.social_uid',
     'social.pipeline.social_auth.auth_allowed',
     'social.pipeline.social_auth.social_user',
     'social.pipeline.user.get_username',
     'social.pipeline.social_auth.associate_by_email',
     'social.pipeline.user.create_user',
     'social.pipeline.social_auth.associate_user',
     'social.pipeline.social_auth.load_extra_data',
     'social.pipeline.user.user_details'
 )

저도 당신처럼 툴을 사용하고 있습니다만, 로그인/등록/...을 패키지와 함께 제공하고 API 처리에 사용합니다.

인스톨 순서에 따라서, 그것들을 나머지 API에 사용할 필요가 있습니다.

" " " allauth ★★★★★★★★★★★★★★★★★」rest-auth합니다. 용 apps apps apps apps:

INSTALLED_APPS = (
    ...,
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth'
    ...,
    'allauth',
    'allauth.account',
    'rest_auth.registration',
    ...,
    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
)

다음으로 커스텀 URL을 추가합니다.

urlpatterns = patterns('',
    ...,
    (r'^auth/', include('rest_auth.urls')),
    (r'^auth/registration/', include('rest_auth.registration.urls'))
)

마지막으로 다음 행을 추가합니다.

TEMPLATE_CONTEXT_PROCESSORS = (
    ...,
    'allauth.account.context_processors.account',
    'allauth.socialaccount.context_processors.socialaccount',
    ...
)

또, 타입의 registration에 가 없습니다은, 「2」의 「로그인.레지스트레이션」의 「로그인.레지스트레이션」이기 때문입니다.allauth loginpackage의 django를 모두 합니다.

도움이 되었으면 좋겠다

언급URL : https://stackoverflow.com/questions/20786327/facebook-auth-with-angularjs-and-django-rest-framework

반응형