Документация разработчика
Интегрируйте единый вход через 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. Генерация случайного 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. Хеширование 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-параметрами:
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 | Да | Идентификатор вашего приложения, полученный при регистрации. |
| redirect_uri | Да | Адрес перенаправления. Должен точно совпадать с одним из зарегистрированных в панели. |
| response_type | Да | Всегда фиксирован: code. |
| scope | Да | Список запрашиваемых прав доступа через пробел (или знак +):• openid — признак OIDC авторизации• profile — доступ к имени, никнейму и аватару• email — доступ к адресу электронной почты• offline_access — если нужен refresh_token для работы в оффлайн режиме |
| state | Да | Случайная строка для защиты от CSRF. Проверяйте её равенство на своей стороне при callback. |
| code_challenge | Да | Строка PKCE challenge, сгенерированная на 2-м шаге. |
| code_challenge_method | Да | Всегда строго: S256. Использование plain запрещено. |
4. Обмен кода на токены
После успешного входа QQ ID перенаправит пользователя на указанный redirect_uri с параметрами code и state:
GET https://yoursite.ru/callback?code=AUTH_CODE_HERE&state=YOUR_RANDOM_STATEУбедитесь, что полученный state равен исходному значению. После этого отправьте POST-запрос с типом контента application/x-www-form-urlencoded на адрес https://id.qqxx.ru/oauth/token для обмена кода на токены.
code_verifier на клиенте.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": "eyJhbGciOiJSUzI1NiIs...",
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "rt_8a2d1f7c...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid profile email"
}5. Получение профиля пользователя
Для получения свежих персональных данных авторизованного пользователя выполните GET-запрос к endpoint https://id.qqxx.ru/oauth/userinfo, передав 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 (OIDC)
Токены id_token и access_token являются JWT-токенами, подписанными алгоритмом RS256 (асимметричный ключ RSA-2048). Вы можете проверить подпись токена без обращения к нашему серверу.
- Скачайте набор открытых ключей JWKS по адресу: https://id.qqxx.ru/.well-known/jwks.json
- Извлеките заголовок JWT токена и найдите идентификатор ключа (
kid). - Найдите соответствующий ключ в JWKS по полю
kid. - Проверьте подпись токена с помощью RSA-2048, используя параметры
n(modulus) иe(exponent). - Убедитесь, что поле
iss(issuer) строго равноhttps://id.qqxx.ru, токен не истек (exp) и полеaudсовпадает с вашимclient_id.
7. Интеграция с помощью JavaScript SDK
Если вы хотите реализовать вход на стороне фронтенда без сложной серверной разработки, вы можете использовать наш официальный JavaScript SDK.
Пример интеграции кнопки на HTML-странице
<!-- 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>Обработка callback на странице возврата
<!-- На странице 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>