Update JWT auth extractors, add state in openid redirect, add back cors for api router

This commit is contained in:
advplyr 2023-09-25 17:05:58 -05:00
parent e282142d3f
commit 0d5a30b214
3 changed files with 43 additions and 21 deletions

View File

@ -16,6 +16,18 @@ class Auth {
constructor() {
}
static cors(req, res, next) {
res.header('Access-Control-Allow-Origin', '*')
res.header("Access-Control-Allow-Methods", 'GET, POST, PATCH, PUT, DELETE, OPTIONS')
res.header('Access-Control-Allow-Headers', '*')
res.header('Access-Control-Allow-Credentials', true)
if (req.method === 'OPTIONS') {
res.sendStatus(200)
} else {
next()
}
}
/**
* Inializes all passportjs strategies and other passportjs ralated initialization.
*/
@ -78,7 +90,7 @@ class Auth {
// Load the JwtStrategy (always) -> for bearer token auth
passport.use(new JwtStrategy({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
jwtFromRequest: ExtractJwt.fromExtractors([ExtractJwt.fromAuthHeaderAsBearerToken(), ExtractJwt.fromUrlQueryParameter('token')]),
secretOrKey: Database.serverSettings.tokenSecret
}, this.jwtAuthCheck.bind(this)))
@ -123,15 +135,25 @@ class Auth {
httpOnly: true
})
// persist state if passed in
if (req.query.state) {
res.cookie('auth_state', req.query.state, {
maxAge: 120000, // 2 min
httpOnly: true
})
}
const callback = req.query.redirect_uri || req.query.callback
// check if we are missing a callback parameter - we need one if isRest=false
if (!req.query.callback) {
if (!callback) {
res.status(400).send({
message: 'No callback parameter'
})
return
}
// store the callback url to the auth_cb cookie
res.cookie('auth_cb', req.query.callback, {
res.cookie('auth_cb', callback, {
maxAge: 120000, // 2 min
httpOnly: true
})
@ -155,9 +177,10 @@ class Auth {
} else {
// UI request -> check if we have a callback url
// TODO: do we want to somehow limit the values for auth_cb?
if (req.cookies.auth_cb?.startsWith('http')) {
if (req.cookies.auth_cb) {
let stateQuery = req.cookies.auth_state ? `&state=${req.cookies.auth_state}` : ''
// UI request -> redirect to auth_cb url and send the jwt token as parameter
res.redirect(302, `${req.cookies.auth_cb}?setToken=${data_json.user.token}`)
res.redirect(302, `${req.cookies.auth_cb}?setToken=${data_json.user.token}${stateQuery}`)
} else {
res.status(400).send('No callback or already expired')
}
@ -201,10 +224,9 @@ class Auth {
// openid strategy callback route (this receives the token from the configured openid login provider)
router.get('/auth/openid/callback',
passport.authenticate('openidconnect', { failureRedirect: '/login', failureMessage: true }),
passport.authenticate('openidconnect'),
// on a successfull login: read the cookies and react like the client requested (callback or json)
this.handleLoginSuccessBasedOnCookie.bind(this)
)
this.handleLoginSuccessBasedOnCookie.bind(this))
// Logout route
router.post('/logout', (req, res) => {
@ -288,9 +310,9 @@ class Auth {
*/
async jwtAuthCheck(jwt_payload, done) {
// load user by id from the jwt token
const user = await Database.userModel.getUserById(jwt_payload.id)
const user = await Database.userModel.getUserByIdOrOldId(jwt_payload.userId)
if (!user || !user.isActive) {
if (!user?.isActive) {
// deny login
done(null, null)
return

View File

@ -180,7 +180,7 @@ class Server {
router.use(express.static(Path.join(global.appRoot, 'static')))
// router.use('/api/v1', routes) // TODO: New routes
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
router.use('/api', Auth.cors, this.authMiddleware.bind(this), this.apiRouter.router)
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
// RSS Feed temp route

View File

@ -6,7 +6,7 @@ class SessionController {
constructor() { }
async findOne(req, res) {
return res.json(req.session)
return res.json(req.playbackSession)
}
async getAllWithUserData(req, res) {
@ -63,32 +63,32 @@ class SessionController {
}
async getOpenSession(req, res) {
const libraryItem = await Database.libraryItemModel.getOldById(req.session.libraryItemId)
const sessionForClient = req.session.toJSONForClient(libraryItem)
const libraryItem = await Database.libraryItemModel.getOldById(req.playbackSession.libraryItemId)
const sessionForClient = req.playbackSession.toJSONForClient(libraryItem)
res.json(sessionForClient)
}
// POST: api/session/:id/sync
sync(req, res) {
this.playbackSessionManager.syncSessionRequest(req.user, req.session, req.body, res)
this.playbackSessionManager.syncSessionRequest(req.user, req.playbackSession, req.body, res)
}
// POST: api/session/:id/close
close(req, res) {
let syncData = req.body
if (syncData && !Object.keys(syncData).length) syncData = null
this.playbackSessionManager.closeSessionRequest(req.user, req.session, syncData, res)
this.playbackSessionManager.closeSessionRequest(req.user, req.playbackSession, syncData, res)
}
// DELETE: api/session/:id
async delete(req, res) {
// if session is open then remove it
const openSession = this.playbackSessionManager.getSession(req.session.id)
const openSession = this.playbackSessionManager.getSession(req.playbackSession.id)
if (openSession) {
await this.playbackSessionManager.removeSession(req.session.id)
await this.playbackSessionManager.removeSession(req.playbackSession.id)
}
await Database.removePlaybackSession(req.session.id)
await Database.removePlaybackSession(req.playbackSession.id)
res.sendStatus(200)
}
@ -111,7 +111,7 @@ class SessionController {
return res.sendStatus(404)
}
req.session = playbackSession
req.playbackSession = playbackSession
next()
}
@ -130,7 +130,7 @@ class SessionController {
return res.sendStatus(403)
}
req.session = playbackSession
req.playbackSession = playbackSession
next()
}
}