Skip to content

Instantly share code, notes, and snippets.

@harshvladha
Last active April 20, 2016 16:34
Show Gist options
  • Save harshvladha/31ef0e09bb7619a0d6d0914ccc385abf to your computer and use it in GitHub Desktop.
Save harshvladha/31ef0e09bb7619a0d6d0914ccc385abf to your computer and use it in GitHub Desktop.
Simple "Facebook-Login" flow for django - without using any extra app (look last - settings.py file for details)
from django.http import HttpResponse
from django.views.generic import View
from django.views.generic.base import TemplateView, RedirectView
from {$APP_NAME}.models import UserProfile, OAuthProvider
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
import requests
BASE_URL = "http://straightmart.com/"
class FacebookLoginRedirect(RedirectView):
provider = None
permanent = False
query_string = True
response_type = 'code'
client_id = None
oauth_url = None
redirect_uri = BASE_URL + '/login/callback'
url = None
def get_redirect_url(self, *args, **kwargs):
self.provider = OAuthProvider.objects.filter(name='facebook')[0]
self.client_id = self.provider.app_id
self.oauth_url = self.provider.oauth_url
self.url = self.oauth_url+'?client_id='+self.client_id+'&redirect_uri='+self.redirect_uri
return super(FacebookLoginRedirect, self).get_redirect_url(*args, **kwargs)
class FacebookLoginCallback(RedirectView):
provider = None
permanent = False
query_string = False
code = None
fb_error = False
client_id = None
client_secret = None
access_token_url = None
debug_url = None
api_url = None
profile_url = None
user_access_token = None
request_uri = BASE_URL + '/login/callback'
url = BASE_URL + '/home'
fb_uid = None
def get_redirect_url(self, *args, **kwargs):
self.provider = OAuthProvider.objects.filter(name='facebook')[0]
self.client_id = self.provider.app_id
self.client_secret = self.provider.app_secret
self.access_token_url = self.provider.access_token_url
self.debug_url = self.provider.debug_token_url
self.api_url = self.provider.api_url
self.profile_url = self.provider.profile_url
if 'code' in self.request.GET:
self.code = self.request.GET.get('code')
elif 'error' in self.request.GET:
self.fb_error = True
if not self.fb_error:
self.get_user_access_token()
if self.inspect_access_token():
self.login_user()
return super(FacebookLoginCallback, self).get_redirect_url(*args, **kwargs)
def get_user_access_token(self):
params = dict(client_id=self.client_id, client_secret=self.client_secret, redirect_uri=self.request_uri, code=self.code)
r = requests.get(self.access_token_url, params=params)
data = r.json()
self.user_access_token = data['access_token']
def inspect_access_token(self):
admin = UserProfile.objects.filter(user_id=1)[0]
params = dict(input_token=self.user_access_token, access_token=admin.fb_access_token)
r = requests.get(self.debug_url, params=params)
data = r.json()
data = data['data']
if data['is_valid']:
self.fb_uid = data['user_id']
return data['is_valid']
def login_user(self):
user_profile = None
try:
# check if user already registered, then get that object
user_profile = UserProfile.objects.get(fb_uid=self.fb_uid)
except UserProfile.DoesNotExist:
# sign up the user over here
# check permissions granted in the access_token we've got
r_url = self.profile_url+'/permissions'
params = dict(access_token=self.user_access_token, client_id=self.provider.app_id, client_secret=self.provider.app_secret)
r = requests.get(r_url, params)
data = r.json()
data = data['data']
# create new params for getting user profile
params = dict(fields='first_name, last_name, email', access_token=self.user_access_token, client_id=self.provider.app_id, client_secret=self.provider.app_secret)
for p in data:
if p['permission'] == 'email' and p['status'] != 'granted':
params['fields'] = 'first_name, last_name'
break
# get user profile from facebook
r = requests.get(self.profile_url, params=params)
data = r.json()
# create new user in the database User Object
new_user = User(first_name=data['first_name'], last_name=data['last_name'])
if 'email' in data:
new_user.email = data['email']
new_user.username = data['email'].split('@')[0]
new_user.save()
# create UserProfile object in database
user_profile = UserProfile(user=new_user, fb_uid=self.fb_uid)
user_profile.save()
# get long lived access token when user is about to log in
params = dict(fb_exchange_token=self.user_access_token, grant_type='fb_exchange_token', client_id=self.provider.app_id, client_secret=self.provider.app_secret)
r = requests.get('https://graph.facebook.com/oauth/access_token', params=params)
data = r.content.decode('utf-8').split('=')[1]
data = data.split('&')[0]
self.user_access_token = data
user_profile.fb_access_token = self.user_access_token
user_profile.save()
user = user_profile.user
user = authenticate(username=user.username, type='oauth')
if user:
if user.is_active:
login(self.request, user)
class FacebookLoginLogout(RedirectView):
url = BASE_URL + '/index/'
permanent = False
def get_redirect_url(self, *args, **kwargs):
logout(self.request)
return super(FacebookLoginLogout, self).get_redirect_url(*args, **kwargs)
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
def _get_full_name(self):
return '%s %s' % (self.user.first_name, self.user.last_name)
full_name = property(_get_full_name)
location = models.ForeignKey(Location, null=True)
institute = models.ForeignKey(Institute, null=True)
fb_access_token = models.CharField(max_length=250, null=True, blank=True)
mobile = models.BigIntegerField(null=True,blank=True)
rating = models.SmallIntegerField(default=3)
verified = models.BooleanField(default=False)
date_of_birth = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True)
fb_uid = models.CharField(max_length=50, unique=True, blank=True, null=True)
def __str__(self):
return self.full_name
class OAuthProvider(models.Model):
name = models.CharField(max_length=20)
oauth_url = models.URLField()
access_token_url = models.URLField()
profile_url = models.URLField()
api_url = models.URLField()
debug_token_url = models.URLField()
app_id = models.CharField(max_length=50)
app_secret = models.CharField(max_length=100)
def __str__(self):
return self.name
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class PasswordlessAuthBackend(ModelBackend):
"""
Login to the system without providing a password
"""
def authenticate(self, username=None, **kwargs):
if kwargs['type'] == 'oauth':
try:
return User.objects.get(username=username)
except User.DoesNotExist:
return None
else:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
'''
This is a small section of settings.py
What should be your Project Structure be like (According to this model) :
You have a basic or say "main" django-app in which you need to implement Facebook Login.
../{$PROJECT_NAME}/settings.py
../{$APP_NAME}/oauth_backend.py
../{$APP_NAME}/models.py
Note : Replace every instance of $PROJECT_NAME and $APP_NAME with your django project name and django app name.
'''
AUTHENTICATION_BACKENDS = (
# Default backend
'django.contrib.auth.backends.ModelBackend',
'{$APP_NAME}.oauth_backend.PasswordlessAuthBackend'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment