Перейти к содержанию
DEVELOPERS

5. «Войти через QAIRU»: OAuth 2.0 и OpenID Connect

Вход студента, экран согласия, обмен кода на токены, обновление, выход и отзыв доступа.

Способ «Войти через QAIRU» позволяет внешней платформе получать сведения информационной системы от имени студента. Студент входит на странице входа QAIRU и подтверждает предоставление доступа на экране согласия, после чего приложение получает токены по протоколам OAuth 2.0 (поток Authorization Code с обязательным PKCE) и OpenID Connect.

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

В примерах раздела используются переменные, полученные на предыдущих шагах: code_verifier, state, nonce, access_token, refresh_token.

5.1. Порядок взаимодействия

  1. Приложение формирует параметры PKCE, state и nonce и сохраняет их в серверном сеансе пользователя.
  2. Приложение направляет браузер пользователя на адрес авторизации.
  3. Студент входит в учётную запись QAIRU и подтверждает доступ на экране согласия.
  4. Сервер авторизации возвращает браузер на адрес возврата с кодом авторизации.
  5. Сервер приложения обменивает код авторизации на токены.
  6. Приложение вызывает операции /os/v1/… с токеном доступа и обновляет его по refresh_token.

5.2. Адреса сервера авторизации

Адреса сервера авторизации публикуются в документе OpenID Connect Discovery. Адреса следует получать из этого документа, а не задавать в коде вручную.

URL
https://auth.bbx.kz/realms/qairu/.well-known/openid-configuration
JSON
{
  "issuer": "https://auth.bbx.kz/realms/qairu",
  "authorization_endpoint": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/auth",
  "token_endpoint": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/token",
  "userinfo_endpoint": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/userinfo",
  "end_session_endpoint": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/logout",
  "revocation_endpoint": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/revoke",
  "jwks_uri": "https://auth.bbx.kz/realms/qairu/protocol/openid-connect/certs",
  "code_challenge_methods_supported": ["plain", "S256"]
}

В ответе приведён фрагмент документа. Открытые ключи для проверки подписи токенов публикуются по адресу jwks_uri.

5.3. Параметры PKCE, state и nonce

Для каждого входа формируются новые значения:

  • code_verifier — случайная строка длиной от 43 до 128 символов из набора A–Z, a–z, 0–9, -, ., _, ~;
  • code_challenge — значение BASE64URL(SHA-256(code_verifier)) без завершающих символов =;
  • state — случайное значение для защиты от подделки межсайтовых запросов; сверяется при возврате;
  • nonce — случайное значение, которое возвращается в id_token и сверяется при его проверке.
# code_verifier: 86 characters of the base64url alphabet
CODE_VERIFIER=$(openssl rand -base64 64 | tr -d '\n=' | tr '+/' '-_' | cut -c1-86)

# code_challenge = BASE64URL(SHA-256(code_verifier))
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" \
  | openssl dgst -sha256 -binary | openssl base64 | tr -d '\n=' | tr '+/' '-_')

STATE=$(openssl rand -hex 16)
NONCE=$(openssl rand -hex 16)

Значения code_verifier, state и nonce хранятся в серверном сеансе пользователя до завершения обмена кода. Применяется только метод S256; метод plain не допускается.

5.4. Адрес авторизации

Браузер пользователя направляется на адрес authorization_endpoint со следующими параметрами:

Параметры адреса авторизации
ПАРАМЕТРОБЯЗАТЕЛЕНЗНАЧЕНИЕ
response_typeДаcode
client_idДаИдентификатор клиента, выданный при регистрации, например ext-campus-planner
redirect_uriДаАдрес возврата, совпадающий с зарегистрированным
scopeДаopenid и области доступа модулей через пробел, например openid qairu.scheduling.read
stateДаСлучайное значение, сохранённое в сеансе
nonceДаСлучайное значение, сохранённое в сеансе
code_challengeДаBASE64URL(SHA-256(code_verifier))
code_challenge_methodДаS256
ui_localesНетЯзык страницы входа и экрана согласия: ru, kk или en
https://auth.bbx.kz/realms/qairu/protocol/openid-connect/auth
  ?response_type=code
  &client_id=ext-campus-planner
  &redirect_uri=https%3A%2F%2Fplanner.example.com%2Foauth%2Fcallback
  &scope=openid%20qairu.academic.read%20qairu.scheduling.read
  &state=af0ifjsldkj
  &nonce=n-0S6_WzA2Mj
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
  &ui_locales=ru

