Аутентификация OAuth в Django с помощью social-auth

В ходе разработки моего последнего проекта django мне нужно было обеспечить аутентификацию пользователей с помощью аккаунтов Google. Для этого я использовал библиотеку social-app-django, которая реализует механизм аутентификации/регистрации, поддерживающий несколько провайдеров и протоколов, таких как OAuth (версии 1 и 2) или OpenId.

Краткий обзор OAuth

Для обеспечения аутентификации пользователей Google поддерживает несколько протоколов, включая OAuth 2. OAuth - это открытый протокол, который обеспечивает безопасную авторизацию для веб-приложений, мобильных и настольных приложений простым и стандартным способом. Протокол полагается на доверенную третью сторону для организации процесса аутентификации. Он предоставляет клиенту доступ к ресурсу, делегируя процесс авторизации внешнему серверу авторизации с одобрения владельца ресурса.

На этой схеме вы можете увидеть, как это работает:

Полное руководство по использованию этого протокола для доступа к API Google доступно здесь.

В этом посте мы построим простое приложение для блога, использующее протокол OAuth для обеспечения аутентификации пользователей с помощью учетных записей Google.

Поехали!

1. Установка библиотеки

В качестве первого шага мы должны установить и включить библиотеку social-auth-app-django в нашем проекте django. Мы можем установить эту библиотеку с помощью pip или pipenv в соответствии с нашим окружением/личными предпочтениями. Советуем ознакомиться с современным удобным способом управлением версиями Python и окружениями.

Если мы выбираем pip:

pip install social-auth-app-django

или если мы используем pipenv:

pipenv install social-auth-app-django

После установки библиотеки мы должны добавить приложение в список INSTALLED_APPS в файле настроек проекта, используя идентификатор social_django:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'social_django',
]

2. Добавление бэкенда аутентификации Google OAuth2

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

AUTHENTICATION_BACKENDS = (
    'social_core.backends.google.GoogleOAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

3. Настройка API аутентификации Google

После добавления бэкенда мы должны настроить его для использования в приложении. Для этого переходим в консоль Google Developers Console и в левом меню переходим в раздел Credentials. Появится диалог для выбора или создания проекта. На данный момент у нас все еще нет никакого проекта, поэтому мы выберем второй вариант, чтобы создать его.

Теперь нам нужно выполнить следующие задачи:

  1. Дайте проекту описательное имя. Это поможет нам сохранить порядок при управлении несколькими приложениями.
  2. Создайте учетные данные, выбрав OAuth client ID в меню Create Credentials.
  3. Выберите Web-приложение и заполните необходимые данные. URI авторизованного перенаправления используются бэкендом аутентификации Google для перенаправления пользователей на приложение после прохождения аутентификации.
  4. Нажмите на кнопку Create и будут сгенерированы ключ и секрет. Эти параметры понадобятся нам на следующем шаге.

Google включает аутентификацию с помощью OAuth 2 через свой Google + API, поэтому нам необходимо включить ее. Перейдите в раздел APIs & Services и нажмите на кнопку Enable APIs and Services. Затем найдите API Google+ и включите его.

4. Конфигурирование проекта в бэкенде

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

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'INSERT_PROVIDED_KEY_HERE'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'INSERT_PROVIDED_SECRET_HERE'

Нам также необходимо добавить ключи LOGIN_URL, LOGIN_REDIRECT_URL и LOGOUT_REDIRECT_URL в конфигурационный файл. Библиотека social-app-django использует ключ LOGIN_URL для перенаправления пользователя на страницу аутентификации Google. LOGIN_REDIRECT_URL и LOGOUT_REDIRECT_URL задают URL, на которые будет перенаправлен пользователь после событий входа и выхода.

LOGIN_URL = '/auth/login/google-oauth2/'

LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'

Для завершения процесса настройки нам нужно добавить несколько маршрутов:

from django.conf import settings
from django.contrib.auth.views import logout

urlpatterns = [
  ...,
  path('', include('social_django.urls', namespace='social')),
  path('logout/', logout, {'next_page': settings.LOGOUT_REDIRECT_URL},
    name='logout'),
  ...,
]

Нам также необходимо добавить следующий ключ в файл настроек:

SOCIAL_AUTH_URL_NAMESPACE = 'social'

На этом этапе конфигурация должна быть готова. Теперь пришло время поместить некоторую логику в представления и шаблоны!

5. Добавление логики в представлениях и шаблонах

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

from django.shortcuts import render
from .models import Post


def index(request):
    context = {
        'posts': Post.objects.order_by('-date')
        if request.user.is_authenticated else []
    }

    return render(request, 'blog/index.html', context)

Как видите, представление отправляет список постов в шаблон только тогда, когда пользователь аутентифицирован.

В шаблоне мы размещаем код для отображения постов и ссылку для выхода, но если пользователь не аутентифицирован, мы показываем ссылку для входа.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>My fake blog!</title>

  <link
    rel="stylesheet"
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
    integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4"
    crossorigin="anonymous">
</head>
<body>
  <div class="jumbotron">
    <h1>My fake blog!</h1>
    {% if user.is_authenticated %}
      <p>Logged as {{ user.username }}</p>
      <a class="btn btn-primary" href="{% url 'logout' %}">Logout</a>
    {% else %}
      <a class="btn btn-primary" href="{% url 'social:begin' 'google-oauth2' %}">
        Login
      </a>
    {% endif %}
  </div>

  <div class="container-fluid">
  {% for post in posts %}
    <div>
      <h2>{{ post.title }}</h2>
      <p>{{ post.content }}</p>
      <p>Posted by {{ post.user.username }} | {{ post.date }}</p>
    </div>
  {% endfor %}
  </div>
</body>
</html>

Когда пользователь заходит на наш блог без аутентификации, страница выглядит следующим образом:

Когда пользователь нажимает на ссылку входа и выполняет процесс аутентификации, отображается список постов, и страница выглядит следующим образом:

Выводы

В этом посте мы рассмотрели, как библиотека social-app-django позволяет простым способом реализовать аутентификацию OAuth в наших django проектах. В примере приложения для блога мы использовали библиотеку для добавления поддержки использования учетных записей Google для аутентификации пользователей приложения. Аналогично, мы могли бы использовать другие бэкенды для добавления аутентификации с помощью twitter, github, facebook и т.д.

Наконец, я хотел бы подчеркнуть, что эта библиотека также работает с различными python frameworks, позволяя нам реализовать аутентификацию так же легко, как мы это сделали с django.

Вернуться на верх