Перейти до основного вмісту

Steam OAuth та Telegram OAuth з Casdoor: Додавання нестандартних соціальних входів через OIDC

· Читання за 9 хв
Yang Luo
Casdoor Maintainer

Не існує "Steam OAuth": Steam автентифікує користувачів за допомогою OpenID 2.0 і надає вам 64-бітний SteamID, і більше нічого. Класичний Login Widget Telegram також не є OAuth: він передає вашій сторінці набір полів користувача плюс хеш HMAC-SHA256, який ви перевіряєте за допомогою токена бота. Зараз Telegram також запускає справжнього провайдера OpenID Connect за адресою oauth.telegram.org. Якщо ви поставите Casdoor між вашим додатком і цими провайдерами, Casdoor виконає специфічні для протоколу перевірки, а ваш додаток завжди спілкуватиметься з Casdoor лише через OpenID Connect, так само як це було б для Google або GitHub.

Провайдери на погляд​

ПровайдерПротоколЩо ідентифікує користувачаДоступна електронна пошта?Тип провайдера Casdoor
SteamOpenID 2.0 за адресою https://steamcommunity.com/openid/login, плюс Steam Web API для профілюSteamID64, взятий з заявленого ID https://steamcommunity.com/openid/id/<steamid>НіSteam
Telegram (Login Widget)Підписані дані віджета, HMAC-SHA256 з ключем SHA-256 токена ботаTelegram user idНіTelegram
Telegram (OpenID Connect)Потік авторизаційного коду OIDC з PKCE за адресою https://oauth.telegram.orgТвердження sub у ID-токеніНемає твердження email; телефон із областю phoneCustom
X (Twitter)OAuth 2.0 з авторизаційним кодом та PKCEІдентифікатор користувача X з /2/users/meНе з стандартними областями CasdoorTwitter
FacebookOAuth 2.0 з авторизаційним кодомІдентифікатор користувача в межах додаткаЛише якщо профіль має дійсну основну електронну адресуFacebook

Решта цього посту описує, що саме повертає кожен протокол і що з цим робить Casdoor.

Steam: OpenID 2.0, без OAuth​

Сторінки розробників Steam описують Steam як провайдера OpenID: ваш сайт надсилає користувача до Steam, а Steam повертає заявлений ID у форматі https://steamcommunity.com/openid/id/<steamid>. Число в кінці — це 64-бітний SteamID користувача. Немає авторизаційного коду, токена доступу, областей (scopes) та електронної пошти: ні відповідь OpenID, ні профіль через Web API її не містять.

Ось чому пошуки за запитом "steam oauth" не приводять до корисних результатів: протокол — це OpenID 2.0, попередник OpenID Connect, тому бібліотека клієнта OAuth 2.0 або OIDC не може безпосередньо взаємодіяти зі Steam.

Що робить Casdoor при вході через Steam:

  1. Сторінка входу Casdoor формує запит checkid_setup OpenID 2.0 до https://steamcommunity.com/openid/login, де openid.realm встановлено як origin Casdoor, а openid.return_to — як сторінку /callback Casdoor.
  2. Коли Steam перенаправляє назад, Casdoor відправляє підписані поля назад до Steam з openid.mode=check_authentication. Воно продовжує лише якщо Steam відповідає is_valid:true. Також воно перевіряє, чи openid.claimed_id відповідає шаблону steamcommunity.com/openid/id/<digits>, і витягує з нього SteamID.
  3. З ключем Steam Web API, який ви вводите як Client secret провайдера, Casdoor викликає ISteamUser/GetPlayerSummaries, щоб отримати ім'я гравця (persona name) та аватар.

Результатом створення користувача Casdoor є те, що його ім'я користувача відповідає SteamID64, відображуване ім'я — імені профілю в Steam, а аватар — зображенню з Steam. Поле email залишається порожнім. Casdoor навмисно ігнорує текст-заповнювач (placeholder), який підкладкова бібліотека розміщує там. Якщо вашому додатку потрібна електронна адреса, зберігайте її після реєстрації.

