Files
website/server/test/registry.test.js
wtclaude 5e398d8acd feat(auth): sign in with Steam (MODULE_API 1.17.0)
Steam is a built-in provider beside Google and Discord (STEAM_SIGNIN.md,
D392-D396). OpenID 2.0: the assertion is verified server to server with
check_authentication, return_to must match byte for byte, and the claimed id
must be a 17-digit SteamID64. A Steam Web API key is required to enable it
(D394); persona name and avatar are stored on the identity and refreshed at
each sign-in, and a failed lookup never blocks one. Steam never signs anybody
up (D395), on the web or the mobile bridge. Several Steam accounts may be
linked; DELETE /auth/me/account/identities/:provider takes ?id= to unlink one.

MODULE_API 1.17.0: ctx.identities.list, api.onIdentityLinking (refuse-only,
fails closed, module text never shown) and api.onIdentityLinked. No unlink
hook (D393). Schema additive; OpenAPI, routes and engagement manifests
regenerated with no modules installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-19 14:02:49 -05:00

54 lines
2.7 KiB
JavaScript

process.env.JWT_SECRET = process.env.JWT_SECRET || 'test-secret'
process.env.SECRET_ENC_KEY = process.env.SECRET_ENC_KEY || 'unit-test-enc-key'
process.env.DB_HOST = '127.0.0.1'
process.env.DB_PORT = '59999'
const { test, after } = require('node:test')
const assert = require('node:assert/strict')
const registry = require('../src/auth/providers/registry')
const authProvidersModel = require('../src/model/authProviders/authProviders.model')
const db = require('../src/utils/db')
after(() => db.close())
test('validateConfig: built-in needs client_id + secret', () => {
assert.equal(registry.validateConfig({ kind: 'google', client_id: 'x', client_secret_enc: 'e' }).valid, true)
assert.deepEqual(registry.validateConfig({ kind: 'google', client_id: 'x' }).missing, ['client_secret'])
assert.deepEqual(registry.validateConfig({ kind: 'google' }).missing, ['client_id', 'client_secret'])
})
test('validateConfig: custom OIDC also needs the endpoint URLs', () => {
const complete = {
kind: 'oidc', client_id: 'x', client_secret_enc: 'e',
authorize_url: 'a', token_url: 't', userinfo_url: 'u',
}
assert.equal(registry.validateConfig(complete).valid, true)
const noUrls = { kind: 'oidc', client_id: 'x', client_secret_enc: 'e' }
assert.deepEqual(registry.validateConfig(noUrls).missing, ['authorize_url', 'token_url', 'userinfo_url'])
})
test('listConfigured always includes every built-in with health', async () => {
authProvidersModel.list = async () => [] // no rows yet
const out = await registry.listConfigured()
const ids = out.map((p) => p.id)
assert.deepEqual(ids, ['google', 'discord', 'steam'])
assert.equal(out[0].builtin, true)
assert.equal(out[0].enabled, 0)
assert.equal(out[0].health.valid, false) // unconfigured
})
test('listEnabledValid returns only enabled+valid, shaped and sorted by priority', async () => {
authProvidersModel.list = async () => [
{ id: 'discord', kind: 'discord', name: 'Discord', enabled: 1, client_id: 'd', client_secret_enc: 'e', priority: 2 },
{ id: 'google', kind: 'google', name: 'Google', enabled: 1, client_id: 'g', client_secret_enc: 'e', priority: 1 },
{ id: 'brokenidp', kind: 'oidc', name: 'Broken', enabled: 1, client_id: 'x', client_secret_enc: 'e', priority: 0 }, // missing URLs → hidden
{ id: 'authentik', kind: 'oidc', name: 'Authentik', enabled: 0, client_id: 'x', client_secret_enc: 'e', authorize_url: 'a', token_url: 't', userinfo_url: 'u', priority: 3 }, // disabled → hidden
]
const out = await registry.listEnabledValid()
assert.deepEqual(out.map((p) => p.id), ['google', 'discord']) // sorted by priority, broken/disabled excluded
assert.deepEqual(out[0], {
id: 'google', name: 'Google', icon: 'google', loginUrl: '/api/v1/auth/sso/google/start', priority: 1,
})
})