Как хранить повара ie в Redux после входа в Facebook? - PullRequest
0 голосов
/ 21 марта 2020

Я использую Паспорт. js для аутентификации Пользователя в Facebook. Однако я столкнулся с проблемой невозможности выяснить, как хранить повар ie, который содержит токен аутентификации. Для тестового компонента React я использую js-cookie, чтобы получить соответствующий повар ie, но, безусловно, должен быть лучший способ вызвать редуктор, который установил бы isAuthenticated в true после завершения входа в систему.

Итак, это паспорт. js файл:

const passport = require("passport");
const FacebookStrategy = require("passport-facebook").Strategy;
const config = require("config");

const clientId = config.get("facebook_api_key");
const clientSecret = config.get("facebook_api_secret");
const callbackUrl = config.get("facebook_callback_url");

const User = require("../models/User");

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  User.findById(id).then(user => {
    done(null, user);
  });
});

passport.use(
  new FacebookStrategy(
    {
      clientID: clientId,
      clientSecret: clientSecret,
      callbackURL: callbackUrl,
      profileFields: [
        "id",
        "email",
        "gender",
        "profileUrl",
        "displayName",
        "locale",
        "name",
        "timezone",
        "updated_time",
        "verified"
      ]
    },
    async (accessToken, refreshToken, profile, done) => {
      try {
        const oldUser = await User.findOne({ facebookId: profile.id });

        if (oldUser) {
          return done(null, oldUser);
        }
      } catch (err) {}

      // register user
      try {
        const newUser = await new User({
          facebookId: profile.id,
          name: profile.displayName,
          surname: "This is the surname",
          email: profile.emails[0].value,
          pictureUrl: profile.profileUrl
        }).save();

        done(null, newUser);
      } catch (err) {
        console.log(err);
      }
    }
  )
);

Это маршруты:

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

// @route   GET api/auth/facebook
// @desc    Login user via Facebook
// @access  Public
router.get(
  "/facebook",
  passport.authenticate("facebook", {
    scope: ["public_profile", "email"]
  })
);

// @route   GET api/auth/facebook/callback
// @desc    Get a callback from Facebook
// @access  Public
router.get(
  "/facebook/callback",
  passport.authenticate("facebook", {
    session: false,
    failureRedirect: "/"
  }),
  function(req, res) {
    const token = tokenFromUser(req.user);
    const user = req.user;
    res.cookie("x-auth-cookie", token);
    res.redirect("http://localhost:3000/api/profile");
    console.log(token);
    console.log(user);
  }
);

module.exports = router;

И это компонент React, который инициирует вход через Facebook . Обратите внимание, что само имя входа не относится к типу Action, поскольку я не смог понять, как сделать вход в Facebook через passport.js действием в Redux. Вместо этого есть прямая ссылка на конечную точку API:

import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";

class Landing extends Component {
  render() {
    return (
      <div>
        <div>Dashboard</div>
        {fbContent}
        <a
          href="http://localhost:5000/api/auth/facebook"
          onClick={this.fbLinkLogin}
        >
          Login with Facebook
        </a>
      </div>
    );
  }
}

Landing.propTypes = {
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});

export default connect(mapStateToProps)(withRouter(Landing));

Как только пользователь вошел в систему, он перенаправляется на /profile, и это компонент, где я использую js-cookie чтобы получить токен:

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
//import Navbar from "../layouts/Navbar";
import Cookies from "js-cookie";
import isEmpty from "../../validation/is-empty";

class Profile extends Component {
  constructor(props) {
    super(props);
    this.state = {
      cookie: Cookies.get("x-auth-cookie")
    };
  }

  componentDidMount() {
    console.log(this.state.cookie);
  }

  render() {
    const { user } = this.props.auth;

    let content;

    if (!isEmpty(this.state.cookie)) {
      content = (
        <div>
          {/*<Navbar auth={ this.props.auth }/>*/}
          Welcome !
        </div>
      );
    } else {
      content = (
        <div>
          {/*<Navbar auth={ this.props.auth }/>*/}
          not logged in !
        </div>
      );
    }

    return <div>{content}</div>;
  }
}

Profile.propTypes = {
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps)(Profile);

Это правильно отображает «Добро пожаловать!», так как я получаю токен от соответствующего повара ie. Тем не менее, я не хочу проверять наличие этого повара ie в каждом компоненте, и я хотел бы переместить все эти вещи в Redux, начиная с функции входа (которая теперь является прямой ссылкой). ) и токен аутентификации.

Что может быть лучшим способом сделать это?

...