对后端API的代理请求进行响应以启动Passport,Google OAuth2请求

问题描述 投票:3回答:1

SO社区,

我正在将Passport的Google-OAuth2策略与React前端一起使用。目前,我可以通过Postman转到后端API调用的Google登录页面。但是,如果我使用React从前端进行调用,React会将请求视为未知路径,并抛出我们的本地404页面。

这是我的代码,目前(我已经尝试了几种不同的方法来解决此问题):

反应成分

import React, { Component } from 'react';

// MaterialUI Components
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
// React APIs 
import API from "../utils/API";

const styles = {
    button: {
        marginTop: "1rem"
    }
}

export default class LoginForm extends Component {

    state = {
        email: "",
        password: ""
    };

    handleInputChange = event => {
        const { name, value } = event.target;

        this.setState({
            [name]: value
        });
    };

    handleSubmitForm = () => {
        let newLogin = {
            email : this.state.email,
            password : this.state.password
        }
        API.login(newLogin).then(res => console.log(res)).catch(err => console.log(err));
    };

    handleGoogleLogin = () => {
        fetch("/api/auth/google", {mode: 'no-cors'})
        .then(response => {
            console.log(response)
        })
        .catch(err => {
            console.log(err);
        });
    }

    render() {
        return (
            <div>
            <form noValidate autoComplete="off">
                <div>
                <TextField
                    id="email"
                    label="Email"
                    name="email"
                    value={this.state.email}
                    onChange={this.handleInputChange}
                    margin="normal"
                />
                </div>
                <div>
                <TextField
                    id="password"
                    label="Password"
                    type="password"
                    name="password"
                    onChange={this.handleInputChange}
                    margin="normal"
                    />
                </div>
                <Button
                    onClick={this.handleSubmitForm}
                    style={styles.button}
                    variant="outlined"
                    size="small">Login</Button>
                <Button
                    onClick={this.handleGoogleLogin}
                    style={styles.button}
                    variant="outlined"
                    size="small">Google Login</Button>
            </form>
            <div>
                <a type="button" className="MuiButtonBase-root MuiButton-root MuiButton-outlined MuiButton-sizeSmall" href="/api/auth/google">Google A Tag</a>
            </div>
            </div>
        )
    }
}

我有两个用于测试的不同按钮:

  1. [<a>“按钮”将重定向到我们的React 404页面。
  2. 调用handleGoogleLogin功能的按钮将挂起。的Google DevTools中的“网络”标签显示来自Google。

API路由

    // Redirect to Google authentication.
    app.get('/api/auth/google', function(){
        console.log("google api")
    }, passport.authenticate('google', { scope: ['profile', "email"] }));

    // After authentication, redirect back to home page.
    app.get('/api/auth/google/callback', passport.authenticate('google', { successRedirect: "/", failureRedirect: '/404', session: false }), function(req, res) {
        // var token = req.user.token
        // res.redirect('/');
        res.redirect("http://localhost:3000?token=" + token);
        // console.log("google callback")
    });

Passport.js

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const db = require('../models');
const keys = require('../config/keys');

const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;

module.exports = (passport) => {

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

    passport.use(
        new JwtStrategy(opts, (jwtPayload, done) => {
            db.Users
                .findOne({
                    where: {
                        id: jwtPayload.id
                    }
                })
                .then((user) => {
                    if (user) {
                        return done(null, user);
                    }
                    return done(null, false);
                })
                .catch((err) => console.log(err));
        })
    );

    passport.use(
        new GoogleStrategy({
            clientID: keys.googleClientID,
            clientSecret: keys.googleClientSecret,
            callbackURL: "http://localhost:3001/api/auth/google/callback"
        },
        function(accessToken, refreshToken, profile, done) {
            db.Users.findOrCreate({ googleId: profile.id }, function (err, user) {
                return done(err, user);
            });
        }
    ));
};

请告诉我是否可以提供其他信息。

非常感谢!

node.js reactjs google-oauth2 passport-google-oauth2
1个回答
0
投票

对于我的项目,当我在锚标记中将完整的URL传递给节点google-auth端点:http://localhost:3550/auth/google时,问题已解决。

您是否已经在做同样的事情?

我已如下设置我的google-oauth2登录名。

护照策略设置如下:

/**
 * Route handlers for Google oauth2 authentication. 
 * The first handler initiates the authentication flow. 
 * The second handler receives the response from Google. In case of failure, we will 
 * redirect to a pre-determined configurable route. In case of success, we issue a Json 
 * Web Token, and redirect to a pre-determined, configurable route.
 */

 this.router.get('/google', (req: Request, res: Response, next: NextFunction) => {
      passport.authenticate('google', {
          scope: process.env.GOOGLE_OAUTH2_SCOPES.split(",")
      })(req, res, next);
 });

 this.router.get('/google/callback',
      passport.authenticate('google', { failureRedirect:process.env.AUTH_FAILURE_REDIRECT }), (req, res) => this.jwtAuthService.issueJWTEnhanced(req, res, 'google'));

issueJwtEnhanced定义如下:

/**
 * Middleware for issuing JWT as part of the authentication flow. 
 * @param req Express HttpRequest Object
 * @param res Express HttpResponse Object
 */
 issueJWTEnhanced(req: any, res: Response, loginMech: string ) {
        this.logger.info('Inside JWT issuing service');
        this.logger.info('UserID: ' + req.user._id);
        jwt.sign({userId: req.user._id, loginMethod: loginMech}, process.env.JWT_SECRET, {expiresIn: '5 min'}, (err, token) => {
            if(err){
                this.logger.error('Error while trying to issue JWT: ' + err);
                this.logger.error(JSON.stringify(err));
                return res.redirect(process.env.AUTH_FAILURE_REDIRECT);
            }else{
                this.logger.info('Successfully issued JWT');
                this.logger.info('JWT Issued: ' + token);
                return res.redirect(process.env.AUTH_SUCCESS_REDIRECT + '/' + token);
            }
        }); 
    }

哪里,

AUTH_SUCCESS_REDIRECT ='http://localhost:4200/login-success'AUTH_FAILURE_REDIRECT ='http://localhost:4200/login/'

© www.soinside.com 2019 - 2024. All rights reserved.