08.03.2018       Выпуск 220 (05.03.2018 - 11.03.2018)       Статьи

Регистрация и логин через фейсбук и джанго рест АПИ.

Без social-auth-core


Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Writing a client-server token-based facebook authentication with django rest framework

In this tutorial I’ll guide you through the basic implementation of login and registration from facebook in your app, that is used to interact with mobile and desktop devices. I am going to use python 3.6 and Django 2.0

Check out the repository for this tutorial if you want:

python3 -m venv ~/venvs/csa
source ~/venvs/csa/bin/activate
mkdir client-serv-auth
cd client-serv-auth
pip install django djangorestframework
django-admin startproject csa

Open project in the editor or IDE that you prefer, go to settings.py and add next lines to it:


'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',

FACEBOOK_APP_ID = 'your-app-id'
FACEBOOK_APP_SECRET = 'your-secret-app'

Everything up there should be pretty straightforward and self-explanatory, but to make sure we on the same wavelength.
We added a “rest_framework” and “rest_framework.authtoken” to our installed apps just how it says in documentation.

To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication, and additionally include rest_framework.authtoken in your INSTALLED_APPS setting

We’ve then setup default authentication schemes to use TokenAuthentication.
Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. 
“DEFAULT_RENDERER_CLASSES” is basically a set of renderers that may be used when returning a Responseobject.
And pagination just to make our results look better.
Then you’ll need to add a facebook secret and public keys. Create your app on https://developers.facebook.com, go to dashboard of your app and copy App ID and App Secret.

Okay, I think we finished with the settings for now. So let’s start with the fun part. Which is obviously coding. Since we want to make a possibility to login and registrateourusers we probably want to create a custom User model. By registering I mean, that whenever person log in with the facebook for the first time we want to create a user profile against our database and save all of the info there.

python manage.py startapp auth_fb

Write this to your auth_fb/models.py

Let’s review some of the code step by step. First, we are creating a User class that inherits from AbstractBaseUser and PermissionMixin. Because we use AbstractBaseUser we must provide some key implementation details like USERNAME_FIELDwhich in our case is ‘username’ field. This is going to be used as the unique identifier and must beunique=True. The other necessary field is REQUIRED_FIELDS.This a list of the field names that will be prompted for when creating a user with createsuperuser. Next, PermissionMixin is an abstract model that gives you all the methods and database fields necessary to support Django’s permission model. 
We want every user to have an automatically generated Token and can do this very easy by simply catching the User’s post_save signal. You can read more about it in docs.

Now we need to add this line to our settings. Basically this will override a default user model with one that we’ve created.

AUTH_USER_MODEL = "auth_fb.User"

I think this is a good point to run migrartions and create a super user just to be sure we are doing everything right.

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser

You can also register your User model in admin.py to check that everything works on the admin site.

from django.contrib import admin
from .models import User
class UserAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email', 'date_joined')
admin.site.register(User, UserAdmin)

If you followed every step on this tutorial and I didn’t forget anything everything should be good.
Now let’s create our views. Actually, we will have only one, but still.
And before we do this we will need to install facebook sdk package:

pip install facebook-sdk

Again step by step. We are using @csrf_exempt because our application on iOS or Android can’t have a csrf_token on a login. Usually csrf_token will be stored in cookies, but we don’t need to use cookies or sessions at all if our app is going to be used only through mobile devices.
Next, we are taking a data from request.data which is going to be json. We are asking to provide access_token from our mobile developers. This is basically what they got when you pressing a log in with facebook on a login page. For testing purpose you can always get one from facebook here. This is going to be your acces token, or you can create a test users for your application. Navigate to your applicaton on a facebook, go to roles and test users. 
Then we are collecting all of the info from facebook using facebook sdk by providing access token to it. Read the docs here.
If access token is correct, we have all of the info of a person, then we are trying to search if this person is already registered in our app, if that’s the case we are just going to return our token for this person to mobile developers. If the user does not exist, we are going to create one, using the info that we’ve collected from facebook. Remember post_save from earlier? This wil ensure that whenever a new user created we will have a token generated for them. Also we are catching exceptions with the wrong data to notify our mobile developers about a problem. The last two lines should never actually be executed, unless you are already had a users before you added post_save to models.

So what about this auth_token ? Now, because we’ve set up our default permissions to IsAuthenticated whenever user tries to access any page on our API map he will see 401 Unathorized, unless he will send to us auth_token .

But first things first. Let’s test that our login view works, since we don’t have anything else for now. Personally I am a huge fan of Postman app, that let you check your APIs very easy, but for convenience I am going to use cURL here.

Let’s create an endpoint for our login view. First, go to auth_fb/urls.py

from django.urls import path
from . import views
urlpatterns = [
path('login/', views.login_view, name='login'),

Now navigate to csa/urls.py

from django.contrib import admin
from django.urls import path, include
api_patterns = [
path('', include('auth_fb.urls')),

urlpatterns = [
path('admin/', admin.site.urls),
path('api/v0/', include(api_patterns)),

Run the server and then open terminal and type:

curl -X POST -d '{
"accessToken": "your-access-token here"

You should get a response like this:

{"auth_token": "your-auth-token", "new_user": true}

Okay, but what we are going to do with this response? Pretty easy, we will send it in the header for every request that requires authentication, which is all requests, except for login. Let’s create some dummy app for making a Posts to check that everything works. And add it to your INSTALLED_APPS

python manage.py createapp post

Write this to your post/models.py

from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)


from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'text', 'created')


from .models import Post
from .serializers import PostSerializer
from rest_framework import viewsets

class PostViewSet(viewsets.ModelViewSet):
model = Post
queryset = Post.objects.all()
serializer_class = PostSerializer


from .views import PostViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'', PostViewSet, base_name='post')
urlpatterns = router.urls

And this is going to be our final version of a csa/urls.py

from django.contrib import admin
from django.urls import path, include
api_patterns = [
path('post/', include('post.urls')),
path('', include('auth_fb.urls')),

urlpatterns = [
path('admin/', admin.site.urls),
path('api/v0/', include(api_patterns)),

Next, run migrations 
python manage.py makemigrations
python manage.py migrate

I’m not really going through this, because this is just a very basic things.
But now everything is in a place and we can properly test that everything works. First, let’s try to get or create a post without providing an authentication token.

curl -X GET
{"detail":"Authentication credentials were not provided."}

Exactly what we’ve expected. Now let’s create a post by providing an authentication token.

curl -X POST -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' -d '{
"title": "some title",
"text": "some text"

Congratulations! Note the way we are sending our Token “Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b” 
We need to put word Token after a colons than put a space and then our token. 
You can read more about it in docs.(as usual)

Thank you very much for reading it untill here, hope it was helpfull. Feel free to comment your suggestions or questions!

Лучшая Python рассылка

Нас поддерживает

Python Software Foundation

Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus