Skip to content

Expose authentication / handshake readiness for bidirectional streaming RPCs in grpc-java #12628

@Trajanv

Description

@Trajanv

Is your feature request related to a problem?

Yes. In gRPC bidirectional streaming RPCs, application code can begin sending messages immediately after stream creation, even though transport authentication (TLS/mTLS handshake and certificate validation) may still be in progress. Authentication failures (e.g., invalid or rotated certificates) are surfaced asynchronously, potentially after a large number of messages have already been sent or buffered.

In high-throughput, low-latency, real-time systems, this creates a correctness and operational problem: by the time the client observes the authentication error, it may have already emitted many requests on the stream, resulting in wasted work, dropped messages, and difficulty implementing fail-fast behavior—especially during certificate rotation or maintenance windows.

Although a stream with failed authentication will ultimately not be successfully established, the lack of a deterministic, application-visible authentication readiness signal makes it hard to prevent premature sends.

Describe the solution you'd like

Expose an explicit, application-visible mechanism to determine when transport authentication has completed successfully for a bidirectional streaming RPC, before application messages are accepted for sending.

This could take one or more forms, such as:

A stream-level readiness signal or callback indicating successful authentication and handshake completion
A fail-fast option to prevent stream creation or message sends until authentication succeeds
Authentication-aware gating of send operations (e.g., rejecting sends immediately if authentication is pending or has failed)

The goal is not to introduce blocking semantics, but to provide deterministic observability and control so applications with real-time requirements can avoid sending data on unauthenticated or not-yet-authenticated streams.

Describe alternatives you've considered

  1. Channel connectivity state APIs: Connection-level state (e.g., READY) does not provide a strict guarantee that authentication has completed for a specific stream and is not sufficient for per-stream correctness (esp. in Bidi RPCs).
    2)Application-level warm-up or health-check RPCs: These add complexity, increase latency, and do not eliminate race conditions during cert rotation or transient authentication failures.
    3)Application-level authentication RPCs: This does not address transport-level authentication (TLS/mTLS), which is inseparable from stream establishment.
    For e.g, we could use synchronization mechanisms such as CountDownLatch : use a CountDownLatch to make asynchronous gRPC calls behave synchronously, ensuring that authentication is completed before sending any requests.
    // Create a CountDownLatch with an initial count of 1
    CountDownLatch latch = new CountDownLatch(1);
    ...
    // Simulate synchronous behavior using CountDownLatch
    try {
    // Wait for the latch to be released (authn/z is completed)
    latch.await();
    // Sending request(s) to the server
    requestObserver.onNext(request);
    } catch (InterruptedException e) {
    // Handle InterruptedException
    }
    The use of a CountDownLatch can introduce blocking behavior, especially if the latch is not released in a timely manner. If the authentication process takes a long time, it can cause the application to hang or become unresponsive.

Additional context

This issue is particularly impactful for:

  1. High-throughput, real-time bidirectional streaming workloads
  2. Systems with strict ordering or delivery semantics
  3. Environments with frequent certificate rotation or maintenance events

This request does not seek to weaken TLS guarantees, expose sensitive transport details, or introduce blocking streaming APIs. It aims to improve lifecycle observability and correctness for applications that need stronger guarantees around authentication readiness.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions