Code Flow
Authorization Code Flow с PKCE — основной сценарий входа пользователя через REGOS. Он подходит для сайта, мобильного приложения, SPA и серверного веб-приложения. Идея простая: пользователь входит на стороне REGOS, ваше приложение получает короткий одноразовый код, а затем меняет этот код на токены.
PKCE нужен для защиты кода авторизации. Даже если кто-то перехватит код возврата, он не сможет обменять его на токены без code_verifier, который остался у вашего приложения.

Что подготовить заранее
Перед началом интеграции получите client_id для вашего приложения и зарегистрируйте redirect_uri. Это адрес в вашем приложении, куда REGOS вернет пользователя после входа. Адрес должен совпадать с зарегистрированным значением полностью, включая протокол https, путь и завершающий слэш, если он есть.
Если ваше приложение является серверным и ему выдан client_secret, храните секрет только на сервере. Не вставляйте секрет в frontend, мобильное приложение, HTML-страницу или JavaScript.
Шаг 1. Подготовьте PKCE
Перед открытием страницы авторизации приложение создает случайную строку code_verifier. Из нее вычисляется code_challenge, который отправляется в REGOS. Для новых public-клиентов PKCE с методом S256 обязателен; для остальных клиентов также используйте S256. Обычный вход существующего клиента с RequirePkce=false допускается без PKCE для совместимости, но новые native-интеграции должны использовать PKCE. Если challenge передан, его проверка и проверка verifier обязательны. Временный вход всегда требует S256.
Обычно библиотека OAuth делает это автоматически. Если вы реализуете процесс вручную, используйте случайную строку длиной от 43 до 128 символов и вычислите:
code_challenge = BASE64URL(SHA256(code_verifier))
Шаг 2. Отправьте пользователя на авторизацию
Пользователь должен открыть адрес /oauth/authorize в браузере. Это не серверный запрос: пользователь увидит страницу входа REGOS, пройдет авторизацию и затем будет возвращен на ваш redirect_uri.
GET https://auth.regos.uz/oauth/authorize?response_type=code&client_id=your_client_id&redirect_uri=https%3A%2F%2Fyour.app%2Fcallback&scope=openid%20profile%20email&state=random_state&code_challenge=your_code_challenge&code_challenge_method=S256
Параметр state нужен для защиты от подмены ответа. Сохраните его до перехода на REGOS и после возврата проверьте, что значение не изменилось.
Если scope не передан, REGOS использует разрешения, которые настроены для клиента. Для OpenID Connect обычно нужен openid; для email добавьте email, для расширенного профиля — profile, для телефона — phone.
Шаг 3. Примите код авторизации
После успешного входа REGOS перенаправит пользователя на ваш redirect_uri. В адресе будут code и iss, а также state, если вы передавали его на первом шаге. Сравните iss с ожидаемым issuer и проверьте state до обмена кода.
https://your.app/callback?code=one_time_code&state=random_state&iss=https%3A%2F%2Fauth.regos.uz
Код авторизации короткоживущий и одноразовый. Не сохраняйте его надолго и не используйте повторно. Сразу обменяйте его на токены.
Шаг 4. Обменяйте код на токены
Запрос на обмен кода отправляется методом POST в формате application/x-www-form-urlencoded. Если вы использовали PKCE, обязательно передайте исходный code_verifier.
curl -X POST https://auth.regos.uz/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=one_time_code" \
-d "redirect_uri=https%3A%2F%2Fyour.app%2Fcallback" \
-d "client_id=your_client_id" \
-d "code_verifier=your_code_verifier"
Для confidential-клиента добавьте client_secret. Для публичного клиента секрет не используется.
Успешный ответ содержит токены. Значение expires_in показывает срок жизни access_token в секундах. Не задавайте это значение вручную в приложении: используйте то, что пришло в ответе.
{
"access_token": "opaque_access_token",
"token_type": "Bearer",
"id_token": "eyJ...id_token",
"expires_in": 600,
"refresh_token": "opaque_refresh_token",
"scope": "openid profile email"
}
Шаг 5. Используйте access token
access_token передается в API в заголовке Authorization.
Authorization: Bearer opaque_access_token
Если вам нужно получить данные профиля пользователя, вызовите /oauth/userinfo. Набор полей в ответе зависит от выданных scope.
Шаг 6. Обновите токен
Когда access_token истек, не отправляйте пользователя на повторный вход сразу. Если клиенту разрешены refresh tokens и такой токен был выдан, сначала попробуйте обновить доступ через него.
curl -X POST https://auth.regos.uz/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=opaque_refresh_token" \
-d "client_id=your_client_id"
Если ваш клиент confidential, добавьте client_secret. После успешного обновления сохраните новый access_token и новый refresh_token как одну операцию. Старый refresh token недействителен: его повторное использование отзывает всю цепочку. Не запускайте refresh параллельно. При invalid_grant нужен повторный вход.
Проверка id_token
id_token — это JWT, который подтверждает факт входа пользователя. Проверяйте подпись токена публичными ключами REGOS, issuer, audience и срок действия. Публичные ключи доступны через endpoint JWKS, а служебные адреса можно получить из OpenID configuration.
Для native-приложения допустим зарегистрированный custom scheme с точным совпадением адреса либо HTTP loopback 127.0.0.1 / [::1], где при authorize может отличаться только порт. При обмене кода URI должен точно совпасть с исходным запросом. Подробные правила приведены на странице authorize. Сроки access/refresh tokens зависят от настроек клиента и сервера; используйте фактический expires_in и правила ротации со страницы token.