Как использовать токен обновления JWT для создания нового токена доступа - PullRequest
0 голосов
/ 03 октября 2018

Я использую Node.js и Express для работы с JWT Auth.Прежде всего, каждый раз, когда пользователь создается и проверяется, я храню коллекцию refresh token внутри User:

const refreshToken = await jwt.sign({ userId: decoded.user }, process.env.JWT_Refresh_Key);
const user = await User.updateOne({ _id: mongoose.Types.ObjectId(decoded.user) }, { refresh_token: refreshToken, status: true });

Токен доступа JWT генерируется после успешного входа в систему (срок действия истекает через 15 минут):

const token = await jwt.sign(
                { email: user.email, userId: user._id, role: user.role },
                process.env.JWT_Key,
                { expiresIn: '15m' });
res.status(200).json({success: true, token: token});

Затем access token сохраняется в localStorage для обработки Angular Http Interceptor и методами аутентификации.Через 15 минут token будет недействительным для обработки запросов, поэтому мне нужно использовать refresh token, хранящийся в базе данных.

Метод обновления вызывается на AuthService.ts:

export class AuthService {
  constructor(private http: HttpClient){}

  refreshToken(token: string) {
      this.http.post<{token: string, expiresIn: number, name: string}>(`${BACKEND_URL}/refreshtoken`,     {token: token})
        .subscribe((data) => {
          const expiresAt = moment().add(data.expiresIn, 'second');
          localStorage.setItem('token', data.token);
          localStorage.setItem('expiration', JSON.stringify(expiresAt.valueOf()));
        });
    }
}

//route
router.post('/refreshtoken', user.refreshToken);

//controller user.js
exports.refreshToken = async(req, res, next) => {
    // I need to store and call 'old_refreshtoken' where??
    const user = await User.findOne({ refresh_token: old_refreshtoken });
    if (user) {
        const newToken = await jwt.sign(
            { email: user.email, userId: user._id, role: user.role },
            process.env.JWT_Key,
            { expiresIn: '15m' });
        res.status(200).json({success: true, token: newToken, expiresIn: 900, name: user.name});
    } else {
        res.status(401).json({success: false, message: 'Autenticação falhou.'});
    }
};

Как я могу использовать refresh token (базу данных) для генерации нового access token?Я не уверен, как хранить refresh token на стороне клиента (Angular) для сравнения с refresh token, хранящимся в базе данных.

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

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

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

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

 refreshToken = (payload, secret) => {
  const token = jwt.sign(payload, secret, {
    expiresIn: '15m',
  });
  return token
 }

, а затем проверить токен с помощьюjwt verify method jwt.verify(token, secret, handler).

exports.refreshToken = (req, res, next) => {
 const token = req.headers['x-access-token'] || req.headers.token;
 /* if token was not provided */
 if (!token) {
    return res.status(403).send({
        success: false,
        message: 'Not Authorized',
    });
 }
 /* verify token*/
 jwt.verify(token, secret, (error, decoded) => {
    if (error) {
        return res.status(401).send({
            success: false,
            message: 'Invalid token',
        });
    }
    req.decoded = decoded;
    next();
 });
}

В интерфейсном хранилище сохранить дату истечения срока действия (токен).Затем каждый раз, когда вы делаете запрос к бэкэнду, проверяйте, если токен все еще действителен (истек), используя метод jwt verify.Если срок его действия истек, запустите метод обновления токена.

  • Вы можете получить декодированный токен в параметре req, например req.decoded.
  • Store token на стороне клиента, используя localStorage , localStorage.setItem(userToken, token) и получить токен localStorage.getItem(userToken).
0 голосов
/ 03 октября 2018

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

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

  1. В интерфейсном хранилище сохранить дату окончания срока действия.Затем каждый раз, когда вы делаете запрос к бэк-энду, проверяйте, не истек ли срок действия (возможно, вы хотите учесть задержки запроса, например, за 5 секунд до истечения срока действия).Если срок его действия истек, запустите метод обновления токена.
  2. Создайте конечную точку токена обновления в back-end и отправьте ей access-token и refresh-token
  3. Декодируйте access-tokenи получите необходимые данные.В этой функции декодирования игнорируйте дату истечения срока действия.
  4. Сравните refresh-token с последним refresh-token в БД.Если он не совпадает, пользователь не авторизован.В противном случае продолжайте.
  5. Теперь, если вы хотите повторно использовать старые данные, вам не нужно запрашивать базу данных и просто перекодировать содержимое access-token в новый токен.В противном случае сделайте запрос и перестройте access-token.

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...