OAuth, Refresh Token и боевое тестирование

OAuth, Refresh Token и боевое тестирование

Гусинец Евгений

В первых двух частях мы разобрали основы и популярные механизмы (Session Token, JWT). Теперь переходим к продвинутому уровню: OAuth и Refresh Token – тем инструментам, которые делают авторизацию одновременно удобной для пользователя и головной болью для тестировщика

OAuth Access Token: когда вход через "чужих"

OAuth – это протокол, который позволяет приложению получить доступ к данным пользователя без передачи пароля. Классический пример: "Войти через Google", "Войти через GitHub".

Упрощенный flow (Authorization Code):

1.      Пользователь нажимает "Войти через Google".

2.     Приложение перенаправляет его на страницу Google.

3.     Google спрашивает: "Приложение X хочет доступ к вашему email. Разрешить?"

4.     Пользователь соглашается.

5.      Google редиректит обратно в приложение с authorization code.

6.     Приложение обменивает code на access token.

7.      Теперь приложение может делать запросы к Google API от имени пользователя.

Что проверять QA:

·        Redirect URI корректный и совпадает с зарегистрированным в OAuth-провайдере (иначе CORS errors).

·        После успешной авторизации приложение получает access token.

·        Access token дает доступ только к запрошенным scope (например, только email, но не календарь).

·        Токен истекает через заявленное время (обычно 1-2 часа).

·        При истечении API провайдера возвращает 401.

Типичные грабли:

·        CORS errors: redirect_uri не в whitelist у провайдера.

·        Invalid scope: запросили больше прав, чем разрешено.

·        Token revoked: пользователь отозвал доступ в настройках своего аккаунта Google/Facebook – токен перестает работать мгновенно.

Refresh Token: как не выкидывать пользователя каждые 15 минут

Access Token обычно живет недолго (15 минут – стандарт для безопасности). Но заставлять пользователя логиниться заново каждые 15 минут – плохая идея.

Решение: Refresh Token — долгоживущий токен (дни, недели), который используется только для получения нового access token. Он не светится в обычных API-запросах и хранится максимально безопасно (httpOnly cookie или secure storage).

Как это работает:

1.      При логине сервер выдает два токена: access_token (TTL: 15 мин) и refresh_token (TTL: 7 дней).

2.     Клиент работает с API через access_token.

3.     Когда access_token истекает, клиент отправляет refresh_token на специальный endpoint /auth/refresh.

4.     Сервер проверяет refresh token и выдает новый access_token (а иногда и новый refresh_token – это называется rotation).

5.      Клиент продолжает работать с новым access token.

Что проверять QA:

·        При логине выдаются оба токена.

·        Access token работает, пока не истек.

·        После истечения access token – 401.

·        Refresh token позволяет получить новый access token.

·        Старый refresh token инвалидируется после использования (rotation– защита от replay attacks).

·        Refresh token не работает после logout.

·        Refresh token не работает после смены пароля.

·        Нельзя использовать refresh token вместо access token для обычных API-запросов (должен вернуться 401/403).

Пример (упрощенно):

# Логин
POST /auth/login
{ "username": "user", "password": "pass" }
→ Response:
{
 "access_token": "eyJhbG...", // TTL: 15 мин
 "refresh_token": "dGhpc2lz...", // TTL: 7 дней
 "expires_in": 900
}
# Access token истек, обновляем
POST /auth/refresh
{ "refresh_token": "dGhpc2lz..." }
→ Response:
{
 "access_token": "eyJNEW...", // новый
 "refresh_token": "NEW_REFRESH", // новый (rotation)
 "expires_in": 900
}

Когда что использовать: шпаргалка для QA


Автоматизация: как не хардкодить токены в тестах

В Postman:

Используйте Pre-request Script для автоматического получения токена перед запросом:

// Pre-request Script в Collection

pm.sendRequest({

   url: 'https://api.example.com/login',

   method: 'POST',

   header: { 'Content-Type': 'application/json' },

   body: {

       mode: 'raw',

       raw: JSON.stringify({ username: 'user', password: 'pass' })

   }

}, function (err, response) {

   let token = response.json().access_token;

   pm.environment.set("authToken", token);

});

// В Authorization секции запроса:

// Type: Bearer Token

// Token: {{authToken}}

В автотестах (пример для RestAssured):

// Получаем токен

String token = given()

   .contentType("application/json")

   .body("{\"username\":\"user\", \"password\":\"pass\"}")

.when()

   .post("/auth/login")

.then()

   .statusCode(200)

   .extract().path("access_token");

// Используем в запросах

given()

   .header("Authorization", "Bearer " + token)

.when()

   .get("/api/profile")

.then()

   .statusCode(200);

Troubleshooting: Топ-4 проблемы и как их чинить

Проблема 1: "401 Unauthorized при валидном токене"

Причины:

·        Время на сервере/клиенте расходится → JWT поле exp считается истекшим.

·        Токен получен для другого окружения (dev токен на stage).

·        Токен передан неправильно (забыли "Bearer " или лишний пробел).

Как найти:

# Декодировать JWT и проверить exp

echo "eyJ1c2VyX2lkIjoxMjN9" | base64 -d

# Посмотреть на "exp" – это Unix timestamp

# Проверить текущее время сервера

date +%s

# Сравнить с curl verbose

curl -v -H "Authorization: Bearer <token>" https://api.example.com

Как решить:

·        Синхронизировать системное время (NTP).

·        Использовать правильные токены для окружения.

·        Проверить формат: строго Bearer <token> с одним пробелом.

Проблема 2: "Токен работает в Postman, но не в автотестах"

Причины:

·        В Postman используется переменная окружения, а в тестах – хардкод устаревшего токена.

·        Разные окружения (Postman на dev, тесты на stage).

·        Cookie не передаются автоматически в тестовом фреймворке.

Как решить:

·        В автотестах получать токен динамически перед каждым прогоном.

·        Использовать одинаковые конфиги окружения.

·        Если используете Session Cookie – явно управляйте Cookie Jar в тестах.

Проблема 3: "Intermittent failures токен истекает в середине теста"

Причины:

·        Тест долго выполняется (например, E2E), access token имеет короткий TTL (5-15 мин).

Как решить:

·        Использовать Refresh Token в тестах для обновления access token.

·        Получать новый токен перед каждым критичным шагом.

·        Для тестового окружения увеличить TTL (после согласования с командой).

Проблема 4: "CORS errors при OAuth flow"

Причины:

·        Redirect URI не совпадает с зарегистрированным в OAuth-провайдере.

·        Фронтенд пытается сделать запрос напрямую к провайдеру (нарушение CORS).

Как решить:

·        Проверить whitelist redirect URI в настройках OAuth-приложения.

·        OAuth flow должен идти через backend, а не с фронтенда напрямую.


Заключение

Теперь у вас есть полная карта токенов авторизации – от простого API Key до сложных OAuth-сценариев с rotation refresh token. Вы знаете, где искать баги, как автоматизировать проверки и что делать, когда всё сломалось.

Применяйте эти знания на практике. Ломайте системы правильно – так, чтобы находить проблемы до того, как их найдут пользователи.

___________________________________________________________________________
Автор: Евгений Гусинец Канал: QA❤️4Life Группа в ТГ: QA mistakes 
___________________________________________________________________________

Report Page