Перейти к содержимому
Документация · Любая библиотека OIDC

Быстрый старт: любая библиотека OIDC

Usher — стандартный провайдер OpenID Connect. Если для вашего языка есть сертифицированный клиент OIDC, у вас уже есть все необходимое: укажите ему документ обнаружения вашей среды и используйте поток кода авторизации с PKCE.

Настройки

ПараметрЗначение
Издательhttps://<handle>.usherid.com
URL обнаруженияhttps://<handle>.usherid.com/.well-known/openid-configuration
ПотокКод авторизации (response_type=code)
PKCEОбязателен, code_challenge_method=S256
Области доступаopenid profile email offline_access
Аутентификация клиентаКак указано в token_endpoint_auth_methods_supported

Поддомен вашей среды указан в Usher Console рядом с ее издателем. Среды разработки получают случайный поддомен, например wise-otter-42; у рабочих сред — тот, который выбрали вы. Рабочая среда может вместо этого находиться на вашем собственном домене, например login.acme.com: тогда он и становится ее издателем — после того как вы направите домен на Usher записью CNAME.

Прочитайте документ обнаружения

Здесь перечислены все конечные точки и ключи, которые нужны вашему клиенту. Пусть их считывает библиотека — не копируйте URL в код.

Терминал
curl -s https://acme.usherid.com/.well-known/openid-configuration | jq
Ответ (сокращенно)
{
  "issuer": "https://acme.usherid.com",
  "authorization_endpoint": "https://acme.usherid.com/api/auth/oauth2/authorize",
  "token_endpoint": "https://acme.usherid.com/api/auth/oauth2/token",
  "userinfo_endpoint": "https://acme.usherid.com/api/auth/oauth2/userinfo",
  "jwks_uri": "https://acme.usherid.com/api/auth/jwks",
  "introspection_endpoint": "https://acme.usherid.com/api/auth/oauth2/introspect",
  "revocation_endpoint": "https://acme.usherid.com/api/auth/oauth2/revoke",
  "end_session_endpoint": "https://acme.usherid.com/api/auth/oauth2/end-session",
  "scopes_supported": ["openid", "profile", "email", "offline_access"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
  "code_challenge_methods_supported": ["S256"]
}

Как проходит вход

Отправьте человека на конечную точку авторизации

Создайте случайный верификатор PKCE и сохраните его вместе со случайным state там, куда есть доступ только у сеанса этого браузера (хорошо подходит недолговечный cookie с флагом httpOnly). Затем выполните перенаправление с response_type=code, вашими client_id и redirect_uri, областями доступа выше, state и code_challenge вашего верификатора по методу S256.

Дайте человеку войти

Дальше работает Lobby: оно называет ваше приложение, предлагает способы входа, разрешенные в вашей среде, и в первый раз запрашивает согласие.

Проверьте возврат

Usher перенаправляет на ваш redirect_uri с code и state. Отклоните ответ, если state не совпадает с сохраненным. Код одноразовый и действует пять минут.

Обменяйте код на токены

Со своего сервера отправьте код и верификатор PKCE POST-запросом на конечную точку токенов:

Запрос токена
curl -s -X POST https://acme.usherid.com/api/auth/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri=https://app.acme.example/callback \
-d code_verifier="$CODE_VERIFIER"

Проверьте ID-токен

Проверьте его подпись по ключам из jwks_uri, а также что iss — это ваш издатель, aud — ваш ID клиента, а exp еще не наступил. Ваша библиотека делает это за вас; убедитесь, что проверка не отключена.

В Node.js

openid-client делает все описанное выше, включая проверку:

openid-client
import * as client from 'openid-client'

// discovery: every endpoint and key comes from the issuer
const config = await client.discovery(
  new URL('https://acme.usherid.com'),
  process.env.USHER_CLIENT_ID!,
  process.env.USHER_CLIENT_SECRET!,
)

// 1. send them to the Lobby, with PKCE (S256) and a state to check later
const codeVerifier = client.randomPKCECodeVerifier()
const state = client.randomState()
const url = client.buildAuthorizationUrl(config, {
  redirect_uri: 'https://app.acme.example/callback',
  scope: 'openid profile email offline_access',
  code_challenge: await client.calculatePKCECodeChallenge(codeVerifier),
  code_challenge_method: 'S256',
  state,
})
// keep codeVerifier and state in a short-lived httpOnly cookie, then redirect to url

// 2. back at /callback: swap the code for tokens
const tokens = await client.authorizationCodeGrant(config, new URL(request.url), {
  pkceCodeVerifier: codeVerifier,
  expectedState: state,
})
const { sub, email, name } = tokens.claims()!

В других языках

Все эти популярные библиотеки говорят на стандартном OpenID Connect и работают с Usher без каких-либо специальных доработок:

ЯзыкБиблиотека
PythonAuthlib
Gocoreos/go-oidc с golang.org/x/oauth2
JavaSpring Security OAuth 2.0 Client
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect
Rubyomniauth_openid_connect
PHPjumbojett/openid-connect-php

Сохранение входа

С областью offline_access ответ с токенами включает токен обновления. Используйте его с grant_type=refresh_token, чтобы получить новый токен доступа, когда старый истечет. Токены обновления меняются: при каждом использовании выдается новый, а старый перестает работать.

Выход

Сначала завершите собственный сеанс, затем перенаправьте человека на end_session_endpoint с post_logout_redirect_uri (и id_token_hint, если он у вас есть), чтобы Lobby тоже его забыло.