Придумать конечную точку sign_in возвращает неправильно сформированный сеанс приготовления ie при первом вызове, но работает нормально при двух последовательных вызовах sign_in - PullRequest
3 голосов
/ 20 апреля 2020

ОК. У нас есть приложение, которое отлично работает. Несколько недель go (теперь бывший) сотрудник сделал довольно масштабное изменение, которое, казалось, вызвало довольно специфическую ошибку, и я пытаюсь выяснить, что является реальной проблемой, и, конечно, решить ее.

Короче говоря, вот сценарий, который терпит неудачу:

POST Войти и получить информацию о пользователе

В приложении мы используем devise (я полагаю, 4.6.2) для аутентификации пользователей и CanCanCan для авторизации ресурсов и Ahoy для отслеживания определенных типов пользователей (в данном случае администраторов).

У нас есть два соответствующих маршрута для сбоя, с которым мы сталкиваемся:

  1. /users/sign_in <- это маршрут разработки </li>
  2. GET /user <- это маршрут, который возвращает некоторую соответствующую информацию о текущем пользователе, включая роль пользователя и <strong>токен JWT , который они могут использовать для выполнять вызовы API

Конечная точка GET /user определяется внутри контроллера: UsersController < V2::ApplicationController, контроллер приложения имеет несколько хуков, соответствующий: before_action :authenticate_user!, :update_current_session, где update_current_session похоже это:

def current_session
    return unless current_user
    @current_session ||= current_user.sessions.find_by_session_id(cookies.signed[:_session_id])
end

def update_current_session
    return unless current_session
    current_session.accessed!(request)
end

Итак, насколько я понимаю, authenticate_user! использует devise и затем вызывает функцию update_current_session.

Happy Flow - Как все работало раньше:

Мы есть несколько внутренних тестов / скриптов, которым нужен токен, который возвращает /user, потому что они выполняют вызовы API для нашего приложения. Таким образом, они сделали следующее:

  1. Выполните вызов POST для /users/sign_in с телом, которое выглядит как
{
    "user": {
            "email": "email@email.com",
            "password": "whatever"
    }
}
Получить ответ 200 OK с телом success: "true". Устанавливает некоторые файлы cookie (ответ имеет несколько Set-Cookie заголовков:
Set-Cookie: ahoy_visit=[REDACTED]; path=/; expires=Mon, 20 Apr 2020 13:34:21 GMT; HttpOnly
Set-Cookie: _session_id=[REDACTED]; path=/; expires=Mon, 20 Apr 2020 10:34:21 GMT; HttpOnly
Set-Cookie: st_session=[REDACTED]; path=/; expires=Wed, 20 May 2020 09:34:21 GMT; HttpOnly
Set-Cookie: _safe_cookies__known_cookies=ahoy_visitor%7Cahoy_visit%7C_session_id%7Cst_session; path=/; expires=Thu, 18 Apr 2030 09:34:21 GMT; HttpOnly
Вызовите GET /user с заголовком Cookie, который является просто всеми этими параметрами Set-Cook ie вместе (или только несколькими Cookie заголовками, оба работают Получите ответ 200 OK с соответствующий орган.

В заключение:

  1. POST sign_in - получить набор куки
  2. Позвонить GET / пользователю с куки
  3. Успех

Сбои после изменения

С тех пор, как бывшие сотрудники меняют соответствующий поток действий, описанный выше, терпит неудачу. Текущая ситуация такова:

  1. POST sign_in - получить набор файлов cookie
  2. Позвонить GET / пользователю с файлами cookie
  3. Получить 401 Несанкционированный

После попытки выяснить, что не так (в основном через Postman и некоторые скрипты), я заметил кое-что довольно странное:

При первом вызове POST /users/sign_in st_session cook ie кажется * на 1087 * короче , чем было раньше. Если мы дважды вызываем POST /users/sign_in, то поток работает:

  1. POST sign_in - получить набор файлов cookie (кажется, что st_session искажен или что-то отсутствует)
  2. POST sign_in снова - получить набор файлов cookie (теперь st_session выглядит нормально)
  3. Позвонить GET / пользователю с файлами cookie
  4. Работает - получает правильный ответ от сервера

Кажется, st_session из-за конфигурации внутри session_store.rb:

Rails.application.config.session_store :cookie_store, key: 'st_session', expire_after: (Rails.env.production? ? 1.hour : 1.month), secure: Rails.env.production?

Сводка

До изменения работал следующий поток ОК:

  1. POST sign_in - получить набор файлов cookie
  2. Вызов GET / пользователя с печеньем
  3. Успех

После изменения поток завершается с 401:

  1. POST sign_in - получить набор печенья
  2. Позвонить GET / пользователю с файлами cookie
  3. Получить 401 Несанкционированный

Вызов sign_in дважды подряд работает:

  1. POST sign_in
  2. POST sign_in снова
  3. Позвонить GET / пользователю с cookie
  4. Работает - получает правильное разрешение Понсе с сервера

Отладка / Выяснение того, что не так

Я смотрел на devise.rb и на sessions_controller, но кажется, что сбой 401 происходит за пределами этих мест .

Кто-нибудь знает, что может вызвать эту проблему? Я пытаюсь отладить и найти, в чем проблема, но не могу добиться значительного прогресса. Похоже, что-то связано с Devise / Warden, но я не слишком знаком с тем, что там происходит.

Я бы хотел знать, кто хранит st_session cook ie и что хранится в нем, потому что кажется, что в первый раз чего-то не хватает (потому что st_session) короче, и похоже, что devise не может правильно аутентифицировать пользователя на основе этого значения.

Any помощь приветствуется, даже направьте меня в соответствующие места в коде, я могу искать ответы / помощь в отладке

Спасибо.

...