Схема целиком#
- Мы выдаём
client_idиclient_secret— один раз, при подключении. - Интеграция меняет их на токен через
POST /auth/token. - С токеном ходит час, передавая его в заголовке
Authorization. - Через час просто повторяет шаг 2.
Это client_credentials в чистом виде: пользователь в браузер не ходит, согласий не даёт,
редиректов нет.
Получение токена#
curl -X POST https://api.rentu.ru/api/external/v2/auth/token \
-H 'Content-Type: application/json' \
-d '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET"}'{
"success": true,
"access_token": "eyJhbGciOiJIUzUxMiJ9...",
"token_type": "Bearer",
"expires_in": 3600
}| Поле | Тип | Значение |
|---|---|---|
access_token | string | JWT, подписанный HS512 |
token_type | string | всегда Bearer |
expires_in | integer | всегда 3600 — секунд до истечения |
Ответ на неудачную попытку одинаков во всех случаях: неизвестный client_id, неверный секрет и отключённый ключ дают ровно одно 401 unauthorized. Так задумано: по ответу нельзя перебором выяснить, какие client_id существуют.
Использование токена#
curl https://api.rentu.ru/api/external/v2/shopping_centers \
-H 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9...'Заголовок разбирается строго: слово Bearer, ровно один пробел, токен. Передать токен
query-параметром или другим заголовком нельзя.
Что внутри токена#
| Поле | Значение |
|---|---|
| алгоритм | HS512 |
aud | external-v2 — проверяется при разборе |
sub | client_id интеграции |
exp | iat + 3600 |
Токен подписывается симметричным секретом на нашей стороне, проверять его самостоятельно
не нужно. Полезно знать только exp: по нему удобно обновлять токен заранее, не дожидаясь
401.
Когда токен перестаёт работать#
| Ситуация | Ответ | Что делать |
|---|---|---|
| Истёк час | 401 token_expired | Получить новый токен и повторить запрос |
Токен испорчен, чужой, не тот aud | 401 unauthorized | Проверить, что токен получен именно в v2 |
| Ключ отключён с нашей стороны | 401 unauthorized | Связаться с нами |
| Секрет ротирован | 401 при обмене | Использовать новый секрет |
Отдельный код token_expired нужен, чтобы можно было отличить «пора обновить токен»
(повторить имеет смысл) от «учётные данные неверны» (повторять бессмысленно).
Запрашивать токен на каждый запрос не нужно. Его стоит держать в памяти процесса и обновлять по exp либо по первому token_expired. Выдача токенов ограничена десятью попытками в минуту с одного IP.
Отзыв и ротация#
Секрет показывается один раз, в момент выдачи. В открытом виде мы его не храним и восстановить не можем: если потеряли, придётся выпустить новый.
- Ротация секрета.
client_idостаётся прежним, старый секрет перестаёт работать немедленно. Перенастраивать идентификатор интеграции не нужно. - Отключение ключа действует мгновенно: ключ читается из базы на каждом запросе, кэша нет.
Оба действия сейчас выполняются на нашей стороне: достаточно написать менеджеру.
Несовместимость с v1#
Версии подписываются разными секретами и аутентифицируются разными заголовками:
v1 читает api-token, v2 читает Authorization: Bearer. Токен одной версии в другой
даёт 401. Это изоляция, а не ограничение: ротация или утечка секрета одной версии
не затрагивает вторую.