audiobookshelf/test/server/auth/OidcAuthStrategy.test.js
Boris Rybalkin d6cfdd3bec Add configurable OIDC group-to-role mapping
Currently OIDC group-based role assignment only recognizes groups named
'admin', 'user', or 'guest' (case-insensitive), and denies login when a
user's groups match none of them. This makes group-based roles unusable
with identity providers whose group names differ, and offers no way to
admit such users with a default role.

Add two optional server settings:
- authOpenIDAdminGroups: comma-separated group names mapped to the admin
  role, in addition to the built-in names.
- authOpenIDGroupDefaultRole: role assigned when no group matches,
  instead of denying login.

Both default to empty, preserving current behavior. Includes the auth
settings UI fields, en-us strings, and unit tests for setUserGroup.
2026-06-06 19:02:17 +01:00

78 lines
2.6 KiB
JavaScript

const { expect } = require('chai')
const sinon = require('sinon')
const Database = require('../../../server/Database')
const Logger = require('../../../server/Logger')
const OidcAuthStrategy = require('../../../server/auth/OidcAuthStrategy')
describe('OidcAuthStrategy', () => {
let strategy
let originalServerSettings
beforeEach(() => {
strategy = new OidcAuthStrategy()
originalServerSettings = Database.serverSettings
sinon.stub(Logger, 'info')
})
afterEach(() => {
Database.serverSettings = originalServerSettings
sinon.restore()
})
const fakeUser = (type) => ({ type, username: 'tester', save: sinon.stub().resolves() })
describe('setUserGroup', () => {
it('maps a configured admin group to the admin role', async () => {
Database.serverSettings = { authOpenIDGroupClaim: 'groups', authOpenIDAdminGroups: 'syncloud', authOpenIDGroupDefaultRole: null }
const user = fakeUser('user')
await strategy.setUserGroup(user, { groups: ['syncloud'] })
expect(user.type).to.equal('admin')
expect(user.save.calledOnce).to.be.true
})
it('still maps built-in role names when admin groups are configured', async () => {
Database.serverSettings = { authOpenIDGroupClaim: 'groups', authOpenIDAdminGroups: 'syncloud', authOpenIDGroupDefaultRole: null }
const user = fakeUser('guest')
await strategy.setUserGroup(user, { groups: ['User'] })
expect(user.type).to.equal('user')
})
it('falls back to the default role when no group matches', async () => {
Database.serverSettings = { authOpenIDGroupClaim: 'groups', authOpenIDAdminGroups: '', authOpenIDGroupDefaultRole: 'user' }
const user = fakeUser('guest')
await strategy.setUserGroup(user, { groups: ['some-unrelated-group'] })
expect(user.type).to.equal('user')
})
it('denies login when no group matches and no default role is set', async () => {
Database.serverSettings = { authOpenIDGroupClaim: 'groups', authOpenIDAdminGroups: '', authOpenIDGroupDefaultRole: null }
const user = fakeUser('user')
let error
try {
await strategy.setUserGroup(user, { groups: ['some-unrelated-group'] })
} catch (e) {
error = e
}
expect(error).to.be.an('error')
})
it('does nothing when no group claim is configured', async () => {
Database.serverSettings = { authOpenIDGroupClaim: '' }
const user = fakeUser('user')
await strategy.setUserGroup(user, { groups: ['syncloud'] })
expect(user.type).to.equal('user')
expect(user.save.called).to.be.false
})
})
})