mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-11 09:13:49 -04:00
Fix oidc auto-register not cleaning up new user on errors #4563
This commit is contained in:
parent
99a3867ce9
commit
4018be6330
@ -110,6 +110,8 @@ class OidcAuthStrategy {
|
|||||||
* @param {Function} done - Passport callback
|
* @param {Function} done - Passport callback
|
||||||
*/
|
*/
|
||||||
async verifyCallback(tokenset, userinfo, done) {
|
async verifyCallback(tokenset, userinfo, done) {
|
||||||
|
let isNewUser = false
|
||||||
|
let user = null
|
||||||
try {
|
try {
|
||||||
Logger.debug(`[OidcAuth] openid callback userinfo=`, JSON.stringify(userinfo, null, 2))
|
Logger.debug(`[OidcAuth] openid callback userinfo=`, JSON.stringify(userinfo, null, 2))
|
||||||
|
|
||||||
@ -121,9 +123,24 @@ class OidcAuthStrategy {
|
|||||||
throw new Error(`Group claim ${Database.serverSettings.authOpenIDGroupClaim} not found or empty in userinfo`)
|
throw new Error(`Group claim ${Database.serverSettings.authOpenIDGroupClaim} not found or empty in userinfo`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = await Database.userModel.findOrCreateUserFromOpenIdUserInfo(userinfo)
|
user = await Database.userModel.findUserFromOpenIdUserInfo(userinfo)
|
||||||
|
|
||||||
if (!user?.isActive) {
|
if (user?.error) {
|
||||||
|
throw new Error('Invalid userinfo or already linked')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
// If no existing user was matched, auto-register if configured
|
||||||
|
if (global.ServerSettings.authOpenIDAutoRegister) {
|
||||||
|
Logger.info(`[User] openid: Auto-registering user with sub "${userinfo.sub}"`, userinfo)
|
||||||
|
user = await Database.userModel.createUserFromOpenIdUserInfo(userinfo)
|
||||||
|
isNewUser = true
|
||||||
|
} else {
|
||||||
|
Logger.warn(`[User] openid: User not found and auto-register is disabled`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.isActive) {
|
||||||
throw new Error('User not active or not found')
|
throw new Error('User not active or not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +153,10 @@ class OidcAuthStrategy {
|
|||||||
return done(null, user)
|
return done(null, user)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error(`[OidcAuth] openid callback error: ${error?.message}\n${error?.stack}`)
|
Logger.error(`[OidcAuth] openid callback error: ${error?.message}\n${error?.stack}`)
|
||||||
|
// Remove new user if an error occurs
|
||||||
|
if (isNewUser && user) {
|
||||||
|
await user.destroy()
|
||||||
|
}
|
||||||
return done(null, null, 'Unauthorized')
|
return done(null, null, 'Unauthorized')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,18 +211,18 @@ class User extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds an existing user by OpenID subject identifier, or by email/username based on server settings,
|
* Finds an existing user by OpenID subject identifier, or by email/username based on server settings
|
||||||
* or creates a new user if configured to do so.
|
* Returns null if no user is found
|
||||||
*
|
*
|
||||||
* @param {Object} userinfo
|
* @param {Object} userinfo
|
||||||
* @returns {Promise<User>}
|
* @returns {Promise<User|{error: string}>}
|
||||||
*/
|
*/
|
||||||
static async findOrCreateUserFromOpenIdUserInfo(userinfo) {
|
static async findUserFromOpenIdUserInfo(userinfo) {
|
||||||
let user = await this.getUserByOpenIDSub(userinfo.sub)
|
let user = await this.getUserByOpenIDSub(userinfo.sub)
|
||||||
|
|
||||||
// Matched by sub
|
// Matched by sub
|
||||||
if (user) {
|
if (user) {
|
||||||
Logger.debug(`[User] openid: User found by sub`)
|
Logger.debug(`[User] openid: User found by sub "${userinfo.sub}"`)
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,20 +232,27 @@ class User extends Model {
|
|||||||
// Only disallow when email_verified explicitly set to false (allow both if not set or true)
|
// Only disallow when email_verified explicitly set to false (allow both if not set or true)
|
||||||
if (userinfo.email_verified === false) {
|
if (userinfo.email_verified === false) {
|
||||||
Logger.warn(`[User] openid: User not found and email "${userinfo.email}" is not verified`)
|
Logger.warn(`[User] openid: User not found and email "${userinfo.email}" is not verified`)
|
||||||
return null
|
return {
|
||||||
|
error: 'Email not verified'
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger.info(`[User] openid: User not found, checking existing with email "${userinfo.email}"`)
|
Logger.info(`[User] openid: User not found, checking existing with email "${userinfo.email}"`)
|
||||||
user = await this.getUserByEmail(userinfo.email)
|
user = await this.getUserByEmail(userinfo.email)
|
||||||
|
|
||||||
if (user?.authOpenIDSub) {
|
if (user?.authOpenIDSub) {
|
||||||
Logger.warn(`[User] openid: User found with email "${userinfo.email}" but is already matched with sub "${user.authOpenIDSub}"`)
|
Logger.warn(`[User] openid: User found with email "${userinfo.email}" but is already matched with sub "${user.authOpenIDSub}"`)
|
||||||
return null // User is linked to a different OpenID subject; do not proceed.
|
// User is linked to a different OpenID subject; do not proceed.
|
||||||
|
return {
|
||||||
|
error: 'User already linked to a different OpenID subject'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(`[User] openid: User not found and no email in userinfo`)
|
Logger.warn(`[User] openid: User not found and no email in userinfo`)
|
||||||
// We deny login, because if the admin whishes to match email, it makes sense to require it
|
// We deny login, because if the admin whishes to match email, it makes sense to require it
|
||||||
return null
|
return {
|
||||||
|
error: 'No email in userinfo'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Match existing user by username
|
// Match existing user by username
|
||||||
@ -260,43 +267,40 @@ class User extends Model {
|
|||||||
username = userinfo.username
|
username = userinfo.username
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(`[User] openid: User not found and neither preferred_username nor username in userinfo`)
|
Logger.warn(`[User] openid: User not found and neither preferred_username nor username in userinfo`)
|
||||||
return null
|
return {
|
||||||
|
error: 'No username in userinfo'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
user = await this.getUserByUsername(username)
|
user = await this.getUserByUsername(username)
|
||||||
|
|
||||||
if (user?.authOpenIDSub) {
|
if (user?.authOpenIDSub) {
|
||||||
Logger.warn(`[User] openid: User found with username "${username}" but is already matched with sub "${user.authOpenIDSub}"`)
|
Logger.warn(`[User] openid: User found with username "${username}" but is already matched with sub "${user.authOpenIDSub}"`)
|
||||||
return null // User is linked to a different OpenID subject; do not proceed.
|
// User is linked to a different OpenID subject; do not proceed.
|
||||||
|
return {
|
||||||
|
error: 'User already linked to a different OpenID subject'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
// Found existing user via email or username
|
// Found existing user via email or username
|
||||||
if (user) {
|
if (!user.isActive) {
|
||||||
if (!user.isActive) {
|
Logger.warn(`[User] openid: User found but is not active`)
|
||||||
Logger.warn(`[User] openid: User found but is not active`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update user with OpenID sub
|
|
||||||
if (!user.extraData) user.extraData = {}
|
|
||||||
user.extraData.authOpenIDSub = userinfo.sub
|
|
||||||
user.changed('extraData', true)
|
|
||||||
await user.save()
|
|
||||||
|
|
||||||
Logger.debug(`[User] openid: User found by email/username`)
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no existing user was matched, auto-register if configured
|
// Update user with OpenID sub
|
||||||
if (global.ServerSettings.authOpenIDAutoRegister) {
|
if (!user.extraData) user.extraData = {}
|
||||||
Logger.info(`[User] openid: Auto-registering user with sub "${userinfo.sub}"`, userinfo)
|
user.extraData.authOpenIDSub = userinfo.sub
|
||||||
user = await this.createUserFromOpenIdUserInfo(userinfo)
|
user.changed('extraData', true)
|
||||||
return user
|
await user.save()
|
||||||
}
|
|
||||||
|
|
||||||
Logger.warn(`[User] openid: User not found and auto-register is disabled`)
|
Logger.debug(`[User] openid: User found by email/username`)
|
||||||
return null
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user