MERN OAuth 实现不会重定向到 Google 登录页面



我目前正在使用 MERN 堆栈运行网络服务器,我正在尝试让 OAuth 登录正常工作。但是,当我单击"使用谷歌登录"按钮时,反应会加载主页(但 URL 会更改(。直接获取 URL 会从服务器获得 302 响应,但我的前端没有改变。

服务器.js

const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const logger = require('morgan');
const cors = require('cors');
const secure = require('express-force-https');
const passport = require('passport');
const cookieSession = require('cookie-session');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
const dbRoute = process.env.MONGODB_URI || 'NO DB ROUTE PROVIDED';
// db setup
mongoose.connect(
dbRoute,
{
useNewUrlParser: true,
useUnifiedTopology: true,
dbName: process.env.DATABASE_NAME,
}
);
let db = mongoose.connection;
db.once('open', () => console.log("Connected to the database"));
db.on('error', console.error.bind(console, "MongoDB connection error: "));
// middleware
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false })); // body parsing
app.use(bodyParser.json());
app.use(logger("dev"));
app.use(express.static(path.join(__dirname, "client", "build"))); // for serving up the clientside code
app.use(secure); // ensure that the connection is using https
app.use(cookieSession({ // cookies!
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
keys:['vcxzkjvasddkvaosd'] // yeah i'm sure that's secure enough
}));
// models
require('./models/rule');
require('./models/affix');
require('./models/user');
// passport security
require('./config/passport');
app.use(passport.initialize());
app.use(passport.session());
// routes
app.use(require('./routes'));
// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/build/index.html'));
});
app.listen(port);
console.log(`Server listening on ${port}`);

路由(在不同的文件夹中有一些索引文件,因此此路由的完整路径/api/user/google(

const mongoose = require('mongoose');
const passport = require('passport');
const router = require('express').Router();
const auth = require('../auth');
const User = mongoose.model('User');
router.get('/google', 
passport.authenticate('google', {
scope: ['profile', 'email']
})
);
router.get('/google/callback', 
passport.authenticate('google', { failureRedirect: '/affixes'}),
(req, res) => {
res.redirect('/?token=' + req.user.token);
}
);

护照.js

const mongoose = require('mongoose');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
require('dotenv').config();
const User = mongoose.model('User');
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id).then((user) => {
done(null, user);
})
});
passport.use(new GoogleStrategy({
clientID: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
callbackURL: '/api/user/google/callback',
proxy: true
},
(accessToken, refreshToken, profile, done) => {
User.findOne({ googleId: profile.id })
.then((existingUser) => {
if (existingUser) {
done(null, existingUser);
} else {
new User({ googleId: profile.id }).save()
.then((user) => done(null, user));
}
});
}
));

前端登录页面(具有获取按钮和链接按钮。如上所述,不同的行为(

import React from 'react';
import {
ComingSoon
} from '../Common';
import {
Button
} from '@material-ui/core';
const handleClick = () => {
fetch('/api/user/google')
}
export default function Login() {
return (
<>
<Button onClick={handleClick}>
Login with Google
</Button>
<a href="/api/user/google"><button>Log in with Google</button></a>
</>
);
}

更新:看起来像某种 CORS 问题,尽管我仍然不知道如何解决它。浏览器吐出

Access to fetch at '...' (redirected from 'http://localhost:3000/api/user/google') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

添加请求的标头给了我

Access to fetch at '...' (redirected from 'http://localhost:3000/api/user/google') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

事实证明,我对这个问题的性质大错特错!问题是我对 OAuth 端点的提取请求正在调用我的前端,而不是我的后端,因为该请求在其Accept标头中包含text/html。使用反应高级代理设置路由到正确的 URI 解决了该问题。

请参阅:https://github.com/facebook/create-react-app/issues/5103 和 https://github.com/facebook/create-react-app/issues/8550

最新更新