Безопасный доступ к маршруту с JWT и localalstorage - PullRequest
0 голосов
/ 24 апреля 2019

Я создаю небольшое приложение, в которое пользователь входит и перенаправляется в / profile. Прямо сейчас я извлекаю JWT из локального хранилища и проверяю его через сервер. Затем сервер отправляет его обратно клиенту, чтобы сообщить мне, является ли это действительным сеансом или нет.

Jquery / Клиент:

  UserController.initPanel = () => {
    if (session === null) {
     window.location = "/";
    } else {
      UserController.requestAuth(session);
    }
  };

  UserController.requestAuth = (sessionToken) => {
    var settings = {
      "url": "/api/auth", 
      "method": "POST",
      "headers": {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${sessionToken}`,
      },
      "data": ""
    }

    $.ajax(settings).done(function (response) {
      console.log(response);
    });
  };

маршрут Node.js / auth.js:

router.post("/",  (req, res) => {
    const authHeader = req.headers.authorization;
    if (typeof authHeader !== 'undefined') {
        const bearerToken = authHeader.split(' ')[1];
        verifyToken(bearerToken, (authData) => {
            tokenRequest(authData, (authResponse) => {
                handleAuthResponse(req, res, authResponse);
            })
        });
    }
});

const handleAuthResponse = (req, res, authResponse) => {
    console.log(authResponse);
    return res.status(200).json(authResponse);
}


const verifyToken = (token, cb) => {
    jwt.verify(token, 'mysecret', (err, authData) => {
    if (err) {
        res.sendStatus(403)
    } else {
        cb(authData);
    }
    });
}

const tokenRequest = (authHeader, cb) => {
    //console.log(authHeader);
    var config = {
        headers: {'Authorization': `bearer ${authHeader.token}`}
    };
    axios.get('https://myapi.dev/api/session/me', config)
    .then((res) => {
      if (res.data.error) {
        return response.data
      } else {
        cb(res.data);
      }
    })
    .catch((error) => {
      console.log('error', error);
    }); 

}

Я чувствую, что это не правильный способ сделать это. Я рендеринг шаблонов с ejs:

router.get("/profile", (req, res) => {
  const settings = {
    title: "Profile",
    revslider: false
  };
  res.render("profile/profile", { settings: settings } );
});

И если по какой-то причине JS отключен, / profile все еще доступен. Это не такая уж большая проблема, просто кажется, что это неправильно.

Итак, можно ли получить доступ к профилю / маршруту, предварительно проверяя наличие авторизации на стороне сервера, перед рендерингом?

Кроме того, auth.js возвращает некоторые пользовательские данные, которые я мог бы использовать в шаблоне .ejs. Это еще одна причина, по которой я хотел бы попробовать проверить подлинность перед рендерингом.

EDIT:

Аутентификационное промежуточное ПО, которое я не использовал, потому что не знал, как передать токен?

module.exports = (req, res, next) => {
    try {
        const decoded = jwt.verify(req.body.token, 'mysecret');
        req.token = decoded;
    } catch (error) {
        console.log(error);
        return res.status(401).json({
            message: 'Auth Failed'
        }); 
    }
    next();
}

1 Ответ

0 голосов
/ 29 апреля 2019

Очень базовая middleware реализация, ниже которой используются express и express-session.

Мы в основном создаем простую функцию, чтобы проверить, существует ли req.session, внутри этого объекта может быть что-то, что идентифицирует, действительно ли пользователь прошел аутентификацию. Я бы порекомендовал вам добавить свою собственную логику сюда для дальнейшей проверки статуса пользователя.

const authCheckMiddleware = (req, res, next) => {
  // Perform auth checking logic here, which you can attach
  // to any route.
  if(!req.session) {
      return res.redirect('/');
  }

  next();
};

authCheckMiddleware может быть присоединен к любому route, с app.use или router.use. Объект req передается всему промежуточному программному обеспечению.

// Use the authCheckMiddleware function
router.use('/profile', authCheckMiddleware);

Ваш router.get('/profile') вызов теперь защищен вышеуказанным промежуточным ПО.

// Route protected by above auth check middleware
router.get("/profile", (req, res) => {
  const settings = {
      title: "Profile",
      revslider: false
  };

  res.render("profile/profile", { settings: settings } );
});
...