Hi All, I'd like to propose a patch that adds a credential validation framework to PostgreSQL, enabling periodic re-validation of authentication credentials during active sessions.
Currently, PostgreSQL validates credentials only at connection time. Once
authenticated, a session remains valid even if the underlying
credentials expire (e.g., a user's rolvaliduntil passes, or an OAuth token
expires). This can be problematic in environments with strict
security requirements where sessions should be terminated when credentials
become invalid.
This patch introduces a timer-based credential validation mechanism that
periodically checks whether a session's authentication credentials are
still valid. When credentials are found to be expired, the session is
terminated with an appropriate error message
*Key Components *
1. Core Framework (auth-validate.c, auth-validate.h)
- Manages validation callbacks for different authentication methods
- Provides a timeout-based scheduler using
CREDENTIAL_VALIDATION_TIMEOUT
- Handles validation status (CVS_VALID, CVS_EXPIRED, CVS_ERROR)
2. Validation Methods (auth-validate-methods.c)
- Password validation: checks rolvaliduntil in pg_authid
- OAuth validation: delegates to the validator module's new expire_cb
callback
3. GUC Parameters
- credential_validation.enabled (boolean, default: false)
- credential_validation.interval (integer, 1-60 minutes, default: 1)
*OAuth Validator Changes *
The patch extends the OAuth validator API with an optional expire_cb
callback. To maintain backward compatibility, the magic version has been
bumped to PG_OAUTH_VALIDATOR_MAGIC_V2. Existing V1 validators continue to
work; the server simply skips expiration checking for them.
*Example Configuration*
credential_validation.enabled = on
credential_validation.interval = 5 # minutes
Thanks & Best Regards,
Ajit
On Mon, 16 Mar 2026 at 19:27, Ajit Awekar <[email protected]> wrote:
> Hi,
>
> Please find the attached first version of the patch providing credential
> validation framework.
>
> The credential validation framework provides a mechanism to continuously
> validate authentication credentials during an active session. This enables
> the server to periodically check credential validity and take appropriate
> action when credentials expire or become invalid.
>
> Currently, Postgres validates credentials only at connection time. Once
> authenticated, a session remains active even if:
>
> - A user's rolvaliduntil expiration time passes
> - An OAuth bearer token expires
>
>
>
> * Proposed Solution*
> The patch introduces a credential validation framework that:
>
> 1. Periodically checks credential validity during active sessions
> 2. Terminates sessions when credentials expire or become invalid
>
> *Implementation*
>
> The framework consists of:
>
> - Core infrastructure (auth-validate.c/h): Manages validation callbacks,
> dispatches validation checks based on authentication method
> - Method implementations (auth-validate-methods.c/h): Contains
> validators for password-based auth (checks rolvaliduntil in pg_authid) and
> OAuth
> (delegates to validator's expire_cb)
>
> Validation is triggered during query execution in both simple and
> extended query protocol paths, using a time-based approach to limit
> overhead.
>
>
> * Configuration*
> Two new GUC parameters:
>
> credential_validation.enabled = false # enable/disable validation
> credential_validation.interval = 1 # check interval in minutes
> (1-60)
>
>
> * Extensibility*
> New authentication methods can be supported by:
> 1. Adding an enum value to CredentialValidationType
> 2. Implementing a validation callback
> 3. Registering it via RegisterCredentialValidator()
>
>
> Should there be per-authentication-method enable/disable settings?
>
> Thanks & Best Regards,
> Ajit
>
>
> On Fri, 20 Feb 2026 at 15:12, Ajit Awekar <[email protected]> wrote:
>
>>
>> Thanks a lot Daniel, Zslot, Vasuki for your review comments.
>>
>> >The mechanism used is however a secondary discussion,
>> >first thing to get in place is a design for how to handle mid-connection
>> >credential expiration.
>>
>> This patch introduces a generic credential validation framework that
>> allows
>> us to periodically validate authentication credentials during active
>> database sessions. When enabled, this feature detects expired
>> credentials and terminates sessions that are no longer valid.
>>
>> Added GUCs
>> Credential_validation.enabled = on // Enable or Disable Credential
>> validation
>> Credential_validation.interval = 120 //Frequency in seconds of running
>> credential validation
>>
>> The callback mechanism works by:
>> - Defining a CredentialValidationCallback function pointer type
>> - Maintaining an array of validators indexed by authentication method
>> - Allowing other auth mechanisms to register validators via
>> RegisterCredentialValidator()
>> - Selecting the appropriate validator at runtime based on the session's
>> authentication method
>>
>> The current implementation primarily supports password-based
>> authentication methods, verifying that passwords haven't expired. It can be
>> extended to any authentication method.
>> This patch is WIP. I am submitting it now to get early feedback on the
>> overall design and approach.
>>
>> Thanks & Best Regards,
>> Ajit
>>
>> On Wed, 18 Feb 2026 at 22:29, Zsolt Parragi <[email protected]>
>> wrote:
>>
>>> > but I still think that neither should overload
>>> > what FATAL error means
>>>
>>> I see, I misunderstood what you meant by graceful there. In this case,
>>> this is also a good comment for the password expiration thread,
>>> currently that also uses FATAL errors for terminating a connection
>>> when the password expires.
>>>
>>> What other option do you see? Something new for this use case like
>>> GoAway, and clients not understanding it simply get disconnected after
>>> some grace period? Or using the recently merged connectionWarning to
>>> send a warning to the client, and disconnect it shortly if it doesn't
>>> do anything to fix the situation?
>>>
>>> When I tested the password expiration patch I noticed that deleted
>>> users who still have remaining active connections currently get ERRORs
>>> for every statement that requires permission checks, so in this regard
>>> using ERROR/FATAL for the situation seemed fine to me - it's similar
>>> to what already happens in some edge cases with authentication.
>>>
>>
Credential_validation.patch
Description: Binary data
