# Авторизация
# Описание процесса авторизации
Авторизация в системе происходит с помощью протокола OAuth (opens new window).
TIP
В рамках данной статьи будет описана авторизация с помощью кода авторизации (authorization code flow). Этот способ подходит для серверных приложений.
Диаграмма из статьи про OAuth от DigitalOcean (opens new window)
- Пользователь переходит на веб-сайт, нажимает на кнопку "Войти". После нажатия на нее он переходит на страницу с формой для ввода логина и пароля.
- После ввода логина и пароля приложение авторизует пользователя, создается код авторизации.
- Авторизационный сервер переадресовывает пользователя обратно в приложение с кодом авторизации.
- Приложение запрашивает токен доступа с помощью кода авторизации.
- Токен доступа получен, можно производить запросы.
# Регистрация приложения
Для начала работы нужно зарегистрировать приложение в системе и получить 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
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"
}
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
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"
}
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
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)
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