- jose v6 не экспортирует KeyLike → CryptoKey - SimpleWebAuthn v13 требует Uint8Array<ArrayBuffer> - targetType 'credential' в AUDIT_TARGET_TYPES (писался в аудит passkey-ов) - target-app: начальные значения host/path/search никогда не читались
76 lines
1.8 KiB
TypeScript
76 lines
1.8 KiB
TypeScript
import type { AuditSourceApp } from '@authportal/shared'
|
|
|
|
/** Resolve SSO target app from return_to URL host/path (and OIDC authorize unwrap). */
|
|
export function targetAppFromReturnTo(
|
|
returnTo: string | undefined | null,
|
|
): AuditSourceApp {
|
|
if (!returnTo) return 'portal'
|
|
let u: URL
|
|
try {
|
|
u = new URL(returnTo)
|
|
} catch {
|
|
return 'portal'
|
|
}
|
|
const host = u.hostname.toLowerCase()
|
|
const path = u.pathname.toLowerCase()
|
|
const search = u.search
|
|
|
|
// Portal OIDC authorize as return_to → map via client's redirect_uri
|
|
if (path === '/oauth/authorize' || path.endsWith('/oauth/authorize')) {
|
|
try {
|
|
const redirectUri = new URLSearchParams(search).get('redirect_uri')
|
|
if (redirectUri) return targetAppFromReturnTo(redirectUri)
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
const hay = `${host} ${path}`
|
|
if (/\bvps\b/.test(hay) || host.includes('vps')) return 'vps'
|
|
if (
|
|
/\bcfdm\b/.test(hay) ||
|
|
host.includes('cfdm') ||
|
|
host.includes('domain')
|
|
) {
|
|
return 'cfdm'
|
|
}
|
|
if (/\bbgp\b/.test(hay) || host.includes('bgp')) return 'bgp'
|
|
if (
|
|
/\bfw\b/.test(hay) ||
|
|
host.includes('firewall') ||
|
|
host.includes('evofw')
|
|
) {
|
|
return 'fw'
|
|
}
|
|
if (
|
|
/\bdns\b/.test(hay) ||
|
|
host.includes('technitium') ||
|
|
path.includes('/sso/')
|
|
) {
|
|
return 'dns'
|
|
}
|
|
if (
|
|
/\bcdn\b/.test(hay) ||
|
|
host.includes('cdnmanager') ||
|
|
host.includes('cdn-manager')
|
|
) {
|
|
return 'cdn'
|
|
}
|
|
if (
|
|
/\bmm\b/.test(hay) ||
|
|
host.includes('mikrotik') ||
|
|
host.includes('mmapp')
|
|
) {
|
|
return 'mm'
|
|
}
|
|
return 'portal'
|
|
}
|
|
|
|
export function clientUserAgent(
|
|
headers: Record<string, string | string[] | undefined>,
|
|
): string | null {
|
|
const ua = headers['user-agent']
|
|
if (typeof ua === 'string' && ua.trim()) return ua.trim().slice(0, 512)
|
|
return null
|
|
}
|