5.5. Экран согласия

После входа студенту показывается экран согласия с наименованием приложения и перечнем запрошенных модулей. Студент разрешает или отклоняет доступ.

  • согласие сохраняется: при повторном входе с теми же областями доступа экран согласия не показывается;
  • при запросе новых областей доступа экран согласия показывается повторно;
  • области доступа модулей, не разрешённых приложению при регистрации, не предоставляются.

При разрешении доступа браузер возвращается на адрес возврата с кодом авторизации:

URL
https://planner.example.com/oauth/callback?state=af0ifjsldkj&session_state=3f0c9a52-6d1e-4b8a-9f3e-2c7b5d8e1a40&iss=https%3A%2F%2Fauth.bbx.kz%2Frealms%2Fqairu&code=7b2e1f0a-5c3d-4e8f-a1b2-c3d4e5f6a7b8.3f0c9a52-6d1e-4b8a-9f3e-2c7b5d8e1a40.ext-campus-planner

При отказе студента адрес возврата содержит код ошибки access_denied:

URL
https://planner.example.com/oauth/callback?error=access_denied&error_description=User+denied+consent&state=af0ifjsldkj

5.6. Обмен кода на токены

Сервер приложения направляет запрос POST на адрес token_endpoint в формате application/x-www-form-urlencoded. Клиент аутентифицируется идентификатором и секретом по схеме HTTP Basic; допускается также передача параметров client_id и client_secret в теле запроса.

curl -X POST https://auth.bbx.kz/realms/qairu/protocol/openid-connect/token \
  -u "ext-campus-planner:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=AUTHORIZATION_CODE \
  --data-urlencode redirect_uri=https://planner.example.com/oauth/callback \
  -d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
JSON
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 3600,
  "refresh_expires_in": 2592000,
  "refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "not-before-policy": 0,
  "session_state": "3f0c9a52-6d1e-4b8a-9f3e-2c7b5d8e1a40",
  "scope": "openid profile email qairu-student qairu.academic.read qairu.scheduling.read"
}

Поля ответа:

  • access_token — токен доступа для вызова API; действует 1 час (expires_in);
  • refresh_token — токен обновления; сеанс действует до 30 дней (refresh_expires_in);
  • id_token — токен OpenID Connect со сведениями о студенте;
  • scope — фактически предоставленные области доступа; перечень может не совпадать с запрошенным.

5.7. Вызов API от имени студента

Токен доступа передаётся в заголовке Authorization: Bearer <токен доступа>. Пути операций те же, что при авторизации токеном API; доступны операции методом GET модулей, области доступа которых предоставлены, а для модуля ALEM — операции, перечисленные в разделе «Модуль Alem».

curl https://api.bbx.kz/os/v1/me \
  -H "Authorization: Bearer ACCESS_TOKEN"

curl https://api.bbx.kz/os/v1/academic/catalog/disciplines \
  -H "Authorization: Bearer ACCESS_TOKEN"

Информационная система применяет права студента: ответ содержит только сведения, доступные студенту в кабинете. Запрос GET /os/v1/me с токеном доступа возвращает сведения о приложении, студенте и предоставленных модулях:

JSON
{
  "app": {
    "clientId": "ext-campus-planner",
    "name": "Campus Planner"
  },
  "user": {
    "sub": "8b6f1c2e-3a4d-4f5e-9a7b-1c2d3e4f5a6b",
    "name": "Aigerim Nurlanova",
    "email": "a.nurlanova@qairu.edu.kz",
    "studentId": "250142"
  },
  "modules": ["ACADEMIC", "SCHEDULING"],
  "expiresAt": "2026-10-28T09:00:00Z"
}

5.8. Обновление токена доступа

