InResponseTo validation for SAML
Better Auth can enable InResponseTo validation for SP-initiated SAML flows (opt-in for backward compatibility). When enabled, the plugin tracks AuthnRequest IDs and validates the InResponseTo attribute in SAML responses. This prevents unsolicited responses, replay attacks, and cross-provider injection.
InResponseTo validation configuration options
SAML InResponseTo validation configuration options: enableInResponseToValidation (boolean, default true, enables InResponseTo validation), allowIdpInitiated (boolean, default true, allow IdP-initiated SSO responses without InResponseTo; set to false for stricter security), requestTTL (number in milliseconds, default 300000 or 5 minutes, time-to-live for AuthnRequest records).
InResponseTo validation error handling
When InResponseTo validation fails, users are redirected with error query parameters: `?error=invalid_saml_response&error_description=Unknown+or+expired+request+ID` (request ID not found or expired), `?error=invalid_saml_response&error_description=Provider+mismatch` (response meant for different provider), `?error=unsolicited_response&error_description=IdP-initiated+SSO+not+allowed` (IdP-initiated SSO disabled).
SAML assertion replay protection
Better Auth includes SAML assertion replay protection that is always enabled as a critical security feature. Each SAML Assertion ID is tracked and rejected if reused. When a SAML response is received, the Assertion ID is extracted, checked if previously seen, and stored in the database until its NotOnOrAfter expiration. Both `/sso/saml2/callback/:providerId` and `/sso/saml2/sp/acs/:providerId` endpoints are protected. Replay protection uses the database, so it works correctly in multi-instance deployments.
Replay attack detection error handling
When a SAML replay attack is detected, users are redirected with error: `?error=replay_detected&error_description=SAML+assertion+has+already+been+used`
SAML timestamp validation with clock skew
Better Auth validates SAML assertion timestamps (NotBefore and NotOnOrAfter) to prevent acceptance of expired or future-dated assertions. Validation includes a configurable clock skew tolerance for time differences between servers. For each SAML assertion: NotBefore validation rejects if current time is before (NotBefore - clockSkew), NotOnOrAfter validation rejects if current time is after (NotOnOrAfter + clockSkew).
SAML 2.0 Core vs SAML2Int timestamp requirements
According to SAML 2.0 Core spec, NotBefore and NotOnOrAfter attributes are optional. However, SAML2Int (SAML V2.0 Implementation Profile for Federation Interoperability), the widely-adopted spec, requires these timestamps. Better Auth provides flexibility: default behavior accepts assertions without timestamps (SAML 2.0 Core compliant) but logs a warning; strict mode can reject assertions without timestamps (SAML2Int compliant) via requireTimestamps configuration.
SAML timestamp validation configuration
Configuration options for SAML timestamp validation: clockSkew (number in milliseconds, default 300000 or 5 minutes, clock skew tolerance), requireTimestamps (boolean, default false; when true, assertions without NotBefore/NotOnOrAfter conditions are rejected; when false, they are accepted but a warning is logged).
When to enable SAML requireTimestamps
Enable `requireTimestamps: true` when: your IdP follows SAML2Int (most enterprise IdPs like Okta, Azure AD, OneLogin), you need SOC 2, ISO 27001, or similar compliance, you want to prevent acceptance of malformed or test assertions, or you're in a production environment with proper IdP configuration. Keep `requireTimestamps: false` when integrating with legacy IdPs that may not include timestamps, during development/testing with mock IdPs, or when you need maximum compatibility.
SAML timestamp validation error messages
SAML timestamp validation error messages: 'SAML assertion is not yet valid' (current time is before NotBefore minus clock skew), 'SAML assertion has expired' (current time is after NotOnOrAfter plus clock skew), 'SAML assertion missing required timestamp conditions' (assertion has no timestamps and requireTimestamps is enabled).
SAML algorithm validation configuration
Better Auth validates SAML cryptographic algorithms and can warn about or reject deprecated ones (SHA-1, RSA 1.5, 3DES). Configuration: `saml: { algorithms: { onDeprecated: 'warn' } }` (log warning, allow authentication - default), `onDeprecated: 'reject'` (throw error, block authentication), or `onDeprecated: 'allow'` (silent, no validation).
Supported SAML signature and digest algorithms
Supported SAML signature algorithms: RSA-SHA256, RSA-SHA384, RSA-SHA512, ECDSA-SHA256, ECDSA-SHA384, ECDSA-SHA512. Supported digest algorithms: SHA256, SHA384, SHA512. Deprecated algorithms (trigger warning/rejection): RSA-SHA1 (signature), SHA1 (digest), RSA 1.5 (key encryption), 3DES (data encryption).
SAML payload size limits
Better Auth enforces size limits on SAML payloads to protect against denial-of-service attacks via oversized XML. Default limits: maxResponseSize (256KB, maximum SAML response size in bytes), maxMetadataSize (100KB, maximum IdP metadata size in bytes). These can be customized in configuration.
Trusted origins for SSO discovery
Both the discovery endpoint and any URL resolved through the OIDC discovery process are subject to the app's trustedOrigins configuration. Discovery will fail with 'discovery_untrusted_origin' error code unless you explicitly update trustedOrigins to include the IdP's origin (e.g., 'https://your-org.okta.com'). For multiple IdPs, either register them ahead of time in trustedOrigins array or dynamically compute trustedOrigins via callback function.