feat(oidc): enhance SSO target app resolution and audit logging
- Updated targetAppFromReturnTo function to handle OIDC authorization unwrap and added search parameter processing. - Integrated target app resolution into the OIDC route for improved audit logging of SSO handoffs. - Added a test case to verify the logging of the target app during the authorization process. - Updated documentation to reflect changes in audit logging for the Technitium DNS application. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
36c4091dbf
commit
4ce05a6669
5 files changed
+123
-1
No files matched your search
@@ -1,19 +1,32 @@
|
||||
import type { AuditSourceApp } from '@authportal/shared'
|
||||
|
||||
/** Resolve SSO target app from return_to URL host/path. */
|
||||
/** 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 host = ''
|
||||
let path = ''
|
||||
let search = ''
|
||||
try {
|
||||
const u = new URL(returnTo)
|
||||
host = u.hostname.toLowerCase()
|
||||
path = u.pathname.toLowerCase()
|
||||
search = u.search
|
||||
} catch {
|
||||
return 'portal'
|
||||
}
|
||||
|
||||
// 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 (
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
normalizePermissionKeys,
|
||||
} from '@authportal/shared'
|
||||
import { oidcIssuerFromConfig } from '../config.js'
|
||||
import { clientIp, safeAudit } from '../lib/audit.js'
|
||||
import {
|
||||
buildJwks,
|
||||
buildOidcDiscovery,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
signOidcJwt,
|
||||
verifyOidcAccessToken,
|
||||
} from '../lib/oidc/keys.js'
|
||||
import { clientUserAgent, targetAppFromReturnTo } from '../lib/target-app.js'
|
||||
|
||||
const REFRESH_COOKIE = 'refresh_token'
|
||||
const CODE_TTL_MS = 5 * 60 * 1000
|
||||
@@ -266,6 +268,27 @@ export async function oidcRoutes(app: FastifyInstance): Promise<void> {
|
||||
expiresAt: new Date(Date.now() + CODE_TTL_MS),
|
||||
})
|
||||
|
||||
const targetApp = targetAppFromReturnTo(redirectUri)
|
||||
safeAudit(app, {
|
||||
action: 'auth.sso_handoff',
|
||||
severity: 'info',
|
||||
actorUserId: user.id,
|
||||
actorEmail: user.email,
|
||||
actorName: user.name,
|
||||
targetType: 'session',
|
||||
targetId: user.id,
|
||||
summary: `SSO OIDC: ${user.email} → ${targetApp}`,
|
||||
details: {
|
||||
return_to: redirectUri,
|
||||
target_app: targetApp,
|
||||
user_agent: clientUserAgent(request.headers),
|
||||
oidc_client_id: client.clientId,
|
||||
oidc_client_name: client.name,
|
||||
auth_mode: 'oidc',
|
||||
},
|
||||
ip: clientIp(request),
|
||||
})
|
||||
|
||||
const dest = new URL(redirectUri)
|
||||
dest.searchParams.set('code', rawCode)
|
||||
if (state) dest.searchParams.set('state', state)
|
||||
|
||||
Reference in new issue
Block a user