По истечении срока действия токена доступа запрос к API отклоняется с кодом 401 invalid_token. Новый токен доступа запрашивается по refresh_token без участия студента:

curl -X POST https://auth.bbx.kz/realms/qairu/protocol/openid-connect/token \
  -u "ext-campus-planner:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=refresh_token \
  -d refresh_token=REFRESH_TOKEN

Ответ имеет тот же состав, что и при обмене кода. Полученный refresh_token сохраняется вместо прежнего.

5.9. id_token и сведения о пользователе

Перед использованием id_token проверяются подпись по ключам jwks_uri, издатель iss, получатель aud (совпадает с client_id), срок exp и значение nonce. Содержимое id_token:

JSON
{
  "exp": 1793178000,
  "iat": 1793174400,
  "auth_time": 1793174388,
  "iss": "https://auth.bbx.kz/realms/qairu",
  "aud": "ext-campus-planner",
  "sub": "8b6f1c2e-3a4d-4f5e-9a7b-1c2d3e4f5a6b",
  "typ": "ID",
  "azp": "ext-campus-planner",
  "nonce": "n-0S6_WzA2Mj",
  "sid": "3f0c9a52-6d1e-4b8a-9f3e-2c7b5d8e1a40",
  "name": "Aigerim Nurlanova",
  "given_name": "Aigerim",
  "family_name": "Nurlanova",
  "preferred_username": "a.nurlanova",
  "email": "a.nurlanova@qairu.edu.kz",
  "email_verified": true,
  "student_id": "250142"
}
Сведения о пользователе
CLAIMЗНАЧЕНИЕ
subПостоянный идентификатор студента; применяется для связи с учётной записью во внешней платформе
name, given_name, family_nameПолное имя, имя и фамилия студента
preferred_usernameИмя пользователя в информационной системе
email, email_verifiedАдрес электронной почты и признак его подтверждения
student_idНомер студента; присутствует, если он указан в учётной записи

Те же сведения возвращает запрос к адресу userinfo_endpoint с токеном доступа:

curl https://auth.bbx.kz/realms/qairu/protocol/openid-connect/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
JSON
{
  "sub": "8b6f1c2e-3a4d-4f5e-9a7b-1c2d3e4f5a6b",
  "name": "Aigerim Nurlanova",
  "given_name": "Aigerim",
  "family_name": "Nurlanova",
  "preferred_username": "a.nurlanova",
  "email": "a.nurlanova@qairu.edu.kz",
  "email_verified": true,
  "student_id": "250142"
}

Адрес электронной почты и имя пользователя могут измениться. Для связи учётных записей применяется только sub.

5.10. Выход

Для выхода приложение удаляет сохранённые токены и отзывает токен обновления:

curl -X POST https://auth.bbx.kz/realms/qairu/protocol/openid-connect/revoke \
  -u "ext-campus-planner:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d token=REFRESH_TOKEN \
  -d token_type_hint=refresh_token

Для завершения сеанса QAIRU в браузере пользователь направляется на адрес end_session_endpoint. Параметр post_logout_redirect_uri допускается только для адреса, указанного при регистрации приложения.

URL
https://auth.bbx.kz/realms/qairu/protocol/openid-connect/logout
  ?client_id=ext-campus-planner
  &id_token_hint=ID_TOKEN
  &post_logout_redirect_uri=https%3A%2F%2Fplanner.example.com%2F

5.11. Отзыв доступа студентом

Студент отключает приложение в кабинете: раздел «Профиль», карточка «Подключённые приложения», действие «Отключить». После отключения:

  • выданные приложению токены доступа и обновления перестают действовать немедленно;
  • запросы к API с прежним токеном доступа отклоняются с кодом 401 token_revoked;
  • обновление токена завершается ошибкой invalid_grant;
  • при следующем входе студенту повторно показывается экран согласия.
JSON
{
  "error": {
    "type": "authentication_error",
    "code": "token_revoked",
    "message": "The student has revoked access for this application.",
    "request_id": "0d8e4c1a-7f2b-4a9e-b3c5-6e1d2f8a9b70"
  }
}

