2
votes

I'm trying to set up social registration (google, facebook, twitter) in my web application. I use Django Rest Framework for backend and Angular2 for the frontend. The standard registration works well with django-rest-auth. I would like to set up the social auth part with django-allauth. The social authentication scenario is :

  • User clicks on "Login with Facebook" button
  • He his redirected to Facebook's authorization page
  • He accepts the Facebook authorization request
  • He is redirected back to my web app while logged in

But first, I don't know how to redirect the user to the facebook authorization page. When I go to http://localhost:8000/rest-auth/facebook/, the form required data are "Access token" and "Code". But to set these data I have to get them from the facebook authorization page. Am I right? How can I do it? How can I redirect the user to the social (facebook, google, twitter) authorization page ?

1

1 Answers

5
votes

Check out python-social-auth. It's an alternative to django-allauth but easier to use. From your question, in order to enable facebook login, you need to capture the access token from the request made by angular2 to the facebook api and pass it to your backend.For your django backend, implement an api using django-rest-framework. You can go about this in the following steps:

  1. Register your application in facebook developers page.In the settings, leave the app domain empty and set the site url to http://localhost:8000. After successful setup, grab the app secret and app id. You will use it later on.

  2. In your angular2 app index.html file, add the following script to your body.

<script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.7&appId=1622731728039944"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); </script>

  1. npm install ng2-facebook-sdk and in th constructor for your component initialize the sdk

` import {FacebookService, FacebookLoginResponse, FacebookInitParams} from 'ng2-facebook-sdk/dist';

@Component(...)
export class MyComponent {
  constructor(private fb: FacebookService) {
    let fbParams: FacebookInitParams = {
                                   appId: '123456789',
                                   xfbml: true,
                                   version: 'v2.6'
                                   };
    this.fb.init(fbParams);
  }
}
  1. Add login function

login() { this.fb.login({ scope: 'public_profile', return_scopes: true }).then( (response: FacebookLoginResponse) => { status = response['status']; var userId = response['authResponse'].userID; if (status == 'connected') { let access_token = response['authResponse']['accessToken']; localStorage.setItem('id_token', access_token); this.router.navigate(['/home']); } }, (error: any) => console.error(error) ); }

  1. Then in every request you make to your backend, include the access token in the header. This will authenticate the user in your backend. if the user doesn't exist, he will be created. e.g var headers = new Headers(); headers.append('Content-Type', 'application/x-www-form-urlencoded'); headers.append('Authorization', 'Bearer facebook ' + localStorage.getItem('id_token')); return this.http.post(this.url + '/api/images/edits/' + thumbId + '/', null, { headers: headers }) .map(res => res.json());

  2. In your django backend, pip install django-rest-framework-social-oauth2 and add these to your installed apps in settings.py. INSTALLED_APPS = ( ... 'oauth2_provider', 'social.apps.django_app.default', 'rest_framework_social_oauth2',)

    Add it to authentication class for restframework

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'oauth2_provider.ext.rest_framework.OAuth2Authentication', 'rest_framework_social_oauth2.authentication.SocialAuthentication', ), }

And set the authentication backends. Add facebook and any other social auth backend you need.

AUTHENTICATION_BACKENDS = ( 'social.backends.facebook.FacebookAppOAuth2', 'social.backends.facebook.FacebookOAuth2', 'rest_framework_social_oauth2.backends.DjangoOAuth2', 'django.contrib.auth.backends.ModelBackend', ) PROPRIETARY_BACKEND_NAME = 'Facebook' SOCIAL_AUTH_FACEBOOK_SECRET = 'blablabla'

  1. In your view add the following decorator. This will be called on every request that requires authentication. Be sure to also add permission_classes = (IsAuthenticated,) to views that need to be protected.

` from social.apps.django_app.utils import load_backend, load_strategy, psa from social.apps.django_app.views import _do_login from rest_framework.permissions import IsAuthenticated

@psa('social:complete')
def auth_by_fb_token(request, backend):
    token = request.GET.get('access_token')
    user = request.backend.do_auth(token)
    if user:
        return user

Thus the access token you pass to the api will be used to authenticate and create a user in your backend. Redirection to the authentication page e.g facebook is done from the frontend since your backend is an api.