1
0
mirror of https://github.com/square/okhttp.git synced 2026-01-12 10:23:16 +03:00
Files
okhttp/https/index.html
2020-09-15 12:10:01 -05:00

1019 lines
46 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="An HTTP & HTTP/2 client for Android and Java applications">
<link rel="canonical" href="https://square.github.com/okhttp/https/">
<meta name="author" content="Square, Inc.">
<link rel="shortcut icon" href="../images/icon-square.png">
<meta name="generator" content="mkdocs-1.1.2, mkdocs-material-5.5.7">
<title>HTTPS - OkHttp</title>
<link rel="stylesheet" href="../assets/stylesheets/main.b8ac9624.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.28f3ef9a.min.css">
<meta name="theme-color" content="#009688">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
<style>body,input{font-family:"Roboto",-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono",SFMono-Regular,Consolas,Menlo,monospace}</style>
<link rel="stylesheet" href="../css/app.css">
</head>
<body dir="ltr" data-md-color-scheme="" data-md-color-primary="teal" data-md-color-accent="white">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#https" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid" aria-label="Header">
<a href="https://square.github.com/okhttp/" title="OkHttp" class="md-header-nav__button md-logo" aria-label="OkHttp">
<img src="../images/icon-square.png" alt="logo">
</a>
<label class="md-header-nav__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
</label>
<div class="md-header-nav__title" data-md-component="header-title">
<div class="md-header-nav__ellipsis">
<span class="md-header-nav__topic md-ellipsis">
OkHttp
</span>
<span class="md-header-nav__topic md-ellipsis">
HTTPS
</span>
</div>
</div>
<label class="md-header-nav__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</label>
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" data-md-component="search-reset" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header-nav__source">
<a href="https://github.com/square/okhttp/" title="Go to repository" class="md-source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
</div>
<div class="md-source__repository">
OkHttp
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="https://square.github.com/okhttp/" title="OkHttp" class="md-nav__button md-logo" aria-label="OkHttp">
<img src="../images/icon-square.png" alt="logo">
</a>
OkHttp
</label>
<div class="md-nav__source">
<a href="https://github.com/square/okhttp/" title="Go to repository" class="md-source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
</div>
<div class="md-source__repository">
OkHttp
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Overview" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="https://stackoverflow.com/questions/tagged/okhttp?sort=active" title="Stack Overflow ⏏" class="md-nav__link">
Stack Overflow ⏏
</a>
</li>
<li class="md-nav__item">
<a href="../calls/" title="Calls" class="md-nav__link">
Calls
</a>
</li>
<li class="md-nav__item">
<a href="../caching/" title="Caching" class="md-nav__link">
Caching
</a>
</li>
<li class="md-nav__item">
<a href="../connections/" title="Connections" class="md-nav__link">
Connections
</a>
</li>
<li class="md-nav__item">
<a href="../events/" title="Events" class="md-nav__link">
Events
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
HTTPS
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 9h14V7H3v2m0 4h14v-2H3v2m0 4h14v-2H3v2m16 0h2v-2h-2v2m0-10v2h2V7h-2m0 6h2v-2h-2v2z"/></svg>
</span>
</label>
<a href="./" title="HTTPS" class="md-nav__link md-nav__link--active">
HTTPS
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</span>
Table of contents
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#debugging-tls-handshake-failures" class="md-nav__link">
Debugging TLS Handshake Failures
</a>
</li>
<li class="md-nav__item">
<a href="#certificate-pinning-kt-java" class="md-nav__link">
Certificate Pinning (.kt, .java)
</a>
</li>
<li class="md-nav__item">
<a href="#customizing-trusted-certificates-kt-java" class="md-nav__link">
Customizing Trusted Certificates (.kt, .java)
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../interceptors/" title="Interceptors" class="md-nav__link">
Interceptors
</a>
</li>
<li class="md-nav__item">
<a href="../recipes/" title="Recipes" class="md-nav__link">
Recipes
</a>
</li>
<li class="md-nav__item">
<a href="../security/" title="Security" class="md-nav__link">
Security
</a>
</li>
<li class="md-nav__item">
<a href="../security_providers/" title="Security Providers" class="md-nav__link">
Security Providers
</a>
</li>
<li class="md-nav__item">
<a href="../works_with_okhttp/" title="Works with OkHttp" class="md-nav__link">
Works with OkHttp
</a>
</li>
<li class="md-nav__item">
<a href="../upgrading_to_okhttp_4/" title="Upgrading to OkHttp 4" class="md-nav__link">
Upgrading to OkHttp 4
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-14" type="checkbox" id="nav-14">
<label class="md-nav__link" for="nav-14">
4.x API
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="4.x API" data-md-level="1">
<label class="md-nav__title" for="nav-14">
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</span>
4.x API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../4.x/okhttp/okhttp3/" title="okhttp" class="md-nav__link">
okhttp
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-brotli/okhttp3.brotli/" title="brotli" class="md-nav__link">
brotli
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-dnsoverhttps/okhttp3.dnsoverhttps/" title="dnsoverhttps" class="md-nav__link">
dnsoverhttps
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-logging-interceptor/okhttp3.logging/" title="logging-interceptor" class="md-nav__link">
logging-interceptor
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-sse/okhttp3.sse/" title="sse" class="md-nav__link">
sse
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-tls/okhttp3.tls/" title="tls" class="md-nav__link">
tls
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/okhttp-urlconnection/okhttp3/" title="urlconnection" class="md-nav__link">
urlconnection
</a>
</li>
<li class="md-nav__item">
<a href="../4.x/mockwebserver/okhttp3.mockwebserver/" title="mockwebserver" class="md-nav__link">
mockwebserver
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-15" type="checkbox" id="nav-15">
<label class="md-nav__link" for="nav-15">
3.12.x API
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="3.12.x API" data-md-level="1">
<label class="md-nav__title" for="nav-15">
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</span>
3.12.x API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/okhttp/" title="okhttp ⏏" class="md-nav__link">
okhttp ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/okhttp-dnsoverhttps/" title="dnsoverhttps ⏏" class="md-nav__link">
dnsoverhttps ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/logging-interceptor/" title="logging-interceptor ⏏" class="md-nav__link">
logging-interceptor ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/okhttp-sse/" title="sse ⏏" class="md-nav__link">
sse ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/okhttp-tls/" title="tls ⏏" class="md-nav__link">
tls ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/okhttp-urlconnection/" title="urlconnection ⏏" class="md-nav__link">
urlconnection ⏏
</a>
</li>
<li class="md-nav__item">
<a href="https://square.github.io/okhttp/3.x/mockwebserver/" title="mockwebserver ⏏" class="md-nav__link">
mockwebserver ⏏
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../changelog/" title="Change Log" class="md-nav__link">
Change Log
</a>
</li>
<li class="md-nav__item">
<a href="../contributing/" title="Contributing" class="md-nav__link">
Contributing
</a>
</li>
<li class="md-nav__item">
<a href="../code_of_conduct/" title="Code of Conduct" class="md-nav__link">
Code of Conduct
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</span>
Table of contents
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#debugging-tls-handshake-failures" class="md-nav__link">
Debugging TLS Handshake Failures
</a>
</li>
<li class="md-nav__item">
<a href="#certificate-pinning-kt-java" class="md-nav__link">
Certificate Pinning (.kt, .java)
</a>
</li>
<li class="md-nav__item">
<a href="#customizing-trusted-certificates-kt-java" class="md-nav__link">
Customizing Trusted Certificates (.kt, .java)
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/square/okhttp/edit/master/docs/https.md" title="Edit this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>
</a>
<h1 id="https">HTTPS<a class="headerlink" href="#https" title="Permanent link">&para;</a></h1>
<p>OkHttp attempts to balance two competing concerns:</p>
<ul>
<li><strong>Connectivity</strong> to as many hosts as possible. That includes advanced hosts that run the latest versions of <a href="https://boringssl.googlesource.com/boringssl/">boringssl</a> and less out of date hosts running older versions of <a href="https://www.openssl.org/">OpenSSL</a>.</li>
<li><strong>Security</strong> of the connection. This includes verification of the remote webserver with certificates and the privacy of data exchanged with strong ciphers.</li>
</ul>
<p>When negotiating a connection to an HTTPS server, OkHttp needs to know which <a href="http://square.github.io/okhttp/4.x/okhttp/okhttp3/-tls-version/">TLS versions</a> and <a href="http://square.github.io/okhttp/4.x/okhttp/okhttp3/-cipher-suite/">cipher suites</a> to offer. A client that wants to maximize connectivity would include obsolete TLS versions and weak-by-design cipher suites. A strict client that wants to maximize security would be limited to only the latest TLS version and strongest cipher suites.</p>
<p>Specific security vs. connectivity decisions are implemented by <a href="http://square.github.io/okhttp/4.x/okhttp/okhttp3/-connection-spec/">ConnectionSpec</a>. OkHttp includes four built-in connection specs:</p>
<ul>
<li><code>RESTRICTED_TLS</code> is a secure configuration, intended to meet stricter compliance requirements.</li>
<li><code>MODERN_TLS</code> is a secure configuration that connects to modern HTTPS servers.</li>
<li><code>COMPATIBLE_TLS</code> is a secure configuration that connects to securebut not currentHTTPS servers.</li>
<li><code>CLEARTEXT</code> is an insecure configuration that is used for <code>http://</code> URLs.</li>
</ul>
<p>These loosely follow the model set in <a href="https://cloud.google.com/load-balancing/docs/ssl-policies-concepts">Google Cloud Policies</a>. We <a href="../tls_configuration_history/">track changes</a> to this policy.</p>
<p>By default, OkHttp will attempt a <code>MODERN_TLS</code> connection. However by configuring the client connectionSpecs you can allow a fall back to <code>COMPATIBLE_TLS</code> connection if the modern configuration fails.</p>
<div class="highlight"><pre><span></span><code><span class="n">OkHttpClient</span> <span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">connectionSpecs</span><span class="p">(</span><span class="n">Arrays</span><span class="p">.</span><span class="na">asList</span><span class="p">(</span><span class="n">ConnectionSpec</span><span class="p">.</span><span class="na">MODERN_TLS</span><span class="p">,</span> <span class="n">ConnectionSpec</span><span class="p">.</span><span class="na">COMPATIBLE_TLS</span><span class="p">))</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
</code></pre></div>
<p>The TLS versions and cipher suites in each spec can change with each release. For example, in OkHttp 2.2 we dropped support for SSL 3.0 in response to the <a href="http://googleonlinesecurity.blogspot.ca/2014/10/this-poodle-bites-exploiting-ssl-30.html">POODLE</a> attack. And in OkHttp 2.3 we dropped support for <a href="http://en.wikipedia.org/wiki/RC4#Security">RC4</a>. As with your desktop web browser, staying up-to-date with OkHttp is the best way to stay secure.</p>
<p>You can build your own connection spec with a custom set of TLS versions and cipher suites. For example, this configuration is limited to three highly-regarded cipher suites. Its drawback is that it requires Android 5.0+ and a similarly current webserver.</p>
<div class="highlight"><pre><span></span><code><span class="n">ConnectionSpec</span> <span class="n">spec</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConnectionSpec</span><span class="p">.</span><span class="na">Builder</span><span class="p">(</span><span class="n">ConnectionSpec</span><span class="p">.</span><span class="na">MODERN_TLS</span><span class="p">)</span>
<span class="p">.</span><span class="na">tlsVersions</span><span class="p">(</span><span class="n">TlsVersion</span><span class="p">.</span><span class="na">TLS_1_2</span><span class="p">)</span>
<span class="p">.</span><span class="na">cipherSuites</span><span class="p">(</span>
<span class="n">CipherSuite</span><span class="p">.</span><span class="na">TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</span><span class="p">,</span>
<span class="n">CipherSuite</span><span class="p">.</span><span class="na">TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</span><span class="p">,</span>
<span class="n">CipherSuite</span><span class="p">.</span><span class="na">TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</span><span class="p">)</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
<span class="n">OkHttpClient</span> <span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">connectionSpecs</span><span class="p">(</span><span class="n">Collections</span><span class="p">.</span><span class="na">singletonList</span><span class="p">(</span><span class="n">spec</span><span class="p">))</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
</code></pre></div>
<h3 id="debugging-tls-handshake-failures">Debugging TLS Handshake Failures<a class="headerlink" href="#debugging-tls-handshake-failures" title="Permanent link">&para;</a></h3>
<p>The TLS handshake requires clients and servers to share a common TLS version and cipher suite. This
depends on the JVM or Android version, OkHttp version, and web server configuration. If there is no
common cipher suite and TLS version, your call will fail like this:</p>
<div class="highlight"><pre><span></span><code>Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f2719a89e80:
Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake
failure (external/openssl/ssl/s23_clnt.c:770 0x7f2728a53ea0:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
</code></pre></div>
<p>You can check a web server&rsquo;s configuration using <a href="https://www.ssllabs.com/ssltest/">Qualys SSL Labs</a>. OkHttp&rsquo;s TLS
configuration history is <a href="../tls_configuration_history/">tracked here</a>.</p>
<p>Applications expected to be installed on older Android devices should consider adopting the
<a href="https://developer.android.com/training/articles/security-gms-provider">Google Play Services ProviderInstaller</a>. This will increase security for users
and increase connectivity with web servers.</p>
<h3 id="certificate-pinning-kt-java">Certificate Pinning (<a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/kt/CertificatePinning.kt">.kt</a>, <a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CertificatePinning.java">.java</a>)<a class="headerlink" href="#certificate-pinning-kt-java" title="Permanent link">&para;</a></h3>
<p>By default, OkHttp trusts the certificate authorities of the host platform. This strategy maximizes connectivity, but it is subject to certificate authority attacks such as the <a href="http://www.computerworld.com/article/2510951/cybercrime-hacking/hackers-spied-on-300-000-iranians-using-fake-google-certificate.html">2011 DigiNotar attack</a>. It also assumes your HTTPS servers certificates are signed by a certificate authority.</p>
<p>Use <a href="http://square.github.io/okhttp/4.x/okhttp/okhttp3/-certificate-pinner/">CertificatePinner</a> to restrict which certificates and certificate authorities are trusted. Certificate pinning increases security, but limits your server teams abilities to update their TLS certificates. <strong>Do not use certificate pinning without the blessing of your servers TLS administrator!</strong></p>
<div class="tabbed-set" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><label for="__tabbed_1_1">Kotlin</label><div class="tabbed-content">
<div class="highlight"><pre><span></span><code> <span class="k">private</span> <span class="k">val</span> <span class="py">client</span> <span class="p">=</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="n">certificatePinner</span><span class="p">(</span>
<span class="n">CertificatePinner</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">&quot;publicobject.com&quot;</span><span class="p">,</span> <span class="s">&quot;sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="n">build</span><span class="p">())</span>
<span class="p">.</span><span class="n">build</span><span class="p">()</span>
<span class="k">fun</span> <span class="nf">run</span><span class="p">()</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">request</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="n">url</span><span class="p">(</span><span class="s">&quot;https://publicobject.com/robots.txt&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="n">build</span><span class="p">()</span>
<span class="n">client</span><span class="p">.</span><span class="n">newCall</span><span class="p">(</span><span class="n">request</span><span class="p">).</span><span class="n">execute</span><span class="p">().</span><span class="n">use</span> <span class="p">{</span> <span class="n">response</span> <span class="p">-&gt;</span>
<span class="k">if</span> <span class="p">(!</span><span class="n">response</span><span class="p">.</span><span class="n">isSuccessful</span><span class="p">)</span> <span class="k">throw</span> <span class="n">IOException</span><span class="p">(</span><span class="s">&quot;Unexpected code $response&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="p">(</span><span class="n">certificate</span> <span class="k">in</span> <span class="n">response</span><span class="p">.</span><span class="n">handshake</span><span class="o">!!</span><span class="p">.</span><span class="n">peerCertificates</span><span class="p">)</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="n">CertificatePinner</span><span class="p">.</span><span class="n">pin</span><span class="p">(</span><span class="n">certificate</span><span class="p">))</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div>
<input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><label for="__tabbed_1_2">Java</label><div class="tabbed-content">
<div class="highlight"><pre><span></span><code> <span class="kd">private</span> <span class="kd">final</span> <span class="n">OkHttpClient</span> <span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">certificatePinner</span><span class="p">(</span>
<span class="k">new</span> <span class="n">CertificatePinner</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="s">&quot;publicobject.com&quot;</span><span class="p">,</span> <span class="s">&quot;sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="na">build</span><span class="p">())</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="p">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="p">{</span>
<span class="n">Request</span> <span class="n">request</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Request</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">url</span><span class="p">(</span><span class="s">&quot;https://publicobject.com/robots.txt&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
<span class="k">try</span> <span class="p">(</span><span class="n">Response</span> <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="na">newCall</span><span class="p">(</span><span class="n">request</span><span class="p">).</span><span class="na">execute</span><span class="p">())</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">response</span><span class="p">.</span><span class="na">isSuccessful</span><span class="p">())</span> <span class="k">throw</span> <span class="k">new</span> <span class="n">IOException</span><span class="p">(</span><span class="s">&quot;Unexpected code &quot;</span> <span class="o">+</span> <span class="n">response</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="n">Certificate</span> <span class="n">certificate</span> <span class="p">:</span> <span class="n">response</span><span class="p">.</span><span class="na">handshake</span><span class="p">().</span><span class="na">peerCertificates</span><span class="p">())</span> <span class="p">{</span>
<span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">CertificatePinner</span><span class="p">.</span><span class="na">pin</span><span class="p">(</span><span class="n">certificate</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div>
</div>
<h3 id="customizing-trusted-certificates-kt-java">Customizing Trusted Certificates (<a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/kt/CustomTrust.kt">.kt</a>, <a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java">.java</a>)<a class="headerlink" href="#customizing-trusted-certificates-kt-java" title="Permanent link">&para;</a></h3>
<p>The full code sample shows how to replace the host platforms certificate authorities with your own set. As above, <strong>do not use custom certificates without the blessing of your servers TLS administrator!</strong></p>
<div class="tabbed-set" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><label for="__tabbed_2_1">Kotlin</label><div class="tabbed-content">
<div class="highlight"><pre><span></span><code> <span class="k">private</span> <span class="k">val</span> <span class="py">client</span><span class="p">:</span> <span class="n">OkHttpClient</span>
<span class="n">init</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">trustManager</span> <span class="p">=</span> <span class="n">trustManagerForCertificates</span><span class="p">(</span><span class="n">trustedCertificatesInputStream</span><span class="p">())</span>
<span class="k">val</span> <span class="py">sslContext</span> <span class="p">=</span> <span class="n">SSLContext</span><span class="p">.</span><span class="n">getInstance</span><span class="p">(</span><span class="s">&quot;TLS&quot;</span><span class="p">)</span>
<span class="n">sslContext</span><span class="p">.</span><span class="n">init</span><span class="p">(</span><span class="k">null</span><span class="p">,</span> <span class="n">arrayOf</span><span class="p">&lt;</span><span class="n">TrustManager</span><span class="p">&gt;(</span><span class="n">trustManager</span><span class="p">),</span> <span class="k">null</span><span class="p">)</span>
<span class="k">val</span> <span class="py">sslSocketFactory</span> <span class="p">=</span> <span class="n">sslContext</span><span class="p">.</span><span class="n">socketFactory</span>
<span class="n">client</span> <span class="p">=</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="n">sslSocketFactory</span><span class="p">(</span><span class="n">sslSocketFactory</span><span class="p">,</span> <span class="n">trustManager</span><span class="p">)</span>
<span class="p">.</span><span class="n">build</span><span class="p">()</span>
<span class="p">}</span>
<span class="k">fun</span> <span class="nf">run</span><span class="p">()</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">request</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="n">url</span><span class="p">(</span><span class="s">&quot;https://publicobject.com/helloworld.txt&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="n">build</span><span class="p">()</span>
<span class="n">client</span><span class="p">.</span><span class="n">newCall</span><span class="p">(</span><span class="n">request</span><span class="p">).</span><span class="n">execute</span><span class="p">().</span><span class="n">use</span> <span class="p">{</span> <span class="n">response</span> <span class="p">-&gt;</span>
<span class="k">if</span> <span class="p">(!</span><span class="n">response</span><span class="p">.</span><span class="n">isSuccessful</span><span class="p">)</span> <span class="k">throw</span> <span class="n">IOException</span><span class="p">(</span><span class="s">&quot;Unexpected code $response&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="p">((</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">in</span> <span class="n">response</span><span class="p">.</span><span class="n">headers</span><span class="p">)</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;$name: $value&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="n">println</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">body</span><span class="o">!!</span><span class="p">.</span><span class="n">string</span><span class="p">())</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/**</span>
<span class="cm"> * Returns an input stream containing one or more certificate PEM files. This implementation just</span>
<span class="cm"> * embeds the PEM files in Java strings; most applications will instead read this from a resource</span>
<span class="cm"> * file that gets bundled with the application.</span>
<span class="cm"> */</span>
<span class="k">private</span> <span class="k">fun</span> <span class="nf">trustedCertificatesInputStream</span><span class="p">():</span> <span class="n">InputStream</span> <span class="p">{</span>
<span class="p">...</span> <span class="c1">// Full source omitted. See sample.</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">fun</span> <span class="nf">trustManagerForCertificates</span><span class="p">(</span><span class="n">inputStream</span><span class="p">:</span> <span class="n">InputStream</span><span class="p">):</span> <span class="n">X509TrustManager</span> <span class="p">{</span>
<span class="p">...</span> <span class="c1">// Full source omitted. See sample.</span>
<span class="p">}</span>
</code></pre></div>
</div>
<input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><label for="__tabbed_2_2">Java</label><div class="tabbed-content">
<div class="highlight"><pre><span></span><code> <span class="kd">private</span> <span class="kd">final</span> <span class="n">OkHttpClient</span> <span class="n">client</span><span class="p">;</span>
<span class="kd">public</span> <span class="nf">CustomTrust</span><span class="p">()</span> <span class="p">{</span>
<span class="n">X509TrustManager</span> <span class="n">trustManager</span><span class="p">;</span>
<span class="n">SSLSocketFactory</span> <span class="n">sslSocketFactory</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="n">trustManager</span> <span class="o">=</span> <span class="n">trustManagerForCertificates</span><span class="p">(</span><span class="n">trustedCertificatesInputStream</span><span class="p">());</span>
<span class="n">SSLContext</span> <span class="n">sslContext</span> <span class="o">=</span> <span class="n">SSLContext</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="s">&quot;TLS&quot;</span><span class="p">);</span>
<span class="n">sslContext</span><span class="p">.</span><span class="na">init</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="k">new</span> <span class="n">TrustManager</span><span class="o">[]</span> <span class="p">{</span> <span class="n">trustManager</span> <span class="p">},</span> <span class="kc">null</span><span class="p">);</span>
<span class="n">sslSocketFactory</span> <span class="o">=</span> <span class="n">sslContext</span><span class="p">.</span><span class="na">getSocketFactory</span><span class="p">();</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">GeneralSecurityException</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">RuntimeException</span><span class="p">(</span><span class="n">e</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="n">OkHttpClient</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">sslSocketFactory</span><span class="p">(</span><span class="n">sslSocketFactory</span><span class="p">,</span> <span class="n">trustManager</span><span class="p">)</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="p">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="p">{</span>
<span class="n">Request</span> <span class="n">request</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Request</span><span class="p">.</span><span class="na">Builder</span><span class="p">()</span>
<span class="p">.</span><span class="na">url</span><span class="p">(</span><span class="s">&quot;https://publicobject.com/helloworld.txt&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="na">build</span><span class="p">();</span>
<span class="n">Response</span> <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="na">newCall</span><span class="p">(</span><span class="n">request</span><span class="p">).</span><span class="na">execute</span><span class="p">();</span>
<span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="na">body</span><span class="p">().</span><span class="na">string</span><span class="p">());</span>
<span class="p">}</span>
<span class="kd">private</span> <span class="n">InputStream</span> <span class="nf">trustedCertificatesInputStream</span><span class="p">()</span> <span class="p">{</span>
<span class="p">...</span> <span class="c1">// Full source omitted. See sample.</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="n">SSLContext</span> <span class="nf">sslContextForTrustedCertificates</span><span class="p">(</span><span class="n">InputStream</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
<span class="p">...</span> <span class="c1">// Full source omitted. See sample.</span>
<span class="p">}</span>
</code></pre></div>
</div>
</div>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid" aria-label="Footer">
<a href="../events/" title="Events" class="md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-footer-nav__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</div>
<div class="md-footer-nav__title">
<div class="md-ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Events
</div>
</div>
</a>
<a href="../interceptors/" title="Interceptors" class="md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-footer-nav__title">
<div class="md-ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Interceptors
</div>
</div>
<div class="md-footer-nav__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"/></svg>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
<div class="md-footer-copyright__highlight">
Copyright &copy; 2019 Square, Inc.
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/vendor.d1f5a259.min.js"></script>
<script src="../assets/javascripts/bundle.d5fec882.min.js"></script><script id="__lang" type="application/json">{"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents"}</script>
<script>
app = initialize({
base: "..",
features: [],
search: Object.assign({
worker: "../assets/javascripts/worker/search.fae956e7.min.js"
}, typeof search !== "undefined" && search)
})
</script>
</body>
</html>