Separate related domains (ROR) from the in-domain sign-in allow-list
RealmConfig.origins is again purely an allow-list of sign-in sites within the realm's domain (unset = rp-id and all subdomains), restoring the restriction semantics the realm rework had silently turned into an always-open subtree. Cross-domain ROR origins move to their own RealmConfig.related_origins field — always additive, capped, validated to be outside the rp-id domain, and the sole source of the /.well-known/webauthn document. Admin API POST/PATCH accept related_origins; misfiled entries are rejected (cross-domain in origins, in-domain in related_origins). Admin UI: the realm dialog edits the two lists separately with end-user-oriented explanations (allowed sign-in sites vs. related domains + the well-known note); the Realms section intro explains the multi-domain model, and the table shows sign-in site and related domain counts.
This commit is contained in:
@@ -483,6 +483,8 @@ function createRealm() {
|
||||
auth_host: '',
|
||||
origins: [],
|
||||
originValidation: [],
|
||||
related_origins: [],
|
||||
relatedValidation: [],
|
||||
authHostValidation: null,
|
||||
})
|
||||
}
|
||||
@@ -490,6 +492,7 @@ function createRealm() {
|
||||
function openRealm(realm) {
|
||||
// Strip https:// scheme from stored origins and auth_host for editing
|
||||
const origins = (realm.origins || []).map(o => o.replace(/^https:\/\//, ''))
|
||||
const related = (realm.related_origins || []).map(o => o.replace(/^https:\/\//, ''))
|
||||
openDialog('realm-edit', {
|
||||
isNew: false,
|
||||
rp_id: realm.rp_id,
|
||||
@@ -497,6 +500,8 @@ function openRealm(realm) {
|
||||
auth_host: (realm.auth_host || '').replace(/^https:\/\//, ''),
|
||||
origins,
|
||||
originValidation: origins.map(() => null),
|
||||
related_origins: related,
|
||||
relatedValidation: related.map(() => null),
|
||||
authHostValidation: null,
|
||||
})
|
||||
}
|
||||
@@ -936,18 +941,21 @@ async function submitDialog() {
|
||||
} else if (t === 'realm-edit') {
|
||||
const d = dialog.value.data
|
||||
const rp_id = d.rp_id?.trim().toLowerCase()
|
||||
if (!rp_id) throw new Error('RP ID (domain) required')
|
||||
if (!rp_id) throw new Error('Domain (rp-id) required')
|
||||
const rp_name = d.rp_name?.trim() || ''
|
||||
const auth_host = d.auth_host?.trim() || ''
|
||||
// Origins are stored as-is (hostnames); backend normalizes with https://
|
||||
const origins = (d.origins || [])
|
||||
.map(o => o.trim())
|
||||
.filter(o => o)
|
||||
const related_origins = (d.related_origins || [])
|
||||
.map(o => o.trim())
|
||||
.filter(o => o)
|
||||
|
||||
closeDialog()
|
||||
const req = d.isNew
|
||||
? apiJson('/auth/api/admin/realms/', { method: 'POST', body: { rp_id, rp_name, auth_host, origins } })
|
||||
: apiJson(`/auth/api/admin/realms/${rp_id}`, { method: 'PATCH', body: { rp_name, auth_host, origins } })
|
||||
? apiJson('/auth/api/admin/realms/', { method: 'POST', body: { rp_id, rp_name, auth_host, origins, related_origins } })
|
||||
: apiJson(`/auth/api/admin/realms/${rp_id}`, { method: 'PATCH', body: { rp_name, auth_host, origins, related_origins } })
|
||||
req
|
||||
.then(() => {
|
||||
authStore.showMessage(`Realm "${rp_id}" ${d.isNew ? 'created' : 'updated'}.`, 'success', 2500)
|
||||
|
||||
Reference in New Issue
Block a user