Администрация университета может отключить приложение полностью. В этом случае запросы отклоняются с кодом 403 app_disabled, а вход через приложение становится невозможным.

5.12. Сроки действия

Сроки действия
ОБЪЕКТСРОК
Код авторизацииНе более 1 минуты, однократное использование
Токен доступа access_token1 час
Сеанс и токен обновления refresh_token30 дней с момента входа; по истечении срока требуется повторный вход
Согласие студентаДо отзыва студентом или отключения приложения

5.13. Ошибки OAuth

Ошибки сервера авторизации возвращаются по протоколу OAuth 2.0: при авторизации — параметрами error и error_description адреса возврата, при выдаче токенов — телом ответа:

JSON
{
  "error": "invalid_grant",
  "error_description": "Code not valid"
}
Ошибки сервера авторизации
КОДГДЕ ВОЗВРАЩАЕТСЯЗНАЧЕНИЕРЕКОМЕНДУЕМОЕ ДЕЙСТВИЕ
access_deniedАдрес возвратаСтудент отклонил доступ на экране согласия.Сообщить пользователю, что вход не выполнен, и предложить повторить вход.
invalid_requestАдрес возврата; выдача токенов, HTTP 400Отсутствует обязательный параметр или указан недопустимый параметр, в том числе не передан code_challenge.Проверить параметры запроса.
invalid_scopeАдрес возвратаЗапрошена недопустимая область доступа.Указать openid и области доступа модулей, разрешённых приложению.
unauthorized_clientАдрес возврата; выдача токенов, HTTP 400Приложению не разрешён указанный способ получения кода или токена.Проверить значения response_type и grant_type.
temporarily_unavailableАдрес возвратаСервер авторизации временно недоступен.Повторить вход позднее.
server_errorАдрес возврата; выдача токеновВнутренняя ошибка сервера авторизации.Повторить запрос позднее.
invalid_clientВыдача токенов, HTTP 401Неверный идентификатор или секрет клиента либо приложение отключено.Проверить client_id и client_secret; после перевыпуска секрета использовать новый.
invalid_grantВыдача токенов, HTTP 400Код авторизации недействителен, истёк или уже использован; code_verifier или redirect_uri не совпадают с переданными при авторизации; токен обновления истёк или отозван.Повторить вход; при обновлении токена предложить студенту войти повторно.
unsupported_grant_typeВыдача токенов, HTTP 400Указан неподдерживаемый grant_type.Использовать authorization_code или refresh_token.

Коды ошибок API, связанные с токеном доступа студента, приведены в разделе «Коды ошибок».

5.14. Области доступа

Области доступа по умолчанию предоставляются приложению при каждом входе. Области доступа модулей указываются в параметре scope и предоставляются только для модулей, разрешённых приложению при регистрации.

Области доступа OAuth
ОБЛАСТЬ ДОСТУПАВИДНАЗНАЧЕНИЕ
openidПо умолчаниюОбязательна. Подтверждает вход по протоколу OpenID Connect и выдачу id_token.
profileПо умолчаниюИмя, фамилия и имя пользователя студента.
emailПо умолчаниюАдрес электронной почты и признак его подтверждения.
qairu-studentПо умолчаниюНомер студента student_id.
qairu.alem.readМодуль ALEMЯзыковые модели, эмбеддинги, ранжирование и распознавание речи платформы Alem.Cloud
qairu.users.readМодуль USERSУчётные записи и роли пользователей
qairu.files.readМодуль FILESФайлы информационной системы
qairu.learning.readМодуль LEARNINGОбучение: дисциплины, задания, оценки и компетенции
qairu.academic.readМодуль ACADEMICОбразовательные программы, учебные планы и каталог дисциплин
qairu.scheduling.readМодуль SCHEDULINGРасписание занятий
qairu.skillmatch.readМодуль SKILLMATCHСопоставление навыков и профессиональных требований
qairu.clubs.readМодуль CLUBSСтуденческие клубы и их мероприятия
qairu.projects.readМодуль PROJECTSСтуденческие и исследовательские проекты
qairu.ideas.readМодуль IDEASИдеи и обращения студентов