我如何获得会话属性附加到使用Auth0和护照与MERN应用程序的req对象?



我正在研究一个现有的MERN应用程序,我在auth0和passport方面遇到了麻烦。据我所知,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, done) => {
done(null, 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', authCheckMiddleware, challengeRouter)
app.use('/api/v1/code', authCheckMiddleware, codeRouter)
app.use('/api/v1/config', authCheckMiddleware, configRouter)
app.use('/api/v1/feedback', authCheckMiddleware, feedbackRouter)
app.use('/api/v1/hint', authCheckMiddleware, hintRouter)
app.use('/api/v1/standing', authCheckMiddleware, standingRouter)
app.use('/api/v1/submission', authCheckMiddleware, submissionRouter)
app.use('/api/v1/user', authCheckMiddleware, 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.jsapp.use('/', authenticationRouter)中导入的代码为:

const express = require('express')
const passport = require('passport')
require('dotenv').config()
const router = express.Router()
const {
AUTH0_DOMAIN,
AUTH0_CALLBACK_URL,
AUTH0_CLIENT_ID,
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, res, 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, res, next)
})
// Perform session logout and redirect to homepage
router.get('/logout/auth0', (req, res) => {
req.session.destroy(() => {
res.redirect(`https://${AUTH0_DOMAIN}/v2/logout?returnTo=${AUTH0_CALLBACK_URL}/deauthenticated&client_id=${AUTH0_CLIENT_ID}`)
});
});
router.get('/deauthenticated', (req, 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('/', (req, 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!!被记录。但是我不能再往前走了。

所以,如果我能弄清楚如何获得session对象追加到req对象一旦重定向从Auth0回来,我可以继续这个项目。

原来我在Chromebook上使用的nodejs版本不是最新的。一旦我更新了它,项目就可以正常工作了。

最新更新