square / okhttp

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
https://square.github.io/okhttp/
Apache License 2.0
45.66k stars 9.14k forks source link

Support HSTS #3170

Open yschimke opened 7 years ago

yschimke commented 7 years ago

Feature Request: https://tools.ietf.org/html/rfc6797

HSTS with Preloaded site list

Mainly curious if this is something that would fit within OkHttp core, or should be a purely separate addon? To me this seems like something that should be part of the core, because its required to correctly follow the directions of sites that provide the header.

I was experimenting here https://github.com/square/okhttp/compare/master...yschimke:hsts?expand=1

It seems like it should be possible to implement cleanly either way as an application interceptor. Implementing in OkHttp core would ideally built of some persistent configuration support.

swankjesse commented 7 years ago

Persistent configuration would be really nice for stuff like this. See also: https://github.com/square/okhttp/issues/2890

amirlivneh commented 6 years ago

We have an implementation of an Interceptor implementing HSTS pre-loaded list (no Strict-Transport-Security header support). I can submit a PR if you decide this should be part of the OkHttp core.

yschimke commented 6 years ago

@amirlivneh I'd love to integrate a java/kotlin version in my own project if not. Care to publish this somewhere?

I would argue for OkHttp moving in this direction, sites should be able to indicate their security policy like this and have it respected by mobile clients. But it seems like something that could cause problems when applied globally by default given the wide number of older devices, it's likely these devices would start showing up on app developers failure dashboards.

amirlivneh commented 6 years ago

@yschimke, I'll wait for the maintainers' decision on this. If we don't end up upstreaming it, I may be able to publish the Interceptor somewhere.

yschimke commented 6 years ago

I'm one of the maintainers, it would be easier to judge suitability once we can evaluate the code. We have a similar feature that includes a large binary list for top level domains, and it does cause some pain as well as bloat but is a reasonably important feature.

amirlivneh commented 6 years ago

I don't expect the implementation to add bloat because the list of preloads is provided by the user. The API will be something along these lines:

List<HstsPreload> hstsPreloads = Arrays.asList(
    // Force HTTPS for foo.com and all of its subdomains
    new HstsPreload.Builder().domain("foo.com").build(),

    // Force HTTPS for bar.com and all of its subdomains, except for special.bar.com
    new HstsPreload.Builder().domain("bar.com").build(),
    new HstsPreload.Builder().domain("special.bar.com"),
        .forceHttps(false)
        .includeSubdomains(false)
        .build());

OkHttpClient client = new OkHttpClient.Builder()
    .hstsPreloads(hstsPreloads)
    .build();
swankjesse commented 6 years ago

I think perhaps the best approach of OkHttp is also pretty easy. Just disable all cleartext:

    client = new OkHttpClient.Builder()
        .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS))
        .build();

HSTS is great for general-purpose clients like browsers. But many folks who’d use HSTS with OkHttp might be better off just dropping all cleartext.

yschimke commented 6 years ago

This might be best as a separate library. If we were to build it into OkHttp I'd personally push for including a public (firefox/chrome) preload list, upgrading to https automatically and eventually observing and storing Strict-Transport-Security headers.

amirlivneh commented 6 years ago

I agree that disabling cleartext is the simplest solution and probably good enough for most clients. Our apps have special use cases that require more granular control. Fortunately, Interceptors are powerful enough, so we can rely on one to address our needs.

In our solution, we decided not to couple the enforcing mechanism with a public preload list. We have lightweight apps with extreme APK size constraints. Some of these apps only send requests to a limited set of domains. Decoupling the public preload list from the enforcing mechanism allows those apps to benefit from HTTPS forcing without taking the size penalty of a full public list.

yschimke commented 4 years ago

This seems pretty widely adopted https://caniuse.com/#search=hsts

yschimke commented 3 years ago

Also relevant https://emilymstark.com/2020/10/24/strict-transport-security-vs-https-resource-records-the-showdown.html

and

https://twitter.com/estark37/status/1320442640123326464

yschimke commented 3 years ago

https://twitter.com/tunetheweb/status/1320661941556252672

Discusses caching of similar items.

yschimke commented 3 years ago

Curl implementation https://daniel.haxx.se/blog/2020/11/03/hsts-your-curl/ https://github.com/curl/curl/blob/21464a65c60092e410bb3c8195f3160fc49f4286/docs/HSTS.md

yschimke commented 2 years ago

Given Android usually fails with plaintext requests. Should there be a HTTPS-only mode or HTTPS everywhere mode on OkHttpClient that ignores http in the url and forces https.

This would be the simplest form of HSTS manually configured by developers. Asking because I had to implement an SSLOnlyInterceptor when dealing with API content that can have images or redirects to http://

swankjesse commented 2 years ago

We could write a recipe for a SecurityPolicyInterceptor? Perhaps convert requests to HTTPS? Perhaps have an allowlist for outbound hosts? I'd prefer to not ship anything with build in network information; we have very little influence on our users upgrading their OkHttp and I don't think these browsers-packager HSTS lists last forever. Even publicsuffix is problematic this way!

yschimke commented 2 years ago

I'll do that sample and leave this as open in case we decide to implement HSTS.