简体   繁体   中英

How to check isAuthenticated on react component using passport

Im having trouble figuring out how to proceed from where Im at. Right now I have the app running so you can sign up and log in but I want to be able to check if they are logged in by removing the sign up login in the nav and change it to logout. I have googled around but couldnt find anything would anyone be able to help me or point me in the right direction?

Here are my routes:

let express = require("express");
let router = express.Router();
let passport = require("passport");
let LocalStrategy = require("passport-local").Strategy;

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

// Register User
router.post("/register", function(req, res) {
  let email = req.body.email;
  let name = req.body.name;
  let phonenumber = req.body.phonenumber;
  let password = req.body.password;

  if (!name) {
    console.log("Errors");
  } else {
    //checking for email and username are already taken
    User.findOne(
      {
        email: {
          $regex: "^" + email + "\\b",
          $options: "i"
        }
      },
      function(err, mail) {
        if (mail) {
          res.render("register", {
            mail: mail
          });
        } else {
          let newUser = new User({
            name: name,
            email: email,
            phonenumber: phonenumber,
            password: password
          });

          User.createUser(newUser, function(err, user) {
            if (err) throw err;
            console.log(user);
          });

          req.flash("success_msg", "You are registered and can now login");
          res.redirect("/users/login");
        }
      }
    );
  }
});

passport.use(
  new LocalStrategy(
    {
      usernameField: "email"
    },
    function(username, password, done) {
      User.getUserByUsername(username, function(err, user) {
        if (err) throw err;
        if (!user) {
          return done(null, false, { message: "Unknown User" });
        }

        User.comparePassword(password, user.password, function(err, isMatch) {
          if (err) throw err;
          if (isMatch) {
            return done(null, user);
          } else {
            return done(null, false, {
              message: "Invalid password"
            });
          }
        });
      });
    }
  )
);

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

passport.deserializeUser(function(id, done) {
  User.getUserById(id, function(err, user) {
    done(err, user);
  });
});

router.post(
  "/login",
  passport.authenticate("local", {
    successRedirect: "/YOU_DID_IT_SCRUB",
    failureRedirect: "/YOU_FAILED_SCRUB",
    failureFlash: true
  }),
  function(req, res) {}
);

module.exports = router;

Here is the component I want to display the login logout button

import React, { Component } from "react";
import {
  Navbar,
  NavbarBrand,
  NavbarItem,
  NavbarEnd,
  Modal,
  ModalCard,
  ModalCardTitle,
  ModalBackground,
  ModalCardFooter,
  ModalCardHeader,
  Delete,
  ModalCardBody
} from "bloomer";
import { Link } from "react-router-dom";
import StepZilla from "react-stepzilla";
import "bulma/css/bulma.css";
import "./Nav.css";
import pad from "./pad.png";
import modal from "./modal.svg";
import { SignUpModal } from "./SignUpModal";
import { LoginModal } from "./LoginModal";
import { MemberType } from "./MemberType";
import API from "../../utils/API";

const padLogo = { image: `url(${pad})` };
const steps = [
  { name: "Step 1", component: <MemberType /> },
  { name: "Step 2", component: <SignUpModal /> }
];

const modalBG = { backgroundImage: `url(${modal})` };

export class Nav extends Component {
  state = {
    modal: "",
    login: ""
  };

  modalOpen = () => {
    this.setState({ modal: "is-active" });
  };

  loginOpen = () => {
    this.setState({ login: "is-active" });
  };

  modalClose = () => {
    this.setState({
      modal: "",
      login: ""
    });
  };

