Skip to content

Support dynamic password callback for IAM authentication #5887

Description

@godu

What is the problem this feature would solve?

When using AWS RDS or Aurora DSQL with IAM database authentication, the authentication token expires after a
fixed period (15 minutes for RDS, 60 minutes for DSQL). The current PgClientConfig only accepts a static
Redacted for the password field, which means:

  1. The token is generated once at connection pool creation time
  2. After the token expires, new connections fail with "Signature expired" errors
  3. Even with connectionTTL set to recycle connections, the same expired token is reused

What is the feature you are proposing to solve the problem?

The underlying pg library (node-postgres) has supported brianc/node-postgres#1873.
When the password is a function, pg invokes it for each new connection authentication:

 // From pg/lib/client.js
 if (typeof this.password === 'function') {
   this._Promise
     .resolve()
     .then(() => this.password())  // Invokes password function
     .then((pass) => { /* use pass for auth */ })
 }

Use Case: AWS DSQL / RDS IAM Authentication with @effect-aws/dsql

 import { DsqlSigner } from '@effect-aws/dsql';
 import * as PgClient from '@effect/sql-pg/PgClient';
 import * as Layer from 'effect/Layer';

 // Desired API (with this feature)
 const pgLayer = PgClient.layer({
   host: hostname,
   username: 'admin',
   database: 'postgres',
   password: DsqlSigner.getDbConnectAdminAuthToken(), // Effect<string>
 }).pipe(
   Layer.provide(DsqlSigner.layer({ hostname }))
 );

Each new connection will run the Effect to get a fresh token, integrating cleanly with the Effect ecosystem
and the @effect-aws/dsql package.

Additional context

What alternatives have you considered?

Current workaround: Using @aws-sdk/dsql-signer directly with a type cast:

 import { DsqlSigner } from '@aws-sdk/dsql-signer';
 import * as PgClient from '@effect/sql-pg/PgClient';
 import * as Layer from 'effect/Layer';
 import * as Redacted from 'effect/Redacted';

 const signer = new DsqlSigner({ hostname });

 const pgLayer = PgClient.layer({
   host: hostname,
   username: 'admin',
   database: 'postgres',
   password: Redacted.make(() => signer.getDbConnectAdminAuthToken()) as unknown as Redacted.Redacted<string>,
 });

This works at runtime because Redacted.value() returns whatever was passed to Redacted.make(), and pg accepts
the function. However, it requires an unsafe type assertion (as unknown as).

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.0Used for issues, pull requests, etc. that are relevant for the `v3` branch targeting Effect v3.enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions