Единый вход (SSO)
Как это работает
- Пока читатель авторизован на вашем сайте, ваш сервер подписывает короткоживущий токен, в котором сказано, кто он.
- Страница передаёт этот токен виджету комментариев в атрибуте
sso-token. - Crowment проверяет подпись и авторизует читателя в комментариях под этой личностью.
Токен подписывается секретом, который знают только ваш сервер и Crowment, поэтому никто не сможет войти от имени другого читателя. Единый вход доступен на всех тарифах.
1. Включите его
Откройте Site Console → ваш виджет → Single Sign-On. Менять настройки могут владельцы и администраторы.
Создайте секрет подписи
Это может сделать только владелец виджета. Секрет показывается один раз: сохраните его в переменных окружения сервера, например как CROWMENT_SSO_SECRET. Никогда не размещайте его в коде для браузера, в сборке приложения или в публичном репозитории.
Выберите режим
- Off: читатели входят только через Crowment.
- Optional: читатели, вошедшие на ваш сайт, авторизуются автоматически; вход через Crowment остаётся доступным.
- Required: войти могут только аккаунты вашего сайта. Существующие комментарии и сессии сохраняются.
Укажите страницы входа и выхода (необязательно)
Обе должны находиться на домене виджета. Кнопка входа в виджете отправляет читателей на вашу страницу входа с параметром return_to, в котором указана страница, откуда они пришли. Перед перенаправлением убедитесь, что return_to ведёт на ваш собственный сайт.
2. Подпишите токен на сервере
При каждом просмотре страницы авторизованным читателем подписывайте JWT алгоритмом HS256 своим секретом.
| Claim | Обязательно | Значение |
|---|---|---|
sub | да | ID пользователя на вашем сайте в виде строки, не длиннее 128 символов. Используйте ID, который никогда не меняется и не переиспользуется; адрес email — плохой выбор. |
name | да | Имя рядом с комментариями, до 100 символов. HTML удаляется. |
avatar | нет | URL изображения с https://. Всё остальное игнорируется. |
badges | нет | Ключи значков читателя, например ["vip"], совпадающие с SSO-ключами в разделе Badges. Если не передать, значки не меняются; [] снимает значки, выданные этим способом. Значки, выданные в панели, остаются. |
aud | да | App key вашего виджета — точно как в коде встраивания. |
iat, exp | да | Время выпуска и истечения в секундах. Токен живёт не дольше часа. Допускается расхождение часов в одну минуту. |
Claim email не нужен и не используется: Crowment никогда не сопоставляет аккаунты по email.
// npm install jsonwebtoken
import jwt from 'jsonwebtoken'
const ssoToken = jwt.sign(
{ sub: String(user.id), name: user.displayName, avatar: user.avatarUrl },
process.env.CROWMENT_SSO_SECRET,
{ algorithm: 'HS256', audience: CROWMENT_APP_KEY, expiresIn: '1h' },
)
// composer require firebase/php-jwt
use Firebase\JWT\JWT;
$now = time();
$ssoToken = JWT::encode([
'sub' => (string) $user->id,
'name' => $user->display_name,
'avatar' => $user->avatar_url,
'aud' => CROWMENT_APP_KEY,
'iat' => $now,
'exp' => $now + 3600,
], getenv('CROWMENT_SSO_SECRET'), 'HS256');
# pip install pyjwt
import os
from datetime import datetime, timedelta, timezone
import jwt
now = datetime.now(timezone.utc)
sso_token = jwt.encode(
{
"sub": str(user.id),
"name": user.display_name,
"avatar": user.avatar_url,
"aud": CROWMENT_APP_KEY,
"iat": now,
"exp": now + timedelta(hours=1),
},
os.environ["CROWMENT_SSO_SECRET"],
algorithm="HS256",
)
// go get github.com/golang-jwt/jwt/v5
now := time.Now()
ssoToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": strconv.FormatInt(user.ID, 10),
"name": user.DisplayName,
"avatar": user.AvatarURL,
"aud": crowmentAppKey,
"iat": now.Unix(),
"exp": now.Add(time.Hour).Unix(),
}).SignedString([]byte(os.Getenv("CROWMENT_SSO_SECRET")))
3. Передайте токен виджету
На страницах, которые рендерит сервер, поместите токен в код встраивания:
<script defer src="https://embeds.crowment.com/comments.js"></script>
<!-- signed in: pass the token your backend signed for this page view -->
<crow-comments app-key="YOUR_APP_KEY" sso-token="SIGNED_TOKEN"></crow-comments>
<!-- signed out: leave sso-token out -->
<crow-comments app-key="YOUR_APP_KEY"></crow-comments>
Передавайте токен на каждой странице, где читатель авторизован. Страница без токена сообщает виджету, что читатель вышел, и виджет выходит из комментариев тоже. Переходы по страницам не приводят к повторному входу каждый раз: виджет сохраняет сессию и обменивает новый токен только при смене читателя.
В одностраничном приложении добавляйте и удаляйте атрибут по мере изменения статуса входа и слушайте события виджета:
const widget = document.querySelector('crow-comments')
// after your site signs the reader in
widget.setAttribute('sso-token', await fetchCrowmentToken())
// after your site signs the reader out
widget.removeAttribute('sso-token')
// the token expired while the page was open: hand over a fresh one
widget.addEventListener('crow:sso-expired', async () => {
widget.setAttribute('sso-token', await fetchCrowmentToken())
})
// Required mode without a sign-in page: show your own login
widget.addEventListener('crow:login-required', () => openLoginDialog())
crow:sso-expired: виджету нужно было авторизовать читателя, но срок токена истёк. Передайте новый.crow:login-required: режим Required, страница входа не задана, и читатель нажал кнопку входа.
Читатели, вошедшие через ваш сайт, выходят тоже на вашем сайте. Если страница выхода не задана, виджет скрывает собственную кнопку выхода, ведь отсутствие токена на следующей странице и так завершит сессию.
4. Привязка аккаунтов
Читатель, у которого уже есть аккаунт Crowment, может привязать его в блоке комментариев с помощью значка ссылки рядом с аватаром. Он входит в Crowment во всплывающем окне и подтверждает действие на странице Crowment. После этого ваш сайт авторизует его под аккаунтом Crowment, а комментарии, написанные с аккаунтом вашего сайта, переходят к этому аккаунту.
Привязка позволяет вашему сайту авторизовать этого читателя под аккаунтом Crowment только на ваших страницах; страница подтверждения сообщает ему об этом. Отвязать аккаунт можно в любой момент в User Console в разделе Profile → Linked sites; комментарии остаются у читателя. Отключить привязку можно параметром Account linking в настройках SSO.
Имя и аватар из вашего токена обновляют профиль читателя в комментариях при каждом входе. Привязанные аккаунты Crowment сохраняют собственные имя и аватар.
Безопасность
- Храните секрет на сервере. Тот, у кого он есть, может авторизовать на вашем сайте кого угодно под любым именем.
- При утечке нажмите Replace secret. Токены, подписанные старым секретом, сразу перестают работать, поэтому немедленно разверните новый. Читатели, уже вошедшие в комментарии, остаются авторизованными.
- Подписывайте токены только для читателя текущего запроса и делайте их короткоживущими.
Устранение неполадок
| Симптом | Вероятная причина |
|---|---|
invalid_sso_token | Неверный или заменённый секрет, aud не совпадает с app key, алгоритм отличен от HS256, sub передан числом, пустое name или срок жизни больше часа. |
sso_token_expired | Время exp токена прошло или часы сервера сбиты. Подписывайте новый токен при каждом просмотре страницы. |
| SSO is not enabled for this app | Режим Off или секрет не создан. |
| Request origin does not match | Страница находится не на домене виджета и не на его поддомене. |