2016-10-03 7 views
7

У меня есть базовый компонент Node.js на основе Koa для моего личного/хобби-приложения.Обработка срока действия JWT и обновление полезной нагрузки JWT

Я реализовал обработку сеанса с помощью токенов JWT. Клиент (AngularJS) получает токен после успешного входа и где-то хранит токен (в настоящее время находится в sessionStorage, но для целей этого вопроса это не имеет значения).

У меня есть два вопроса:

  1. Когда мне нужно обновить запись пользователя, которая представляет JWT, скажем, пользователь включил 2fa, поэтому я попросил его предоставить свой номер телефона, и я хотел бы чтобы установить этот номер телефона в записи пользователя. В настоящее время после успешной проверки номера телефона я вызываю свой сервер для обновления записи пользователя, и я создаю новый токен JWT с обновленной пользовательской записью (я исключаю конфиденциальную информацию из токена JWT, как хешированный пароль, но я бы хотел чтобы указать номер телефона для использования на стороне клиента). Можно ли создать новый токен, когда некоторые учетные данные меняются и обновляют существующий токен клиентской стороны с помощью этого нового токена? Должен ли я когда-либо создавать еще один токен, только для создания одного и только при успешной аутентификации? Как мне затем обновить полезную нагрузку в токене?

  2. Как обращаться с истекшими токенами JWT? На мой взгляд, у меня есть 3 (возможных) сценария:

    2.1. JWT настроен на короткое время жизни, скажем, 15 минут. Если сервер backend отвечает с 401 Unauthenticated 'Invalid token' (я думаю, это поведение по умолчанию koa-jwt), то я автоматически выхожу из своего клиента и требую повторной аутентификации. Но я также создал дополнительное промежуточное программное обеспечение, которое является последним в цепочке на бэкэнде, чтобы заново создать токен с обновленным сроком действия, и клиент также заменит существующий токен обновленным. Поэтому, если пользователь активен и использует приложение для каждого защищенного вызова API, в случае успеха создаст новый токен, чтобы заменить старый токен.

    2.2. JWT установлен долгоживущим, скажем, 1 неделя, и если он истекает, я откажусь от повторной аутентификации у клиента.

    2.3. Скопируйте https://tools.ietf.org/html/rfc6749#section-1.5. Здесь при создании токена JWT после успешной аутентификации мы отправляем access_token, а также refresh_token. Когда срок действия access_token истек, и сервер отвечает с помощью HTTP 401 «недопустимый токен» (koa-jwt по умолчанию), клиент отправляет refresh_token в резервную копию, чтобы потребовать новый access_token (и, возможно, новый refresh_token). В этом случае я не совсем понимаю, как refresh_token проверяется против старого access_token, чтобы предоставить новый токен? Или почему нам нужно иметь refresh_token?

Любой общий совет по верхним темам (обновления JWT и истечение срока JWT) будет полезен.

+0

Почему бы просто не использовать печенье? – Kebman

ответ

3

Я хотел бы ответить на ваш второй вопрос, прежде чем я смогу перейти к первому.

В принципе, третий вариант, который вы упомянули, является лучшим способом продлить токены доступа. Токен доступа должен быть коротким проживанием (~ 5 минут), а токен обновления - более продолжительный. Когда ваш токен доступа истекает, отправьте токен обновления в бэкэнд и получите новый токен доступа.Таким образом, ваш ответ должен быть что-то вроде этого:

{ 
"token_type":"bearer", 
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s", 
"expires_in":10, 
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b" 
} 

Так что идея состоит в том, чтобы отделить ваше приложение в сервер авторизации (который генерирует маркер доступа/обновления маркера) & ресурсов сервера (проверить маркер доступа и доступа к ресурсам). Вы можете сохранить схему для проверки токена обновления с токеном доступа на сервере авторизации. Пожалуйста, обратитесь к разделу схемы, упомянутому в этой ссылке, которое может дать вам некоторую идею. Oauth2. Вы можете изменить схему в соответствии с вашими потребностями. Вам не нужно отправлять токен обновления вместе с токеном доступа для каждого вызова запроса. Обновить токен можно отправить только на сервер авторизации для создания нового токена доступа. Как создать токены обновления? Если я использую Java, я бы использовал UUID.randomUUID() для создания уникального токена обновления.

Теперь, чтобы ответить на ваш первый вопрос, если вы хотите обновить свою полезную нагрузку JWT на основе обновленных пользовательских записей, вы можете использовать тот же токен обновления, чтобы генерировать новый токен доступа с обновленной полезной нагрузкой. Логика остается такой же, поскольку, если номер телефона существует в пользовательской записи, он добавляется в полезную нагрузку, а если нет, то в полезной нагрузке будет пусто.

Основное преимущество использования Refresh маркеров является то, что доступ токены могут быть возобновлены в любое время с помощью токенов обновления

5

Начиная с нижней части, я бы игнорировать токены обновления, как я не думаю, что они помогут вам здесь , Они, как правило, нацелены на другие сценарии, в которых клиентское приложение может обеспечить более безопасное хранилище, чем пользовательский браузер, - считают родные мобильные приложения или серверные веб-приложения.

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

(выделено мною; источник refresh tokens)

Это означает, что вариант 2,3 является в основном таким же, как 2.2, который не является плохим вариантом. Нередко есть веб-приложения с длительной продолжительностью сеанса. Если ваше приложение не очень чувствительно, для повышения удобства пользователей приемлемо использовать длительный сеанс. Например, Django использует дефолт в течение двух недель для возраста своего cookie сеанса. См. SESSION_COOKIE_AGE.

Оставшаяся опция (2.1) обычно называется скользящей сессией. Тайм-аут сеанса короткий, но пока пользователь продолжает использовать приложение в течение этого интервала, сеанс автоматически обновляется. Возможно, это самый распространенный подход или, по крайней мере, тот, который я использовал больше всего времени, поэтому я предвзятый. Единственное, что я хотел бы отметить, это то, что скользящий сеанс обычно выполняется с непрозрачными идентификаторами сеанса, хранящимися на стороне клиента в виде файлов cookie, а затем с фактическими данными сеанса, хранящимися на сервере.

Ваш подход немного отличается, поскольку у вас есть токен JWT без государственной регистрации (он содержит фактические данные пользователя), хранящиеся в локальном хранилище браузера. Как вы сказали, для обновления токена вам придется сгенерировать новый, потому что вам придется создавать новую подпись.

Сигнатура используется для проверки того, что отправитель JWT, кто это говорит, что это и гарантировать, что сообщение не было изменено в пути.

(выделено мною; источник JSON web tokens)

Сказав все это, я хотел бы рассмотреть следующее:

  1. Спросите себя, если вам действительно нужно JWT-й или обычные идентификаторы сеанса сохраняются как cookie (HTTP Only) упростит вашу логику.
  2. Если JWT является требованием, например, у вас есть другой API, который также будет принимать эти токены в качестве аутентификации, тогда я бы рассмотрел вариант 2.1 или 2.2, поскольку токены обновления для браузера не рекомендуется.

Сказав это, вы также должны учитывать, что JWT не являются огромными, но они все равно будут накладными расходами, если вы решите автоматически продлеваться. Вы можете немного смягчить это, выбирая продолжительность сеанса 20 минут и выполняйте автоматическое обновление после половины сеанса.

Другое дело, что уязвимость, как XSS в приложении выставит маркер доступа к атакующим как инжектированных скрипты будут иметь возможность читать из localStorage/sessionStorage, это может быть еще одним доводом в пользу HTTP только сеанса хранения печенья ,