Skip to content

Post Handshake Auth works with an SSLContext but not a cert tuple #989

@aiman-alsari

Description

@aiman-alsari

If I am connecting to a server that requires TLS auth after a handshake has already been established (e.g. this nginx config):

events {}
http {
    server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/certs/server.crt;
        ssl_certificate_key /etc/nginx/certs/server.key;
        ssl_client_certificate /etc/nginx/certs/ca.crt;
        ssl_verify_client optional;

        location / {
            if ($ssl_client_verify != SUCCESS) { return 403; }
            return 200 "OK";
        }
    }
}

It only works if I provide it with a client cert via an SSLContext, rather than via the cert tuple parameter, e.g.

import httpx2, asyncio, ssl

async def run():
    # Fails with 403
    async with httpx2.AsyncClient(verify="certs/ca.crt", cert=("certs/client.crt", "certs/client.key")) as c:
        r = await c.get("https://127.0.0.1:8443/")
        print(f"Cert param: {r.status_code}")

    # Works with 200
    ctx = ssl.create_default_context(cafile="certs/ca.crt")
    ctx.load_cert_chain("certs/client.crt", "certs/client.key")
    async with httpx2.AsyncClient(verify=ctx) as c:
        r = await c.get("https://127.0.0.1:8443/")
        print(f"Manual sslcontext: {r.status_code}")

asyncio.run(run())

Results in:

Cert param: 403
Manual sslcontext: 200

Note; this bug appears in httpx and httpx2, but not in httpxyz where it appears to have been fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions