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>
)
}
}
我有两个用于测试的不同按钮:
<a>
“按钮”将重定向到我们的React 404页面。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);
});
}
));
};
请告诉我是否可以提供其他信息。
非常感谢!
对于我的项目,当我在锚标记中将完整的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/'