diff --git a/server/Auth.js b/server/Auth.js index d6d67d49..b7ea59c4 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -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 diff --git a/server/Server.js b/server/Server.js index 08f4b8d9..2f04b850 100644 --- a/server/Server.js +++ b/server/Server.js @@ -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 diff --git a/server/controllers/SessionController.js b/server/controllers/SessionController.js index 85baeb27..884f0cd6 100644 --- a/server/controllers/SessionController.js +++ b/server/controllers/SessionController.js @@ -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() } }