Налаштування займає дві хвилини: зареєструйте ключ Web API для вашого домену Casdoor на сторінці ключів Steam, створіть провайдера типу Steam і вставте ключ як client secret. Покрокові інструкції дивіться у посібнику з провайдера Steam.

Telegram: віджет входу та перевірка HMAC​

Класичний вхід через Telegram використовує JavaScript-віджет. Ви створюєте бота через @BotFather, прив'язуєте свій домен за допомогою команди /setdomain і вбудовуєте віджет. Коли користувач підтверджує вхід у Telegram, віджет або перенаправляє на URL, вказаний у data-auth-url, або викликає функцію JavaScript, передаючи id, first_name, last_name, username, photo_url, auth_date та hash.

Жоден елемент цих даних не є токеном. Будь-хто може ввести ці поля в URL, тому сервер повинен перевіряти hash. Документована перевірка Telegram працює так:

data_check_string = all received fields except hash,
as key=value, sorted by key, joined with "\n"
secret_key = SHA256(bot_token)
valid = hex(HMAC_SHA256(data_check_string, secret_key)) == hash

Telegram також рекомендує перевіряти auth_date, щоб уникнути повторного використання застарілих даних, але визначення допустимого періоду часу залишається за вами.

У Casdoor тип провайдера Telegram використовує ім'я користувача бота (без @) як Client ID, а токен бота — як Client secret. Коли користувач натискає кнопку Telegram, Casdoor відкриває власну сторінку /telegram-login, яка завантажує telegram-widget.js з telegram.org із вашим іменем користувача бота і встановлює data-auth-url на зворотний виклик Casdoor /callback. Зворотний виклик збирає поля, а потім бекенд Casdoor:

  • rebuilds the data-check string from every field except hash, sorts it, and compares the HMAC-SHA256 against hash using SHA256(bot token) as the key;
  • відхиляє дані, якщо auth_date старший за 24 години;
  • використовує числовий id Telegram як ідентифікатор, username як ім'я користувача, ім'я та прізвище як відображуване ім'я, а photo_url як аватар.

Імена користувачів Telegram є опціональними. Якщо у користувача немає імені, Casdoor генерує telegram_<id>, яке залишається незмінним при кожному вході. Віджет ніколи не надсилає електронну адресу чи номер телефону, тому користувач Casdoor, який увійшов лише через Telegram, не має ні того, ні іншого. Детальні кроки для BotFather описані у посібнику з провайдера Telegram.

Telegram тепер також пропонує OpenID Connect​

Сторінка "Log In With Telegram" від Telegram тепер документує стандартний потік OpenID Connect, а стара документація щодо iframe-віджета переміщена на архівну сторінку. Факти з документації Telegram:

  • Документ Discovery: https://oauth.telegram.org/.well-known/openid-configuration. Ендпоінт авторизації — https://oauth.telegram.org/auth, ендпоінт токенів — https://oauth.telegram.org/token, ключі доступні за адресою https://oauth.telegram.org/.well-known/jwks.json.
  • У @BotFather ви відкриваєте налаштування Login Widget свого бота, реєструєте дозволені URL-адреси (origins та точні redirect URIs) і отримуєте client ID та client secret.
  • Потік з authorization code, PKCE з S256 рекомендований. Запит на отримання токена використовує HTTP Basic authentication з client ID та secret.
  • Області доступу (scopes): openid є обов'язковим; profile додає ім'я, preferred_username та picture; phone додає phone_number за згодою користувача. Клейма email немає.
  • Ендпоінту UserInfo немає. Усі дані користувача містяться в ID токені, де iss дорівнює https://oauth.telegram.org, а aud — ID вашого бота.

Ви можете підключити цей потік за допомогою custom OAuth provider у Casdoor. Встановіть Auth URL та Token URL на зазначені вище ендпоінти, задайте Scope як openid profile (додайте phone, якщо потрібно), увімкніть Enable PKCE і залиште UserInfo URL порожнім. Зареєструйте https://<your-casdoor-host>/callback Casdoor як дозволену URL-адресу в BotFather. Оскільки UserInfo URL порожній, Casdoor отримує дані користувача з ID токена в відповіді з токенами: він вимагає наявності sub, відхиляє прострочений токен і перевіряє, чи містить aud client ID. Без налаштування маппінгу користувача sub стає ID користувача, preferred_username — іменем користувача, name — відображуваним ім'ям, picture — аватаром, а phone_number заповнює поле телефону. Сторінка входу Casdoor розпізнає custom provider, auth URL якого вказує на oauth.telegram.org, і скорочує параметр OAuth state для нього.

