Документация разработчика
Интегрируйте единый вход через QQ ID в свое веб-приложение. Наша платформа полностью соответствует стандартам OAuth 2.1 и OpenID Connect (OIDC), делая авторизацию защищенной, современной и быстрой.
Введение
QQ ID реализует современную спецификацию OAuth 2.1. Это означает, что:
- PKCE (Proof Key for Code Exchange) обязателен для всех клиентов. В отличие от классического OAuth 2.0, здесь нельзя авторизоваться без отправки криптографического подтверждения.
- Не поддерживается небезопасный метод Implicit Grant (токен в хэше URL) и метод передачи паролей Resource Owner Password Credentials.
- Используется строгое совпадение зарегистрированных адресов перенаправления (redirect_uri).
1. Регистрация приложения
Перед началом работы вам необходимо зарегистрировать приложение в личном кабинете разработчика:
- Перейдите в Кабинет разработчика (требуется авторизация).
- Нажмите кнопку «Создать приложение».
- Укажите название вашего сервиса, домашнюю страницу и список разрешенных Redirect URIs (например, https://my-app.ru/callback).
- После создания скопируйте уникальный идентификатор client_id (начинается с app_).
2. Генерация параметров PKCE
PKCE защищает авторизационный код от перехвата. Вам необходимо сгенерировать два параметра:
- code_verifier — случайная криптографическая строка длиной от 43 до 128 символов (состоящая из букв, цифр, дефиса, точки, подчеркивания и тильды).
- code_challenge — закодированный в Base64Url хэш SHA-256 от строки code_verifier.
// 1. // 1. Генерация случайного code_verifier
function generateVerifier() {
const array = new Uint32Array(56);
window.crypto.getRandomValues(array);
return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join('');
}
// 2. // 2. Хеширование SHA-256 и Base64Url кодирование для code_challenge
async function generateChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const hash = await window.crypto.subtle.digest('SHA-256', data);
return btoa(String.fromCharCode(...new Uint8Array(hash)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
const verifier = generateVerifier();
const challenge = await generateChallenge(verifier);
console.log({ verifier, challenge });3. Запрос авторизации (Redirect)
Перенаправьте пользователя на страницу входа QQ ID. Вы должны составить URL со следующими query-параметрами:
- client_id — ID вашего приложения, полученный при регистрации.
- redirect_uri — адрес перенаправления на вашем сайте (должен точно совпадать с зарегистрированным).
- response_type — должен быть равен code.
- scope — запрашиваемые права доступа. Для OIDC обязателен openid. Дополнительно можно запросить profile и email.
- state — случайная уникальная строка для защиты от CSRF атак.
- code_challenge — challenge, сгенерированный на шаге 2.
- code_challenge_method — должен быть равен S256.
Пример авторизационной ссылки:
https://id.qqxx.ru/oauth/authorize?
client_id=app_82f1bc8f9b...&
redirect_uri=https://yoursite.ru/callback&
response_type=code&
scope=openid+profile+email&
state=YOUR_RANDOM_STATE&
code_challenge=CODE_CHALLENGE_HERE&
code_challenge_method=S256Описание параметров запроса
| Параметр | Обязателен | Описание |
|---|---|---|
| client_id | Да | client_id — ID вашего приложения, полученный при регистрации. |
| redirect_uri | Да | redirect_uri — адрес перенаправления на вашем сайте (должен точно совпадать с зарегистрированным). |
| response_type | Да | Всегда фиксирован: code. |
| scope | Да | Список запрашиваемых прав доступа через пробел (или знак +):• openid — признак OIDC авторизации• profile — доступ к имени, никнейму и аватару• email — доступ к адресу электронной почты• offline_access — если нужен refresh_token для работы в оффлайн режиме |
| state | Да | state — случайная уникальная строка для защиты от CSRF атак. |
| code_challenge | Да | code_challenge — challenge, сгенерированный на шаге 2. |
| code_challenge_method | Да | Всегда строго: S256. Использование plain запрещено. |
4. Обмен кода на токены (Token Exchange)
После успешной авторизации QQ ID перенаправит пользователя на ваш redirect_uri с параметрами code и state в URL (например, https://my-app.ru/callback?code=AUTH_CODE&state=RANDOM_STATE).
GET https://yoursite.ru/callback?code=AUTH_CODE_HERE&state=YOUR_RANDOM_STATEВаш бэкенд должен выполнить POST-запрос на обмен кода на токены. Запрос должен выполняться на бэкенде в целях безопасности:
POST /oauth/token HTTP/1.1
Host: id.qqxx.ru
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=AUTH_CODE_HERE&
client_id=YOUR_CLIENT_ID&
code_verifier=YOUR_ORIGINAL_CODE_VERIFIER&
redirect_uri=https://yoursite.ru/callbackПример успешного ответа сервера (JSON):
Ответ содержит access_token для запросов к API, id_token (подписанный JWT-токен OIDC с профилем пользователя) и refresh_token для обновления сессии.
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "rt_8a2d1f7c...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid profile email"
}5. Получение профиля (UserInfo)
Вы можете запросить информацию о пользователе, отправив GET-запрос с полученным access_token в заголовке Authorization:
GET /oauth/userinfo HTTP/1.1
Host: id.qqxx.ru
Authorization: Bearer ACCESS_TOKEN_HEREПример ответа UserInfo:
{
"sub": "2f40b2a8-8e6f-4fb6-a4c4-72a39281a8f6",
"email": "user@example.com",
"email_verified": true,
"name": "Иван Иванов",
"preferred_username": "ivan_dev",
"picture": "https://id.qqxx.ru/static/uploads/avatars/default.png",
"locale": "ru",
"updated_at": 1781415000
}6. Самостоятельная проверка подписи JWT (JWKS)
Вы можете не запрашивать UserInfo при каждом запросе, а проверять подпись id_token самостоятельно на своем сервере с помощью открытых ключей платформы.
Наши публичные ключи опубликованы по стандарту RFC 7517. Скачайте их и кэшируйте в своем приложении:
- Используйте стандартные библиотеки для JWT (например, go-jose, jwcrypto, node-jsonwebtoken).
- Получите массив ключей с JWKS-эндпоинта.
- Найдите ключ с kid (Key ID), совпадающим с kid в заголовке JWT.
- Проверьте подпись JWT по алгоритму RS256.
- Убедитесь, что срок действия (exp) не истек, а aud совпадает с вашим client_id.
7. Использование JavaScript SDK
Для максимально быстрой интеграции мы рекомендуем использовать наше готовое клиентское JS-решение, которое берет на себя всю логику генерации PKCE, перенаправлений и обработки токенов:
Подключение скрипта:
<!-- 1. Контейнер для кнопки входа -->
<div id="qqid-btn-container"></div>
<!-- 2. Инициализация SDK -->
<script type="module">
import { QQId } from 'https://id.qqxx.ru/sdk/qq-id.js';
const auth = new QQId({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'https://yoursite.ru/callback'
});
// Встраивание брендовой адаптивной кнопки входа
auth.renderButton('#qqid-btn-container', {
theme: 'dark', // 'dark' | 'light'
size: 'large', // 'small' | 'medium' | 'large'
width: 280
});
// Проверка сессии при загрузке страницы
const user = auth.getUser();
if (user) {
console.log('Пользователь уже авторизован:', user);
}
</script>Инициализация и запуск входа в одно касание:
<!-- На странице https://yoursite.ru/callback -->
<script type="module">
import { QQId } from 'https://id.qqxx.ru/sdk/qq-id.js';
const auth = new QQId({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'https://yoursite.ru/callback'
});
// Автоматически обрабатывает query параметры callback и выполняет обмен
auth.handleCallback()
.then((session) => {
console.log('Авторизация успешна!', session.user);
// Перенаправьте на дашборд
window.location.href = '/dashboard';
})
.catch((err) => {
console.error('Ошибка входа QQ ID:', err);
});
</script>