Steam OAuth та Telegram OAuth з Casdoor: Додавання нестандартних соціальних входів через OIDC
Не існує "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 |
|---|---|---|---|---|
| Steam | OpenID 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; телефон із областю phone | Custom |
| X (Twitter) | OAuth 2.0 з авторизаційним кодом та PKCE | Ідентифікатор користувача X з /2/users/me | Не з стандартними областями Casdoor | Twitter |
| OAuth 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:
- Сторінка входу Casdoor формує запит
checkid_setupOpenID 2.0 доhttps://steamcommunity.com/openid/login, деopenid.realmвстановлено як origin Casdoor, аopenid.return_to— як сторінку/callbackCasdoor. - Коли Steam перенаправляє назад, Casdoor відправляє підписані поля назад до Steam з
openid.mode=check_authentication. Воно продовжує лише якщо Steam відповідаєis_valid:true. Також воно перевіряє, чиopenid.claimed_idвідповідає шаблонуsteamcommunity.com/openid/id/<digits>, і витягує з нього SteamID. - З ключем 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 againsthashusingSHA256(bot token)as the key; - відхиляє дані, якщо
auth_dateстарший за 24 години; - використовує числовий
idTelegram як ідентифікатор,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 демонструє повноцінний застосунок.
Посилання
- Steam Web API та OpenID: steamcommunity.com/dev
- Steamworks, автентифікація користувачів та перевірка власності: partner.steamgames.com/doc/features/auth
- Telegram, Вхід через Telegram (OpenID Connect): core.telegram.org/bots/telegram-login
- Telegram, Віджет входу (застарілий): core.telegram.org/widgets/login-legacy
- X, Потік авторизаційного коду OAuth 2.0 з PKCE: docs.x.com
- Meta, Довідка Graph API щодо користувача: developers.facebook.com/docs/graph-api/reference/user
- Вихідний код Casdoor:
idp/telegram.go,idp/goth.go,idp/custom.go