Skip to content

Feature request: expose a server trust evaluation hook in CupertinoClient for certificate pinning #1981

Closed

Description

@umair9430

cupertino_http's CupertinoClient doesn't currently expose any way to customize TLS server trust evaluation — there's no hook equivalent to URLSessionDelegate's urlSession(_:didReceive:completionHandler:) for the NSURLAuthenticationMethodServerTrust case.

Use case: Certificate pinning against a CA higher up the chain than the leaf. For example, AWS explicitly recommends pinning to an Amazon Trust Services root CA (not the leaf, and not even the intermediate CA) for ACM-issued certificates, since Amazon now issues from multiple "dynamic" intermediate CAs that can rotate unpredictably — see AWS's own guidance: https://aws.amazon.com/blogs/security/amazon-introduces-dynamic-intermediate-certificate-authorities/. Implementing this requires walking the full certificate chain during the TLS handshake to find the pinned CA, which dart:io's HttpClient.badCertificateCallback cannot do — it only exposes the leaf certificate via X509Certificate, never the intermediates or root.

cupertino_http is otherwise a great fit for this — it already streams request/response bodies properly via URLSession's native APIs, unlike dart:io's HttpClient. The only missing piece is a way to intercept the trust decision.

Proposed API (minimal surface, doesn't require exposing the full delegate):

CupertinoClient.fromSessionConfiguration(
  config,
  serverTrustEvaluator: (SecTrust trust, String host) => bool,
);

cupertino_http would still own the actual URLSessionDelegate internally (preserving its existing streaming/redirect handling); it would just call this closure during its own didReceive challenge implementation and act on the returned decision.

Happy to contribute a PR if the maintainers are open to this direction.

Activity

  1. brianquinlan commented on Sep 28, 2026

    @brianquinlan
    Collaborator

    I'm not sure how this would fit together so I can't promise to accept a PR but I'd be interested in seeing what this would look like. Would you mind writing a skeleton PR for discussion? I doesn't need to include tests, comments, etc. for now.

  2. self-assigned this
    on Oct 25, 2026
  3. brianquinlan commented on Oct 25, 2026

    @brianquinlan
    Collaborator

    I've started working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions