# Авторизация

# Описание процесса авторизации

Демонстрация авторизации

Схема процесса авторизации

Авторизация в системе происходит с помощью протокола OAuth (opens new window).

TIP

В рамках данной статьи будет описана авторизация с помощью кода авторизации (authorization code flow). Этот способ подходит для серверных приложений.

Диаграмма из статьи про OAuth от DigitalOcean (opens new window)

  1. Пользователь переходит на веб-сайт, нажимает на кнопку "Войти". После нажатия на нее он переходит на страницу с формой для ввода логина и пароля.
  2. После ввода логина и пароля приложение авторизует пользователя, создается код авторизации.
  3. Авторизационный сервер переадресовывает пользователя обратно в приложение с кодом авторизации.
  4. Приложение запрашивает токен доступа с помощью кода авторизации.
  5. Токен доступа получен, можно производить запросы.

# Регистрация приложения

Для начала работы нужно зарегистрировать приложение в системе и получить client_id и client_secret. Во время регистрации приложения нужно будет указать список адресов, на которые будет перебрасываться пользователь после завершения процесса авторизации.

# Отправка пользователя на сервер авторизации

Для начала веб-сайт должен перенаправить пользователя на сервер авторизации по следующей ссылке:

https://uenv-core.kpfu.ru/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL

  • CLIENT_ID - client_id приложения
  • CALLBACK_URL - адрес, на который пользователь будет возвращен после авторизации

У пользователя открывается форма входа, в которой он вводит логин и пароль. В случае успешной авторизации, пользователь переадресовывается на адрес, который был указан вместо CALLBACK_URL. К этому адресу добавляется параметр с кодом авторизации: ?code=AUTHORIZATION_CODE

# Запрос токена по коду авторизации

Для получения токена нужно взять GET-параметр code и сделать следующий запрос:

  • Метод: POST
  • URL: https://uenv-core.kpfu.ru/oauth/token/
  • Заголовок: Content-Type: application/x-www-form-urlencoded

Тело запроса:

client_id=CLIENT_ID
client_secret=CLIENT_SECRET
grant_type=authorization_code
code=CODE
redirect_uri=CALLBACK_URL
1
2
3
4
5
  • CLIENT_ID - client_id приложения
  • CLIENT_SECRET - client_secret приложения
  • CODE - код авторизации из GET-параметра
  • CALLBACK_URL - URL, на который переадресовывался пользователь ранее

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


 






{
    "access_token": "ACCESS_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "expires_in": 36000,
    "token_type": "Bearer",
    "scope": "read write"
}
1
2
3
4
5
6
7

В параметре expires_in содержится время в секундах, в течение которого токен будет активен. Для того, чтобы получить новый токен, нужно его обновить - об этом написано ниже.

Пример запроса на CURL:

curl -X POST https://uenv-core.kpfu.ru/oauth/token/ \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&redirect_uri=CALLBACK_URL'

# Получение профиля

Нужно выполнить GET-запрос с авторизационным заголовком, в котором будет находиться токен, полученный на предыдущем шаге:

  • Метод: GET
  • URL: https://uenv-core.kpfu.ru/api/v1.0/profile/
  • Заголовок: Authorization: Bearer ACCESS_TOKEN

В ответ придет JSON с профилем пользователя. Подробнее о его структуре можно прочесть в документации.

# Обновление токена

Для получения нового access token с помощью refresh token нужно выполнить запрос:

  • Метод: POST
  • URL: https://uenv-core.kpfu.ru/oauth/token/
  • Заголовок: Content-Type: application/x-www-form-urlencoded

Тело запроса:

grant_type=refresh_token
refresh_token=REFRESH_TOKEN
client_id=CLIENT_ID
client_secret=CLIENT_SECRET
1
2
3
4
  • CLIENT_ID - client_id приложения
  • CLIENT_SECRET - client_secret приложения
  • REFRESH_TOKEN - refresh_token полученный при запросе токена ранее

В ответ придет та же самая информация, как и при первом получении токена:


 






{
    "access_token": "ACCESS_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "expires_in": 36000,
    "token_type": "Bearer",
    "scope": "read write"
}
1
2
3
4
5
6
7

# Отзыв токена (выход)

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

  • Метод: POST
  • URL: https://uenv-core.kpfu.ru/oauth/revoke_token/
  • Заголовок: Content-Type: application/x-www-form-urlencoded

Тело запроса:

token=ACCESS_TOKEN
client_id=CLIENT_ID
client_secret=CLIENT_SECRET
1
2
3
  • CLIENT_ID - client_id приложения
  • CLIENT_SECRET - client_secret приложения
  • ACCESS_TOKEN - токен, полученный ранее

Если ответ пришел с 200 кодом, значит токен успешно отозван.

# Пример кода на Python

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

Пример использует фреймворк Django и библиотеку requests для выполнения запросов.

import requests
from django.conf import settings
from django.contrib.auth import login
from django.http import HttpRequest
from django.urls import reverse

from web.models import User  # импортируйте модель пользователя

# В настройках проекта (settings.py) должны быть следующие переменные:
# UNIENV_HOST - хост пользователя
# UNIENV_CLIENT_ID - client id для авторизации
# UNIENV_CLIENT_SECRET - сlient secret для авторизации

UNIENV_HOST = "https://uenv-core.kpfu.ru"


def _get_redirect_uri(request):
    """
    Внутренняя функция для генерации ссылки на Callback URL.
    В вашем проекте должен быть url с названием unienv-auth-callback, 
    который будет отвечать за завершение авторизации.
    """
    return request.build_absolute_uri(reverse("unienv-auth-callback"))


def get_authorization_start_url(request: HttpRequest) -> str:
    """
    1. В вашем проекте должна быть страница, которая переадресует пользователя для начала авторизации.
    Адрес для переадресации сгенерирует эта функция.
    """
    return (
        f"{settings.UNIENV_HOST}/oauth/authorize/?"
        f"response_type=code&"
        f"client_id={settings.UNIENV_CLIENT_ID}&"
        f"redirect_uri={_get_redirect_uri(request)}"
    )


def get_token(request: HttpRequest, code: str) -> str:
    """
    2. После того, как пользователь вернется с кодом авторизации на callback url,
    нужно получить токен с помощью этой функции.
    """
    response = requests.post(
        f"{settings.UNIENV_HOST}/oauth/token/",
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        data={
            "client_id": settings.UNIENV_CLIENT_ID,
            "client_secret": settings.UNIENV_CLIENT_SECRET,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": _get_redirect_uri(request),
        },
    )
    response.raise_for_status()
    response_data = response.json()
    return response_data["access_token"]


def get_profile(token: str) -> dict:
    """
    3. Вместе с токеном запросите профиль
    """
    response = requests.get(f"{settings.UNIENV_HOST}/api/v1.0/profile/", headers={"Authorization": f"Bearer {token}"})
    response.raise_for_status()
    return response.json()


def login_with_unienv_user_profile(request: HttpRequest, unienv_user_profile: dict):
    """
    4. Если с пользовательскими данными все хорошо, 
    вы можете авторизовать пользователя на сайте на базе его данных
    """
    email = unienv_user_profile["email"]
    user, _ = User.objects.get_or_create(email=email)
    login(request, user)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76