mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-09-01 13:51:27 +02:00
Update passport init with saved settings & check if OIDC is configured
This commit is contained in:
parent
adae905953
commit
9e913b5e17
@ -1,7 +1,7 @@
|
||||
const bcrypt = require('bcryptjs')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const passport = require('passport')
|
||||
const Logger = require('./Logger')
|
||||
const User = require('./objects/User')
|
||||
|
||||
class Auth {
|
||||
constructor(db) {
|
||||
@ -49,7 +49,7 @@ class Auth {
|
||||
}
|
||||
|
||||
req.user = user
|
||||
|
||||
|
||||
return next();
|
||||
}
|
||||
|
||||
@ -210,5 +210,34 @@ class Auth {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async handleOIDCVerification(issuer, profile, cb) {
|
||||
Logger.debug(`[Auth] handleOIDCVerification ${issuer}`)
|
||||
|
||||
let user = this.db.users.find(u => u.id === profile.id)
|
||||
if (!user && this.db.SSOSettings.createNewUser) {
|
||||
// create a user
|
||||
let account = {}
|
||||
account.id = profile.id
|
||||
account.username = profile.username
|
||||
account.isActive = true
|
||||
account.type = "guest"
|
||||
account.permissions = this.db.SSOSettings.getNewUserPermissions()
|
||||
account.pash = await this.hashPass(getId(profile.id))
|
||||
account.token = await this.generateAccessToken({ userId: account.id })
|
||||
account.createdAt = Date.now()
|
||||
user = new User(account)
|
||||
const success = await this.db.insertEntity('user', user)
|
||||
if (!success) {
|
||||
cb('Failed to save new user')
|
||||
}
|
||||
}
|
||||
if (!user || !user.isActive) {
|
||||
Logger.debug(`[Auth] Failed login attempt`)
|
||||
cb("Invalid user or password")
|
||||
return
|
||||
}
|
||||
cb(null, user)
|
||||
}
|
||||
}
|
||||
module.exports = Auth
|
@ -7,8 +7,8 @@ const SocketIO = require('socket.io')
|
||||
const fs = require('fs-extra')
|
||||
const fileUpload = require('express-fileupload')
|
||||
const rateLimit = require('express-rate-limit')
|
||||
const passport = require('passport');
|
||||
const OidcStrategy = require('passport-openidconnect').Strategy;
|
||||
const passport = require('passport')
|
||||
const OidcStrategy = require('passport-openidconnect').Strategy
|
||||
|
||||
const { version } = require('../package.json')
|
||||
|
||||
@ -32,7 +32,6 @@ const RssFeeds = require('./RssFeeds')
|
||||
const DownloadManager = require('./DownloadManager')
|
||||
const CoverController = require('./CoverController')
|
||||
const CacheManager = require('./CacheManager')
|
||||
const User = require('./objects/User')
|
||||
|
||||
class Server {
|
||||
constructor(PORT, UID, GID, CONFIG_PATH, METADATA_PATH, AUDIOBOOK_PATH) {
|
||||
@ -44,10 +43,6 @@ class Server {
|
||||
this.AudiobookPath = Path.normalize(AUDIOBOOK_PATH)
|
||||
this.MetadataPath = Path.normalize(METADATA_PATH)
|
||||
|
||||
console.info(this.ConfigPath)
|
||||
console.info(this.MetadataPath)
|
||||
console.info(this.AudiobookPath)
|
||||
|
||||
fs.ensureDirSync(CONFIG_PATH, 0o774)
|
||||
fs.ensureDirSync(METADATA_PATH, 0o774)
|
||||
fs.ensureDirSync(AUDIOBOOK_PATH, 0o774)
|
||||
@ -74,54 +69,6 @@ class Server {
|
||||
this.io = null
|
||||
|
||||
this.clients = {}
|
||||
passport.serializeUser((user, next) => {
|
||||
next(null, user);
|
||||
});
|
||||
|
||||
passport.deserializeUser((obj, next) => {
|
||||
next(null, obj);
|
||||
});
|
||||
passport.use(new OidcStrategy({
|
||||
issuer: process.env.OIDC_ISSUER,
|
||||
authorizationURL: process.env.OIDC_AUTHORIZATION_URL,
|
||||
tokenURL: process.env.OIDC_TOKEN_URL,
|
||||
userInfoURL: process.env.OIDC_USER_INFO_URL,
|
||||
clientID: process.env.OIDC_CLIENT_ID,
|
||||
clientSecret: process.env.OIDC_CLIENT_SECRET,
|
||||
callbackURL: '/oidc/callback',
|
||||
scope: "openid email profile"
|
||||
}, async (issuer, profile, cb) => {
|
||||
let user = this.db.users.find(u => u.id === profile.id)
|
||||
if (!user) {
|
||||
// create a user
|
||||
let account = {}
|
||||
account.id = profile.id
|
||||
account.username = profile.username
|
||||
account.type = "guest"
|
||||
account.permissions = {
|
||||
download: false,
|
||||
update: false,
|
||||
delete: false,
|
||||
upload: false,
|
||||
accessAllLibraries: false
|
||||
}
|
||||
account.pash = await this.auth.hashPass(getId(profile.id))
|
||||
account.token = await this.auth.generateAccessToken({ userId: account.id })
|
||||
account.createdAt = Date.now()
|
||||
user = new User(account)
|
||||
const success = await this.db.insertEntity('user', user)
|
||||
if (!success) {
|
||||
cb('Failed to save new user')
|
||||
}
|
||||
}
|
||||
if (!user || !user.isActive) {
|
||||
Logger.debug(`[Auth] Failed login attempt`)
|
||||
cb("Invalid user or password")
|
||||
return
|
||||
}
|
||||
cb(null, user)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
get audiobooks() {
|
||||
@ -186,6 +133,26 @@ class Server {
|
||||
|
||||
this.watcher.initWatcher(this.libraries)
|
||||
this.watcher.on('files', this.filesChanged.bind(this))
|
||||
|
||||
this.passportInit()
|
||||
}
|
||||
|
||||
passportInit() {
|
||||
if (this.db.SSOSettings.isOIDCConfigured) {
|
||||
Logger.debug(`[Server] passportInit OIDC is configured - init`)
|
||||
|
||||
passport.serializeUser((user, next) => {
|
||||
next(null, user);
|
||||
})
|
||||
passport.deserializeUser((obj, next) => {
|
||||
next(null, obj);
|
||||
})
|
||||
|
||||
// Initialize passport OIDC verification
|
||||
passport.use(new OidcStrategy(this.db.SSOSettings.getOIDCSettings(), this.auth.handleOIDCVerification))
|
||||
} else {
|
||||
Logger.debug(`[Server] passportInit OIDC not configured`)
|
||||
}
|
||||
}
|
||||
|
||||
async start() {
|
||||
@ -218,7 +185,7 @@ class Server {
|
||||
token = authHeader && authHeader.split(' ')[1]
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Static path to generated nuxt
|
||||
const distPath = Path.join(global.appRoot, '/client/dist')
|
||||
app.use(express.static(distPath))
|
||||
@ -295,10 +262,10 @@ class Server {
|
||||
|
||||
app.get("/oidc/login", passport.authenticate('openidconnect'))
|
||||
|
||||
app.get("/oidc/callback",
|
||||
app.get("/oidc/callback",
|
||||
passport.authenticate('openidconnect', { failureRedirect: '/oidc/login', failureMessage: true }),
|
||||
async (req, res) => {
|
||||
const token = this.auth.generateAccessToken({userId: req.user.id})
|
||||
const token = this.auth.generateAccessToken({ userId: req.user.id })
|
||||
res.cookie('token', token, { httpOnly: true /* TODO: Set secure: true */ });
|
||||
res.cookie('sso', true, { httpOnly: false /* TODO: Set secure: true */ });
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
const { CoverDestination, BookCoverAspectRatio, BookshelfView } = require('../utils/constants')
|
||||
const Logger = require('../Logger')
|
||||
const User = require('./User')
|
||||
const { isObject } = require('../utils')
|
||||
|
||||
const defaultSettings = {
|
||||
oidc: {
|
||||
@ -13,57 +13,61 @@ const defaultSettings = {
|
||||
callbackURL: "/oidc/callback",
|
||||
scope: "openid email profile"
|
||||
},
|
||||
user: {
|
||||
createNewUser: false,
|
||||
isActive: true,
|
||||
userSettings: {
|
||||
mobileOrderBy: 'recent',
|
||||
mobileOrderDesc: true,
|
||||
mobileFilterBy: 'all',
|
||||
orderBy: 'book.title',
|
||||
orderDesc: false,
|
||||
filterBy: 'all',
|
||||
playbackRate: 1,
|
||||
bookshelfCoverSize: 120,
|
||||
collapseSeries: false
|
||||
},
|
||||
permissions: {
|
||||
download: false,
|
||||
update: false,
|
||||
delete: false,
|
||||
upload: false,
|
||||
accessAllLibraries: false
|
||||
}
|
||||
}
|
||||
createNewUser: false,
|
||||
userPermissions: User.getDefaultUserPermissions('guest')
|
||||
}
|
||||
|
||||
class SSOSettings {
|
||||
constructor(settings = defaultSettings) {
|
||||
this.id = 'sso-settings'
|
||||
this.oidc = { ...settings.oidc }
|
||||
this.user = { ...settings.user }
|
||||
this.createNewUser = !!settings.createNewUser
|
||||
this.userPermissions = { ...settings.userPermissions }
|
||||
}
|
||||
|
||||
get isOIDCConfigured() {
|
||||
// Check required OIDC settings are set
|
||||
return !['issue', 'authorizationURL', 'tokenURL', 'clientID', 'clientSecret'].some(key => !this.oidc[key])
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
oidc: { ...this.oidc },
|
||||
user: { ...this.user }
|
||||
createNewUser: this.createNewUser,
|
||||
userPermissions: { ...this.userPermissions }
|
||||
}
|
||||
}
|
||||
|
||||
update(payload) {
|
||||
let hasUpdates = false
|
||||
for (const key in payload) {
|
||||
for (const setting in payload) {
|
||||
if (!this[key] || this[key][setting] === payload[key][setting]) {
|
||||
continue
|
||||
if (isObject(payload[key])) {
|
||||
for (const setting in payload[key]) {
|
||||
if (!this[key] || this[key][setting] === payload[key][setting]) {
|
||||
continue
|
||||
}
|
||||
this[key][setting] = payload[key][setting]
|
||||
hasUpdates = true
|
||||
}
|
||||
this[key][setting] = payload[key][setting]
|
||||
} else if (this[key] !== undefined && this[key] !== payload[key]) {
|
||||
this[key] = payload[key]
|
||||
hasUpdates = true
|
||||
}
|
||||
}
|
||||
return hasUpdates
|
||||
}
|
||||
|
||||
getNewUserPermissions() {
|
||||
return {
|
||||
...this.userPermissions
|
||||
}
|
||||
}
|
||||
|
||||
getOIDCSettings() {
|
||||
return {
|
||||
...this.oidc
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = SSOSettings
|
@ -46,7 +46,7 @@ class User {
|
||||
return !!this.pash && !!this.pash.length
|
||||
}
|
||||
|
||||
getDefaultUserSettings() {
|
||||
static getDefaultUserSettings() {
|
||||
return {
|
||||
mobileOrderBy: 'recent',
|
||||
mobileOrderDesc: true,
|
||||
@ -60,12 +60,12 @@ class User {
|
||||
}
|
||||
}
|
||||
|
||||
getDefaultUserPermissions() {
|
||||
static getDefaultUserPermissions(type) {
|
||||
return {
|
||||
download: true,
|
||||
update: true,
|
||||
delete: this.type === 'root',
|
||||
upload: this.type === 'root' || this.type === 'admin',
|
||||
download: type !== 'guest',
|
||||
update: type !== 'guest',
|
||||
delete: type === 'root',
|
||||
upload: type === 'root' || type === 'admin',
|
||||
accessAllLibraries: true
|
||||
}
|
||||
}
|
||||
@ -152,8 +152,8 @@ class User {
|
||||
this.isLocked = user.type === 'root' ? false : !!user.isLocked
|
||||
this.lastSeen = user.lastSeen || null
|
||||
this.createdAt = user.createdAt || Date.now()
|
||||
this.settings = user.settings || this.getDefaultUserSettings()
|
||||
this.permissions = user.permissions || this.getDefaultUserPermissions()
|
||||
this.settings = user.settings || User.getDefaultUserSettings()
|
||||
this.permissions = user.permissions || User.getDefaultUserPermissions(this.type)
|
||||
// Upload permission added v1.1.13, make sure root user has upload permissions
|
||||
if (this.type === 'root' && !this.permissions.upload) this.permissions.upload = true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user