Я использую Паспорт. 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, начиная с функции входа (которая теперь является прямой ссылкой). ) и токен аутентификации.
Что может быть лучшим способом сделать это?