Зауважте, що користувач Telegram, який увійшов через віджет, і та сама особа, яка увійшла через OIDC, автоматично не вважаються одним і тим самим користувачем Casdoor. Ідентифікатор віджета — це числовий id, тоді як ідентифікатор OIDC — це sub, і приклади з документації Telegram показують різні значення для цих двох. Оберіть один метод для кожного додатку.

X (Twitter) та Facebook​

Це звичайний протокол OAuth 2.0, але кожен має нюанс, який варто знати.

X вимагає PKCE challenge в своєму authorize URL OAuth 2.0. Тип Twitter у Casdoor генерує новий code verifier для кожного входу, надсилає challenge S256 і передає verifier під час обміну на токен, тому нічого конфігурувати, окрім client ID та secret, не потрібно. Casdoor запитує scopes users.read tweet.read і зчитує дані користувача з /2/users/me, що надає ID користувача, handle та відображуване ім'я. Він не запитує поле email, тому будьте готові до того, що у користувачів X може не бути електронної пошти. Налаштування додатку описано у посібнику з провайдера Twitter.

Facebook повертає app-scoped user ID: одна й та сама людина має різні ID у різних додатках Facebook, тому перехід на новий додаток Facebook означає, що ваші користувачі не будуть відповідати своїм старим записам, якщо ви не пов'яжете їх за електронною адресою. Casdoor запитує email,public_profile і зчитує id, name, picture та email з Graph API. Facebook пропускає email, якщо у профілі немає дійсної адреси. Дивіться посібник з провайдера Facebook.

Як ваш додаток бачить усе це: чистий OIDC​

Ваш застосунок ніколи не взаємодіє безпосередньо зі Steam, Telegram, X чи Facebook. Він є OIDC-клієнтом Casdoor, налаштованим один раз з видавцем Casdoor: https://<your-casdoor-host>/.well-known/openid-configuration. Ви додаєте соціальних провайдерів до застосунку Casdoor на вкладці Providers, і їхні кнопки з'являються на сторінці входу Casdoor.

Після будь-якого з цих входів Casdoor знаходить або створює користувача Casdoor і завершує звичайний потік авторизації за кодом (authorization code flow) із вашим застосунком. ID-токен, який отримує ваш застосунок, підписаний Casdoor, а його sub — це ID користувача Casdoor, а не SteamID чи Telegram ID. Тому вашому застосунку не потрібна бібліотека OpenID 2.0, код HMAC, специфічні реалізації PKCE для кожного провайдера чи особлива обробка користувачів без електронної пошти. Оригінальний ID провайдера зберігається у профілі користувача Casdoor, наприклад, у полі steam або telegram, якщо він вам колись знадобиться.

Кілька речей, які варто врахувати:

  • Прив'язка акаунтів. Casdoor прив'язує соціальний вхід до існуючого користувача за верифікованою електронною поштою, верифікованим номером телефону або іменем користувача, відповідно до правил прив'язки, налаштованих у застосунку. Steam та віджет Telegram не надають ні електронну пошту, ні телефон, тому вони створюють окремого користувача, якщо тільки користувач не прив'яже провайдера з уже авторизованого акаунта. Дивіться як Casdoor прив'язує акаунти.
  • Додаткові поля профілю. Провайдери, які передають сирі дані, такі як тип Steam на базі Goth та кастомні провайдери, можуть заповнювати більше полів користувача через мапінг користувачів.
  • Клієнтська частина. Будь-яка стандартна бібліотека працює з Casdoor. У статті Підключення стандартного OIDC-клієнта перелічені кінцеві точки, а пост SSO на Spring Boot з OIDC демонструє повноцінний застосунок.

Посилання​