Авторизация на стороне сервера с JWT в SvelteKit

У меня проблема с отправкой токена JWT на сервер и его использованием для авторизации доступа в обработчиках load. Я использую Firebase на клиенте для аутентификации. При входе в систему (onAuthStateChanged) я отправляю POST запрос с токеном в конечную точку /api/login:

  export async function post(req) {    
    const idToken = req.headers['authorization']
    try {
        const token = await firebase().auth().verifyIdToken(idToken)
        req.locals.user = token.uid
    } catch (e) {
        console.log(e)
        return {
            status: 500,
            body: 'forbidden',
        }
    }
    
    return {
        status: 200,
        body: 'ok',
    }
}

In hooks.js:

export function getSession(request) {
    return {
        user: request.locals.user
    }
}

export async function handle({ request, resolve }) {
    const cookies = cookie.parse(request.headers.cookie || '')
    request.locals.user = cookies.user

    const response = await resolve(request)

    response.headers['set-cookie'] = `user=${request.locals.user || ''}; Path=/; HttpOnly`

    return response
}

В load методах:

export async function load({ session }) {
   if (!session.user) {
      return {
         status: 302,
         redirect: '/start'
      }
   }

   // ...
}

Все это работает нормально, за исключением того, что любая клиентская навигация после входа в систему отклоняется, потому что session.user все еще не определен. При навигации путем ввода URL-адреса в браузере он работает правильно, а после этого также работает клиентская навигация.

Есть идеи, почему и что делать?


person jpfollenius    schedule 12.06.2021    source источник


Ответы (1)


Я решил эту проблему, добавив перезагрузку браузера на той странице, на которую пользователь попадает после входа в систему. Фрагмент для перезагрузки на стороне клиента при успешном ответе от конечной точки API входа выглядит следующим образом

if (sessionLoginResponse?.status === "success") {
            await signOut(auth);
            window.history.back();

            setTimeout(() => {
              window.location.reload();
            }, 10);
          }
person Saikat Das    schedule 13.06.2021
comment
Почему signOut? Я не понимаю. Я попробовал метод перезагрузки, который вызвал цикл перезагрузок, потому что onAuthStateChanged снова сработал. Затем я ввел другой ответ от конечной точки, если пользователь уже вошел в систему, и только перезагрузил, если нет. Сначала казалось, что это сработало, но с тех пор я видел, как это повторялось снова. - person jpfollenius; 14.06.2021
comment
Итак, с аутентификацией firebase вы сохраняете файл cookie сеанса в своем JWT и проверяете его при каждом запросе. За документацией можно ознакомиться здесь. По моему опыту, этот подход работает лучше, чем борьба с токенами доступа и токенами обновления, которые, по моему опыту, лучше работают в ситуации SPA. - person Saikat Das; 14.06.2021
comment
Все еще в замешательстве. Это вызывает onAuthStateChanged вызов null на клиенте, поэтому я фактически выхожу из системы на клиенте. Я сделал что-то не так? Я тоже хочу оставаться авторизованным на клиенте. - person jpfollenius; 15.06.2021
comment
В приложении SSR в идеале, когда ваш бэкэнд предоставит вашему клиентскому приложению свой JWT, вы сможете выйти из системы и сделать последующие запросы к своему бэкэнду, включив JWT в файл cookie. И в этом случае вам не нужно отслеживать изменение состояния аутентификации, поскольку ваш JWT проверяется при каждом запросе к серверу. Причина, по которой вам нужен вход в систему? - person Saikat Das; 17.06.2021
comment
Потому что клиент также напрямую использует Firebase. У меня есть смесь предварительно отрисованных маршрутов с некоторым клиентским кодом Firebase и маршрутами, отрисованными на сервере. - person jpfollenius; 25.06.2021
comment
Понятно. В этом случае вы не можете выйти. Вы должны поддерживать оба состояния авторизации. Для SSR вы будете использовать токен JWT, хранящийся в вашем файле cookie, чтобы делать запросы к вашему бэкэнду, и администратор firebase может таким образом обслуживать данные. На стороне клиента вам нужно будет отслеживать изменения состояния аутентификации с помощью Firebase JS SDK и обрабатывать обновление пользовательского интерфейса в соответствии с - person Saikat Das; 27.06.2021