mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-26 19:21:39 +00:00
refactor(server): centralize request HTTPS and origin detection
This commit is contained in:
parent
6f03467f35
commit
527745b54e
4 changed files with 79 additions and 4 deletions
|
|
@ -14,6 +14,7 @@ const { version } = require('../package.json')
|
||||||
const is = require('./libs/requestIp/isJs')
|
const is = require('./libs/requestIp/isJs')
|
||||||
const fileUtils = require('./utils/fileUtils')
|
const fileUtils = require('./utils/fileUtils')
|
||||||
const { toNumber } = require('./utils/index')
|
const { toNumber } = require('./utils/index')
|
||||||
|
const { getRequestOrigin } = require('./utils/requestUtils')
|
||||||
const Logger = require('./Logger')
|
const Logger = require('./Logger')
|
||||||
|
|
||||||
const Auth = require('./Auth')
|
const Auth = require('./Auth')
|
||||||
|
|
@ -288,10 +289,9 @@ class Server {
|
||||||
// if RouterBasePath is set, modify all requests to include the base path
|
// if RouterBasePath is set, modify all requests to include the base path
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
const urlStartsWithRouterBasePath = req.url.startsWith(global.RouterBasePath)
|
const urlStartsWithRouterBasePath = req.url.startsWith(global.RouterBasePath)
|
||||||
const host = req.get('host')
|
const { origin } = getRequestOrigin(req)
|
||||||
const protocol = req.secure || req.get('x-forwarded-proto') === 'https' ? 'https' : 'http'
|
|
||||||
const prefix = urlStartsWithRouterBasePath ? global.RouterBasePath : ''
|
const prefix = urlStartsWithRouterBasePath ? global.RouterBasePath : ''
|
||||||
req.originalHostPrefix = `${protocol}://${host}${prefix}`
|
req.originalHostPrefix = `${origin}${prefix}`
|
||||||
if (!urlStartsWithRouterBasePath) {
|
if (!urlStartsWithRouterBasePath) {
|
||||||
req.url = `${global.RouterBasePath}${req.url}`
|
req.url = `${global.RouterBasePath}${req.url}`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ const Logger = require('../Logger')
|
||||||
|
|
||||||
const requestIp = require('../libs/requestIp')
|
const requestIp = require('../libs/requestIp')
|
||||||
const jwt = require('../libs/jsonwebtoken')
|
const jwt = require('../libs/jsonwebtoken')
|
||||||
|
const { isRequestSecure } = require('../utils/requestUtils')
|
||||||
|
|
||||||
class TokenManager {
|
class TokenManager {
|
||||||
/** @type {string} JWT secret key */
|
/** @type {string} JWT secret key */
|
||||||
|
|
@ -59,7 +60,7 @@ class TokenManager {
|
||||||
setRefreshTokenCookie(req, res, refreshToken) {
|
setRefreshTokenCookie(req, res, refreshToken) {
|
||||||
res.cookie('refresh_token', refreshToken, {
|
res.cookie('refresh_token', refreshToken, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: req.secure || req.get('x-forwarded-proto') === 'https',
|
secure: isRequestSecure(req),
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
maxAge: this.RefreshTokenExpiry * 1000,
|
maxAge: this.RefreshTokenExpiry * 1000,
|
||||||
path: '/'
|
path: '/'
|
||||||
|
|
|
||||||
34
server/utils/requestUtils.js
Normal file
34
server/utils/requestUtils.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* Whether the request was made over HTTPS.
|
||||||
|
* Uses Express `req.secure` and a strict `x-forwarded-proto === 'https'` check.
|
||||||
|
*
|
||||||
|
* @param {import('express').Request} req
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isRequestSecure(req) {
|
||||||
|
return req.secure || req.get('x-forwarded-proto') === 'https'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('express').Request} req
|
||||||
|
* @returns {'https' | 'http'}
|
||||||
|
*/
|
||||||
|
function getRequestProtocol(req) {
|
||||||
|
return isRequestSecure(req) ? 'https' : 'http'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('express').Request} req
|
||||||
|
* @returns {{ protocol: 'https' | 'http', host: string, origin: string }}
|
||||||
|
*/
|
||||||
|
function getRequestOrigin(req) {
|
||||||
|
const protocol = getRequestProtocol(req)
|
||||||
|
const host = req.get('host')
|
||||||
|
return { protocol, host, origin: `${protocol}://${host}` }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isRequestSecure,
|
||||||
|
getRequestProtocol,
|
||||||
|
getRequestOrigin
|
||||||
|
}
|
||||||
40
test/server/utils/requestUtils.test.js
Normal file
40
test/server/utils/requestUtils.test.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
const { expect } = require('chai')
|
||||||
|
|
||||||
|
const { isRequestSecure, getRequestProtocol, getRequestOrigin } = require('../../../server/utils/requestUtils')
|
||||||
|
|
||||||
|
function mockReq({ secure = false, host = 'books.example.com', xForwardedProto = null } = {}) {
|
||||||
|
return {
|
||||||
|
secure,
|
||||||
|
get(header) {
|
||||||
|
if (header === 'host') return host
|
||||||
|
if (header === 'x-forwarded-proto') return xForwardedProto
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('requestUtils', () => {
|
||||||
|
it('isRequestSecure uses req.secure', () => {
|
||||||
|
expect(isRequestSecure(mockReq({ secure: true }))).to.equal(true)
|
||||||
|
expect(isRequestSecure(mockReq({ secure: false }))).to.equal(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('isRequestSecure uses strict x-forwarded-proto check', () => {
|
||||||
|
expect(isRequestSecure(mockReq({ xForwardedProto: 'https' }))).to.equal(true)
|
||||||
|
expect(isRequestSecure(mockReq({ xForwardedProto: 'http' }))).to.equal(false)
|
||||||
|
expect(isRequestSecure(mockReq({ xForwardedProto: 'http, https' }))).to.equal(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getRequestProtocol returns https or http', () => {
|
||||||
|
expect(getRequestProtocol(mockReq({ secure: true }))).to.equal('https')
|
||||||
|
expect(getRequestProtocol(mockReq())).to.equal('http')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getRequestOrigin builds origin from protocol and host', () => {
|
||||||
|
expect(getRequestOrigin(mockReq({ secure: true }))).to.deep.equal({
|
||||||
|
protocol: 'https',
|
||||||
|
host: 'books.example.com',
|
||||||
|
origin: 'https://books.example.com'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue