Как улучшить поток аутентификации с внутреннего (nodejs) на внешний (реагировать) с использованием паспорта js? - PullRequest
0 голосов
/ 29 марта 2020

С моими текущими настройками аутентификации у меня может быть сценарий ios, где данные устарели и могут вызвать путаницу у потенциального пользователя. Когда пользователь аутентифицирован, паспорт обрабатывает сериализацию и десериализацию; Затем я храню эту информацию для последующего использования.

На внешнем интерфейсе у меня есть поставщик контекста, который делает вызовы API к внутреннему интерфейсу, чтобы получить эту сохраненную информацию о пользователе (req.user). Если пользователь входит в систему или выходит из нее, контекст делает API-вызовы на сервер, чтобы обновить пользовательскую информацию, которая предоставляется компонентам реагирования.

Проблема возникает, если пользователь выходит из системы на другой вкладке или по истечении времени сеанса. Интерфейсный API не узнает об этом, пока я не опрошу пользовательские данные каждые несколько минут. Даже тогда есть период времени для того, чтобы эти данные устарели.

Мой вопрос: как я могу сразу отследить, истек ли сеанс, и затем выполнить обновление состояния реакции в контексте, чтобы не было места для пользователю получить устаревшие данные?

Вот мой маршрут аутентификации auth. js:

const express = require("express");
const router = express.Router();
const passport = require("passport");

router.get("/", function(req, res) {
  if (res.locals.user) {
    res.json(res.locals.user);
  } else {
    res.json({});
  }
});

router.get(
  "/steam",
  passport.authenticate("steam", { failureRedirect: "/" }),
  function(req, res) {
    res.redirect("/");
  }
);

router.get(
  "/steam/return",
  passport.authenticate("steam", { failureRedirect: "/", session: true }),
  function(req, res) {
    res.redirect(`http://localhost:3000`);
  }
);

router.get("/logout", (req, res) => {
  try {
    req.logout();
    res.json({
      status: "success",
      data: "Logout successful."
    });
  } catch (error) {
    return res.status(400).json({ error: "Failed to logout." });
  }
});

module.exports = router;

Вот мой поставщик контекста UserProvider. js:

import React, { createContext, useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import axios from "axios";

const context = createContext(null);

const UserProvider = ({ children }) => {
  const history = useHistory();
  const [user, setUser] = useState(null);

  const getUser = async () => {
    try {
      const userObject = await axios.get("/api/auth");
      setUser(userObject.data);
    } catch (error) {
      console.error("Failed to get user.");
    }
  };

  const handleLogout = async () => {
    try {
      await axios.get("/api/auth/logout");
      setUser({});
    } catch (error) {
      console.error(error);
    }
  };

  // get user every 5 minutes (300,000 ms)
  let userFetchInterval = 5;
  userFetchInterval = 1000 * 60 * userFetchInterval;
  setInterval(getUser, userFetchInterval);

  useEffect(() => {
    getUser();
  }, []);

  return (
    <context.Provider value={{ user, logout: handleLogout, getUser }}>
      {children}
    </context.Provider>
  );
};

UserProvider.context = context;

export default UserProvider;

Редактировать: Я забыл предоставить определение стратегии аутентификации. Вот мой SteamAuth. js

const SteamStrategy = require("passport-steam").Strategy;
const keys = require("./default.json");
const { getDatabase } = require("../Shared/MongoUtil");
const db = getDatabase();
const USERS = db.collection("Users");

module.exports = function(passport) {
  passport.use(
    new SteamStrategy(
      {
        returnURL: "http://localhost:3443/api/auth/steam/return",
        realm: "http://localhost:3443/",
        apiKey: keys.steamAPIKey
      },
      async (identifier, profile, done) => {
        const newUser = {
          provider: "steam",
          steamID: profile.id,
          displayName: profile.displayName,
          image: profile.photos[2],
          visibility: "public"
        };

        let foundUser;
        try {
          foundUser = await USERS.find({
            steamID: { $exists: true },
            steamID: profile.id
          }).toArray();
        } catch (findErr) {
          console.error(err);
        }

        if (foundUser.length > 0) {
          return done(null, foundUser);
        } else {
          try {
            const userData = await USERS.insertOne(newUser);
            return done(null, userData.ops[0]);
          } catch (insertErr) {
            console.error(`Failed to create steam user.${insertErr}`);
            return done(null, null);
          }
        }
      }
    )
  );

  passport.serializeUser(function(user, done) {
    // console.log(`user is ${JSON.stringify(user)}`);
    done(null, user);
  });

  passport.deserializeUser(function(obj, done) {
    done(null, obj);
  });
};
...