如何解决如何使用 Auth0 和通行证通过 MERN 应用程序将会话属性附加到 req 对象?
我正在处理现有的 MERN 应用程序,但在使用 auth0 和护照时遇到问题。据我所知,auth0 提供身份验证并重定向回我的服务器。但是,应该附加到 req 对象的 user
属性似乎没有被添加,我认为这应该发生在 serializeUser
函数中。这是别人的代码库,所以我不是100%熟悉它,也不能咨询程序员提问。
我将在下面列出我的代码,并尝试通过它讲述我的方式来解释我的思考过程。我试过在网上搜索类似的问题和教程,但还没有找到答案。
这是 app.js
文件:
const cookieParser = require('cookie-parser')
const express = require('express')
const session = require('express-session')
const logger = require('morgan')
const passport = require('passport')
const cors = require('cors')
require('dotenv').config()
// connect to the database and define models
require('./db/config')
require('./models')
// require the router modules
const adminRouter = require('./routes/admin')
const authenticationRouter = require('./routes/authentication')
const challengeRouter = require('./routes/challenge')
const codeRouter = require('./routes/code')
const configRouter = require('./routes/config')
const feedbackRouter = require('./routes/feedback')
const hintRouter = require('./routes/hint')
const postAuthenticationRouter = require('./routes/postAuthenticationRouter')
const submissionRouter = require('./routes/submission')
const standingRouter = require('./routes/standing')
const userRouter = require('./routes/user')
const app = express()
// configure express
app.use(logger('dev'))
app.use(express.json())
app.use(cookieParser())
// configure express-session
const { SESSION_SECRET } = process.env
const sessionConfig = {
secret: SESSION_SECRET,cookie: {},resave: false,saveUninitialized: false,}
if (app.get('env') === 'production') {
sessionConfig.cookie.secure = true
}
// prevent status 304
app.disable('etag')
// import passport-auth0 strategy
const auth0Strategy = require('./passport/auth0')
app.use(session(sessionConfig))
passport.use(auth0Strategy)
// load passport strategies
app.use(passport.initialize())
app.use(passport.session())
// gets run after successful Auth0 authenticated login
passport.serializeUser((user,done) => {
done(null,user);
})
// gets run for each subsequent request after logging in
passport.deserializeUser((user,user);
})
app.use((req,res,next) => {
res.locals.isAuthenticated = req.isAuthenticated()
next()
})
// allow CORS
const corsOptions = {
origin: process.env.REACT_SERVER,credentials: true,}
app.use(cors(corsOptions))
// authentication middleware
const authCheckMiddleware = require('./middleware/auth-check')
// tell express which router to use based on endpoint
app.use('/api/v1/admin',authCheckMiddleware,adminRouter)
app.use('/api/v1/challenge',challengeRouter)
app.use('/api/v1/code',codeRouter)
app.use('/api/v1/config',configRouter)
app.use('/api/v1/feedback',feedbackRouter)
app.use('/api/v1/hint',hintRouter)
app.use('/api/v1/standing',standingRouter)
app.use('/api/v1/submission',submissionRouter)
app.use('/api/v1/user',userRouter)
app.use('/api/v1/postAuthentication',postAuthenticationRouter)
app.use('/',authenticationRouter)
module.exports = app
app.js
文件被导入到 www
文件中,从而完成后端服务器设置:
#!/usr/bin/env node
var app = require('../app');
var debug = require('debug')('backend:server');
var http = require('http');
var port = normalizePort(process.env.PORT || '3334');
app.set('port',port);
var server = http.createServer(app);
server.listen(port);
server.on('error',onError);
server.on('listening',onListening);
function normalizePort(val) {
var port = parseInt(val,10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
}
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
使用的 auth0 策略是从 auth0
文件导入的:
const Auth0 = require('passport-auth0')
const User = require('mongoose').model('User')
const {
AUTH0_DOMAIN,AUTH0_CLIENT_ID,AUTH0_CLIENT_SECRET,AUTH0_CALLBACK_URL,} = process.env
module.exports = new Auth0(
{
domain: AUTH0_DOMAIN,clientID: AUTH0_CLIENT_ID,clientSecret: AUTH0_CLIENT_SECRET,callbackURL: `${AUTH0_CALLBACK_URL}/authenticated`,scope: 'openid email profile <proprietary-url-1> <proprietary-url-2>',},// After Auth0 authentication,update user info in MongoDB
// to ensure it remains sync'd with Auth0's source of truth
async (accessToken,refreshToken,extraParams,profile,done) => {
try {
const userData = {
auth0Id: profile.id,username: profile.nickname,displayName: profile.displayName,last_login: new Date(),roleType: profile._json['<proprietary-url-1>'],}
let user = await User.findOneAndUpdate(
{ auth0Id: profile.id },userData,{
new: true,)
if (user) return done(null,user)
user = await User.create(userData)
return done(null,user)
} catch (err) {
return done(err)
}
return done(null,profile)
},)
我尝试评论上面的 try...catch 块并在其位置插入一个 console.log(profile)
,但没有收到任何输出。
在 app.js
中,app.use('/',authenticationRouter)
中导入的代码是:
const express = require('express')
const passport = require('passport')
require('dotenv').config()
const router = express.Router()
const {
AUTH0_DOMAIN,REACT_SERVER,} = process.env
// Pass user authentication off to Auth0
router.get(
'/login/auth0',passport.authenticate('auth0',{
scope: "openid email profile"
}))
// This route gets called once Auth0 has successfully authenticated the user
router.get('/authenticated',(req,next) => {
passport.authenticate('auth0',(passportAuthErr,user) => {
if (passportAuthErr) return next(passportAuthErr)
if (!user) return res.redirect(`${REACT_SERVER}/login`)
return req.logIn(user,(loginErr) => {
if (loginErr) return next(loginErr)
const { returnTo } = req.session
delete req.session.returnTo
return res.redirect(returnTo || `${REACT_SERVER}/authenticated`)
})
})(req,next)
})
// Perform session logout and redirect to homepage
router.get('/logout/auth0',res) => {
req.session.destroy(() => {
res.redirect(`https://${AUTH0_DOMAIN}/v2/logout?returnTo=${AUTH0_CALLBACK_URL}/deauthenticated&client_id=${AUTH0_CLIENT_ID}`)
});
});
router.get('/deauthenticated',res) => {
res.clearCookie('connect.sid')
res.json({ success: true })
})
module.exports = router
当它从 Auth0 返回时重定向到 postAuthenticationRouter.js
:
const express = require('express')
const jwt = require('jsonwebtoken')
const router = express.Router()
const { JWT_SECRET } = process.env
// This route gets called by the client once it has been
// redirected to /authenticated locally (after Auth0 authentication)
router.get('/',res) => {
console.log(req.session)
if (!req.session?.passport?.user) {
console.log('error!!')
return res.status(400).json({
success: false,message: 'Authentication failed!',})
}
const {
nickname: username,_id: userId,role: roleType,} = req.session.passport.user
const payload = {
sub: req.session.passport.user._id,}
const token = jwt.sign(payload,JWT_SECRET)
const userData = {
username,userId,roleType,}
return res.json({
success: true,message: 'You have successfully logged in.',token,user: userData,})
})
module.exports = router
console.log(req.session)
的输出为我提供了会话对象,但其中没有通行证属性。我添加了条件链接问号和 console.log('error!!')
以确保我至少做到了这一点,这是因为 error!!
被记录了。但后来我不能再进一步了。
因此,如果我能弄清楚如何在重定向从 Auth0 返回后将 session
对象附加到 req
对象,我就可以继续这个项目。
解决方法
事实证明,我在 Chromebook 上使用的 nodejs 版本不是最新的。更新后,该项目运行良好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。