mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-03-14 00:21:31 +01:00
Update JWT auth extractors, add state in openid redirect, add back cors for api router
This commit is contained in:
parent
e282142d3f
commit
0d5a30b214
@ -16,6 +16,18 @@ class Auth {
|
|||||||
constructor() {
|
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.
|
* Inializes all passportjs strategies and other passportjs ralated initialization.
|
||||||
*/
|
*/
|
||||||
@ -78,7 +90,7 @@ class Auth {
|
|||||||
|
|
||||||
// Load the JwtStrategy (always) -> for bearer token auth
|
// Load the JwtStrategy (always) -> for bearer token auth
|
||||||
passport.use(new JwtStrategy({
|
passport.use(new JwtStrategy({
|
||||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
jwtFromRequest: ExtractJwt.fromExtractors([ExtractJwt.fromAuthHeaderAsBearerToken(), ExtractJwt.fromUrlQueryParameter('token')]),
|
||||||
secretOrKey: Database.serverSettings.tokenSecret
|
secretOrKey: Database.serverSettings.tokenSecret
|
||||||
}, this.jwtAuthCheck.bind(this)))
|
}, this.jwtAuthCheck.bind(this)))
|
||||||
|
|
||||||
@ -123,15 +135,25 @@ class Auth {
|
|||||||
httpOnly: true
|
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
|
// check if we are missing a callback parameter - we need one if isRest=false
|
||||||
if (!req.query.callback) {
|
if (!callback) {
|
||||||
res.status(400).send({
|
res.status(400).send({
|
||||||
message: 'No callback parameter'
|
message: 'No callback parameter'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// store the callback url to the auth_cb cookie
|
// 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
|
maxAge: 120000, // 2 min
|
||||||
httpOnly: true
|
httpOnly: true
|
||||||
})
|
})
|
||||||
@ -155,9 +177,10 @@ class Auth {
|
|||||||
} else {
|
} else {
|
||||||
// UI request -> check if we have a callback url
|
// UI request -> check if we have a callback url
|
||||||
// TODO: do we want to somehow limit the values for auth_cb?
|
// 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
|
// 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 {
|
} else {
|
||||||
res.status(400).send('No callback or already expired')
|
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)
|
// openid strategy callback route (this receives the token from the configured openid login provider)
|
||||||
router.get('/auth/openid/callback',
|
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)
|
// 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
|
// Logout route
|
||||||
router.post('/logout', (req, res) => {
|
router.post('/logout', (req, res) => {
|
||||||
@ -288,9 +310,9 @@ class Auth {
|
|||||||
*/
|
*/
|
||||||
async jwtAuthCheck(jwt_payload, done) {
|
async jwtAuthCheck(jwt_payload, done) {
|
||||||
// load user by id from the jwt token
|
// 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
|
// deny login
|
||||||
done(null, null)
|
done(null, null)
|
||||||
return
|
return
|
||||||
|
@ -180,7 +180,7 @@ class Server {
|
|||||||
router.use(express.static(Path.join(global.appRoot, 'static')))
|
router.use(express.static(Path.join(global.appRoot, 'static')))
|
||||||
|
|
||||||
// router.use('/api/v1', routes) // TODO: New routes
|
// 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)
|
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
||||||
|
|
||||||
// RSS Feed temp route
|
// RSS Feed temp route
|
||||||
|
@ -6,7 +6,7 @@ class SessionController {
|
|||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
async findOne(req, res) {
|
async findOne(req, res) {
|
||||||
return res.json(req.session)
|
return res.json(req.playbackSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllWithUserData(req, res) {
|
async getAllWithUserData(req, res) {
|
||||||
@ -63,32 +63,32 @@ class SessionController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getOpenSession(req, res) {
|
async getOpenSession(req, res) {
|
||||||
const libraryItem = await Database.libraryItemModel.getOldById(req.session.libraryItemId)
|
const libraryItem = await Database.libraryItemModel.getOldById(req.playbackSession.libraryItemId)
|
||||||
const sessionForClient = req.session.toJSONForClient(libraryItem)
|
const sessionForClient = req.playbackSession.toJSONForClient(libraryItem)
|
||||||
res.json(sessionForClient)
|
res.json(sessionForClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: api/session/:id/sync
|
// POST: api/session/:id/sync
|
||||||
sync(req, res) {
|
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
|
// POST: api/session/:id/close
|
||||||
close(req, res) {
|
close(req, res) {
|
||||||
let syncData = req.body
|
let syncData = req.body
|
||||||
if (syncData && !Object.keys(syncData).length) syncData = null
|
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
|
// DELETE: api/session/:id
|
||||||
async delete(req, res) {
|
async delete(req, res) {
|
||||||
// if session is open then remove it
|
// 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) {
|
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)
|
res.sendStatus(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class SessionController {
|
|||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.session = playbackSession
|
req.playbackSession = playbackSession
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ class SessionController {
|
|||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.session = playbackSession
|
req.playbackSession = playbackSession
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user