host-context.js (2025B)
1 import { HttpError } from './http/http-error.js'; 2 import { isVirtualClient } from './oidc/clients.js'; 3 import { findClientRealm, findOidcClientHost, findRealmHost, normalizeHost } from './realm.js'; 4 5 export async function resolveHostContext(req, { publicUrl } = {}) { 6 const host = normalizeHost(req.headers.host); 7 8 const clientHost = await findOidcClientHost(host); 9 if (clientHost) { 10 return { 11 mode: 'client', 12 host, 13 realm: { 14 id: clientHost.realm_id, 15 slug: clientHost.slug, 16 db_file: clientHost.db_file, 17 owner_user_id: clientHost.owner_user_id, 18 }, 19 clientId: clientHost.client_id, 20 }; 21 } 22 23 const realmHost = await findRealmHost(host); 24 if (realmHost) { 25 return { mode: 'realm', host, realm: realmHost }; 26 } 27 28 if (publicUrl) { 29 const canonicalHost = normalizeHost(new URL(publicUrl).host); 30 if (host === canonicalHost) return { mode: 'canonical', host }; 31 } 32 33 throw new HttpError(404, 'not_found', 'Not found'); 34 } 35 36 export async function resolveClientForHost(context, clientId) { 37 const value = String(clientId || '').trim(); 38 if (!value) throw new HttpError(400, 'invalid_request', 'client_id is required'); 39 40 if (context.mode === 'client') { 41 if (value !== context.clientId) { 42 throw new HttpError(404, 'unknown_client', 'Unknown client'); 43 } 44 return { realm: context.realm, clientId: context.clientId }; 45 } 46 47 if (context.mode === 'realm' && isVirtualClient(value)) { 48 return { realm: context.realm, clientId: value }; 49 } 50 51 const mapping = await findClientRealm(value); 52 if (!mapping || !mapping.realm_id) { 53 throw new HttpError(404, 'unknown_client', 'Unknown client'); 54 } 55 if (context.mode === 'realm' && mapping.realm_id !== context.realm.id) { 56 throw new HttpError(404, 'unknown_client', 'Unknown client'); 57 } 58 59 return { 60 realm: { 61 id: mapping.realm_id, 62 slug: mapping.slug, 63 db_file: mapping.db_file, 64 owner_user_id: mapping.owner_user_id, 65 }, 66 clientId: value, 67 }; 68 }