  render() {
    return (
      <Navbar className="navbar">
        <NavbarBrand>
          <NavbarItem className="nav-logo-item">
            <img src={pad} />
          </NavbarItem>
          <NavbarItem>
            <Link to={"/"}>
              <p className="nav-title">Lilypad Rentals</p>
            </Link>
          </NavbarItem>
        </NavbarBrand>
        <NavbarEnd>
          <NavbarItem>
            <Link to={"/property"}>
              <p>Property</p>
            </Link>
          </NavbarItem>
          <NavbarItem>
            <Link to={"/results"}>
              <p>Results</p>
            </Link>
          </NavbarItem>
          <NavbarItem>
            <Link to={"/manager"}>
              <p>Property Form</p>
            </Link>
          </NavbarItem>
          <NavbarItem href="#">
            <p>Create Listing</p>
          </NavbarItem>
          <NavbarItem href="#" onClick={this.loginOpen}>
            <p>Log in</p>
          </NavbarItem>
          <NavbarItem href="#" onClick={this.modalOpen}>
            <p>Sign Up</p>
          </NavbarItem>
        </NavbarEnd>

        <div className="signup-modal">
          <Modal className={this.state.modal}>
            <ModalBackground />
            <ModalCard style={modalBG}>
              <ModalCardBody>
                <Delete onClick={this.modalClose} />

                <div className="step-progress">
                  <StepZilla
                    steps={steps}
                    showSteps={false}
                    nextButtonCls="button is-medium is-primary"
                    backButtonCls="button is-medium is-primary"
                  />
                </div>
              </ModalCardBody>
            </ModalCard>
          </Modal>
        </div>

        <div className="login-modal">
          <Modal className={this.state.login}>
            <ModalBackground />
            <ModalCard>
              <ModalCardHeader>
                <ModalCardTitle />
                <Delete onClick={this.modalClose} />
              </ModalCardHeader>
              <LoginModal />
              <ModalCardFooter hasTextAlign="centered">
                <p>
                  Already have an account? <Link to={""}>Log In</Link> .
                </p>
              </ModalCardFooter>
            </ModalCard>
          </Modal>
        </div>
      </Navbar>
    );
  }
}

Passport creates a req.user object if authentication was successful. You can use that to determine if the user is logged in or not.

If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user - http://www.passportjs.org/docs/authenticate/

Before proceeding any further, you'll have to set-up the cookie-parser middleware on your Express server.

...
import cookieParser from 'cookie-parser';

app.use(cookieParser({secret: 'mySecret'}));
...

After that, you'll need to create a signed cookie yourself inside the success callback.

...
router.post(
  "/login",
  passport.authenticate("local", {
     successRedirect: "/YOU_DID_IT_SCRUB",
     failureRedirect: "/YOU_FAILED_SCRUB",
     failureFlash: true
  }),
  function(req, res) {
     // if this gets called then authentication was successful
     res.cookie('session', req.user.id, { secure: true, signed: true, expires: new Date(Date.now() + 3600) });
  });

I would recommend using react-cookie to set/get cookies on the client side. To parse the signed cookie just import cookieParser from 'cookie-parser' and use the cookieParser.signedCookie() method in your React component to parse the signed cookie and confirm that it hasn't been tampered with on the client side.

res.cookie reference

After you authenticate the user on your server side, you could use JSON Web Tokens to create a token with the user's information to send to your front end.

Once you have that, you can easily authenticate or de-authenticate your user in React by storing the token in local storage. Here is an example of a few simple steps to do so:

Consider an Auth.js file

class Auth {

    static authenticateUser(token) {
        localStorage.setItem('token', token)
    }

    static isUserAuthenticated() {
        return localStorage.getItem('token') !== null
    }

    static deauthenticateUser() {
        localStorage.removeItem('token')
    }

    static getToken() {
        return localStorage.getItem('token')
    }
}

export default Auth

In your existing Nav.js component, retrieve the token sent from your server side and then you could do something like:

import Auth from './Auth'
export default class Nav extends Component {

    // authenticate user upon login
    isLoggedIn(token) {
        Auth.authenticateUser(token)
    }

    render() {
        if (Auth.isUserAuthenticated()) {
            return <NavbarItem>Log out</NavbarItem>
        } else {
            return <NavbarItem>Log in</NavbarItem>
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM