allow proxy login on the socket

This commit is contained in:
Igor Serebryany 2023-10-06 16:33:48 -07:00
parent 63f1df4015
commit 74e3560153
No known key found for this signature in database
GPG key ID: 0AF607692FD9EB24
2 changed files with 43 additions and 30 deletions

View file

@ -47,6 +47,7 @@ class Auth {
async authMiddleware(req, res, next) { async authMiddleware(req, res, next) {
var token = null var token = null
var proxyAccount = this.getProxyAccount(req.headers)
// If using a get request, the token can be passed as a query string // If using a get request, the token can be passed as a query string
if (req.method === 'GET' && req.query && req.query.token) { if (req.method === 'GET' && req.query && req.query.token) {
@ -56,13 +57,7 @@ class Auth {
token = authHeader && authHeader.split(' ')[1] token = authHeader && authHeader.split(' ')[1]
} }
let proxyUsername = null if (token == null && !(proxyAccount && proxyAccount['username'])) {
if (Database.serverSettings.proxyAuthEnabled) {
const uHeader = Database.serverSettings.proxyAuthUsernameHeader.toLowerCase()
proxyUsername = uHeader ? req.headers[uHeader] : null
}
if (token == null && proxyUsername == null) {
Logger.error('Api called without a token and no proxy auth provided', req.path) Logger.error('Api called without a token and no proxy auth provided', req.path)
return res.sendStatus(401) return res.sendStatus(401)
} }
@ -76,11 +71,8 @@ class Auth {
} }
user.isFromProxy = false user.isFromProxy = false
} else if (proxyUsername) { } else if (proxyAccount) {
const eHeader = Database.serverSettings.proxyAuthEmailHeader.toLowerCase() user = await this.getProxyUser(proxyAccount)
const proxyEmail = eHeader ? req.headers[eHeader] : null
user = await this.getProxyUser(proxyUsername, proxyEmail)
if (!user) { if (!user) {
Logger.error('Cannot get user from proxy headers', proxyUsername) Logger.error('Cannot get user from proxy headers', proxyUsername)
return res.sendStatus(401) return res.sendStatus(401)
@ -121,8 +113,20 @@ class Auth {
return jwt.sign(payload, Database.serverSettings.tokenSecret) return jwt.sign(payload, Database.serverSettings.tokenSecret)
} }
authenticateUser(token) { async authenticateUser(token, headers) {
return this.verifyToken(token) const tokenUser = token ? await this.verifyToken(token) : null
if (tokenUser) return tokenUser
const proxyAccount = this.getProxyAccount(headers)
if (proxyAccount && proxyAccount.username) {
const proxyUser = await this.getProxyUser(proxyAccount)
if (proxyUser) {
proxyUser.isFromProxy = true;
return proxyUser;
}
}
return null
} }
verifyToken(token) { verifyToken(token) {
@ -143,19 +147,28 @@ class Auth {
}) })
} }
async getProxyUser(username, email) { getProxyAccount(headers) {
const user = await Database.userModel.getUserByUsername(username) if (!Database.serverSettings.proxyAuthEnabled) return null
if (user) {
return user
}
if (!email) { const uHeader = Database.serverSettings.proxyAuthUsernameHeader.toLowerCase()
return null const eHeader = Database.serverSettings.proxyAuthEmailHeader.toLowerCase()
}
const account = { return {
username, username: uHeader ? headers[uHeader] : null,
email, email: eHeader ? headers[eHeader] : null,
}
}
async getProxyUser(account) {
const user = await Database.userModel.getUserByUsername(account.username)
if (user) return user;
// we need an email to create accounts
if (!account.email) return null;
// add some fields for proxy users
account = {
...account,
type: 'user', type: 'user',
isActive: true, isActive: true,
} }

View file

@ -147,7 +147,7 @@ class SocketAuthority {
// When setting up a socket connection the user needs to be associated with a socket id // When setting up a socket connection the user needs to be associated with a socket id
// for this the client will send a 'auth' event that includes the users API token // for this the client will send a 'auth' event that includes the users API token
async authenticateSocket(socket, token) { async authenticateSocket(socket, token) {
const user = await this.Server.auth.authenticateUser(token) const user = await this.Server.auth.authenticateUser(token, socket.handshake.headers)
if (!user) { if (!user) {
Logger.error('Cannot validate socket - invalid token') Logger.error('Cannot validate socket - invalid token')
return socket.emit('invalid_token') return socket.emit('invalid_token')
@ -169,7 +169,7 @@ class SocketAuthority {
return return
} }
Logger.debug(`[SocketAuthority] User Online ${client.user.username}`) Logger.debug(`[SocketAuthority] User Online ${client.user.username} (FromProxy: ${user.isFromProxy})`)
this.adminEmitter('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions)) this.adminEmitter('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions))