Войти

Документация разработчика

Интегрируйте единый вход через 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).
⚠️ Важное примечание: Базовый домен для API запросов и OIDC авторизации — https://id.qqxx.ru. Все ссылки интеграции должны вести на этот домен.

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

Перед началом работы вам необходимо зарегистрировать приложение в личном кабинете разработчика:

  1. Перейдите в Кабинет разработчика (требуется авторизация).
  2. Нажмите кнопку «Создать приложение».
  3. Укажите название вашего сервиса, домашнюю страницу и список разрешенных Redirect URIs (например, https://my-app.ru/callback).
  4. После создания скопируйте уникальный идентификатор client_id (начинается с app_).

2. Генерация параметров PKCE

PKCE защищает авторизационный код от перехвата. Вам необходимо сгенерировать два параметра:

  • code_verifier — случайная криптографическая строка длиной от 43 до 128 символов (состоящая из букв, цифр, дефиса, точки, подчеркивания и тильды).
  • code_challenge — закодированный в Base64Url хэш SHA-256 от строки code_verifier.
js
// 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.

Пример авторизационной ссылки:

http
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).

http
GET https://yoursite.ru/callback?code=AUTH_CODE_HERE&state=YOUR_RANDOM_STATE

Ваш бэкенд должен выполнить POST-запрос на обмен кода на токены. Запрос должен выполняться на бэкенде в целях безопасности:

🔒 Параметры тела запроса: code_verifier — оригинальная строка verifier, сгенерированная на шаге 2.
http
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 для обновления сессии.

json
{
  "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:

http
GET /oauth/userinfo HTTP/1.1
Host: id.qqxx.ru
Authorization: Bearer ACCESS_TOKEN_HERE

Пример ответа UserInfo:

json
{
  "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. Скачайте их и кэшируйте в своем приложении:

  1. Используйте стандартные библиотеки для JWT (например, go-jose, jwcrypto, node-jsonwebtoken).
  2. Получите массив ключей с JWKS-эндпоинта.
  3. Найдите ключ с kid (Key ID), совпадающим с kid в заголовке JWT.
  4. Проверьте подпись JWT по алгоритму RS256.
  5. Убедитесь, что срок действия (exp) не истек, а aud совпадает с вашим client_id.

7. Использование JavaScript SDK

Для максимально быстрой интеграции мы рекомендуем использовать наше готовое клиентское JS-решение, которое берет на себя всю логику генерации PKCE, перенаправлений и обработки токенов:

Подключение скрипта:

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>

Инициализация и запуск входа в одно касание:

html
<!-- На странице 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>