<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Loïc Hoguin based on a design from (Soft10) Pol Cámara">
<meta name="generator" content="Hugo 0.37.1" />
<title>Nine Nines: SSL client authentication</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic' rel='stylesheet' type='text/css'>
<link href="/css/99s.css?r=1" rel="stylesheet">
<link rel="shortcut icon" href="/img/ico/favicon.ico">
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/ico/apple-touch-icon-114.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/ico/apple-touch-icon-72.png">
<link rel="apple-touch-icon-precomposed" href="/img/ico/apple-touch-icon-57.png">
</head>
<body class="">
<header id="page-head">
<div id="topbar" class="container">
<div class="row">
<div class="span2">
<h1 id="logo"><a href="/" title="99s">99s</a></h1>
</div>
<div class="span10">
<div id="side-header">
<nav>
<ul>
<li><a title="Hear my thoughts" href="/articles">Articles</a></li>
<li><a title="Watch my talks" href="/talks">Talks</a></li>
<li class="active"><a title="Read the docs" href="/docs">Documentation</a></li>
<li><a title="Request my services" href="/services">Consulting & Training</a></li>
</ul>
</nav>
<ul id="social">
<li>
<a href="https://github.com/ninenines" title="Check my Github repositories"><img src="/img/ico_github.png" data-hover="/img/ico_github_alt.png" alt="Github"></a>
</li>
<li>
<a title="Contact me" href="mailto:[email protected]"><img src="/img/ico_mail.png" data-hover="/img/ico_mail_alt.png"></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</header>
<div id="contents" class="two_col">
<div class="container">
<div class="row">
<div id="docs" class="span9 maincol">
<h1 class="lined-header"><span>SSL client authentication</span></h1>
<div class="sect1">
<h2 id="_purpose">Purpose</h2>
<div class="sectionbody">
<div class="paragraph"><p>SSL client authentication is a mechanism allowing applications to
identify certificates. This allows your application to make sure that
the client is an authorized certificate, but makes no claim about
whether the user can be trusted. This can be combined with a password
based authentication to attain greater security.</p></div>
<div class="paragraph"><p>The server only needs to retain the certificate serial number and
the certificate issuer to authenticate the certificate. Together,
they can be used to uniquely identify a certicate.</p></div>
<div class="paragraph"><p>As Ranch allows the same protocol code to be used for both SSL and
non-SSL transports, you need to make sure you are in an SSL context
before attempting to perform an SSL client authentication. This
can be done by checking the return value of <code>Transport:name/0</code>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_obtaining_client_certificates">Obtaining client certificates</h2>
<div class="sectionbody">
<div class="paragraph"><p>You can obtain client certificates from various sources. You can
generate them yourself, or you can use a service like CAcert.org
which allows you to generate client and server certificates for
free.</p></div>
<div class="paragraph"><p>Following are the steps you need to take to create a CAcert.org
account, generate a certificate and install it in your favorite
browser.</p></div>
<div class="ulist"><ul>
<li>
<p>
Open <a href="http://cacert.org">http://cacert.org</a> in your favorite browser
</p>
</li>
<li>
<p>
Root Certificate link: install both certificates
</p>
</li>
<li>
<p>
Join (Register an account)
</p>
</li>
<li>
<p>
Verify your account (check your email inbox!)
</p>
</li>
<li>
<p>
Log in
</p>
</li>
<li>
<p>
Client Certificates: New
</p>
</li>
<li>
<p>
Follow instructions to create the certificate
</p>
</li>
<li>
<p>
Install the certificate in your browser
</p>
</li>
</ul></div>
<div class="paragraph"><p>You can optionally save the certificate for later use, for example
to extract the <code>IssuerID</code> information as will be detailed later on.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_transport_configuration">Transport configuration</h2>
<div class="sectionbody">
<div class="paragraph"><p>The SSL transport does not request a client certificate by default.
You need to specify the <code>{verify, verify_peer}</code> option when starting
the listener to enable this behavior.</p></div>
<div class="listingblock">
<div class="title">Configure a listener for SSL authentication</div>
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>{<span style="color: #FF6600">ok</span>, <span style="color: #990000">_</span>} <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">ranch:start_listener</span></span>(<span style="color: #FF6600">my_ssl</span>,
<span style="color: #FF6600">ranch_ssl</span>, [
{<span style="color: #FF6600">port</span>, <span style="color: #009900">SSLPort</span>},
{<span style="color: #FF6600">certfile</span>, <span style="color: #009900">PathToCertfile</span>},
{<span style="color: #FF6600">cacertfile</span>, <span style="color: #009900">PathToCACertfile</span>},
{<span style="color: #FF6600">verify</span>, <span style="color: #FF6600">verify_peer</span>}
],
<span style="color: #FF6600">my_protocol</span>, []
)<span style="color: #990000">.</span></tt></pre></div></div>
<div class="paragraph"><p>In this example we set the required <code>port</code> and <code>certfile</code>, but also
the <code>cacertfile</code> containing the CACert.org root certificate, and
the option to request the client certificate.</p></div>
<div class="paragraph"><p>If you enable the <code>{verify, verify_peer}</code> option and the client does
not have a client certificate configured for your domain, then no
certificate will be sent. This allows you to use SSL for more than
just authenticated clients.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_authentication">Authentication</h2>
<div class="sectionbody">
<div class="paragraph"><p>To authenticate users, you must first save the certificate information
required. If you have your users' certificate files, you can simply
load the certificate and retrieve the information directly.</p></div>
<div class="listingblock">
<div class="title">Retrieve the issuer ID from a certificate</div>
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #000000">certfile_to_issuer_id</span></span>(<span style="color: #009900">Filename</span>) <span style="color: #990000">-></span>
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">Data</span>} <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">file:read_file</span></span>(<span style="color: #009900">Filename</span>),
[{<span style="color: #FF6600">'Certificate'</span>, <span style="color: #009900">Cert</span>, <span style="color: #FF6600">not_encrypted</span>}] <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">public_key:pem_decode</span></span>(<span style="color: #009900">Data</span>),
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">IssuerID</span>} <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">public_key:pkix_issuer_id</span></span>(<span style="color: #009900">Cert</span>, <span style="font-weight: bold"><span style="color: #000080">self</span></span>),
<span style="color: #009900">IssuerID</span><span style="color: #990000">.</span></tt></pre></div></div>
<div class="paragraph"><p>The <code>IssuerID</code> variable contains both the certificate serial number
and the certificate issuer stored in a tuple, so this value alone can
be used to uniquely identify the user certificate. You can save this
value in a database, a configuration file or any other place where an
Erlang term can be stored and retrieved.</p></div>
<div class="paragraph"><p>To retrieve the <code>IssuerID</code> from a running connection, you need to first
retrieve the client certificate and then extract this information from
it. Ranch does not provide a function to retrieve the client certificate.
Instead you can use the <code>ssl:peercert/1</code> function. Once you have the
certificate, you can again use the <code>public_key:pkix_issuer_id/2</code> to
extract the <code>IssuerID</code> value.</p></div>
<div class="paragraph"><p>The following function returns the <code>IssuerID</code> or <code>false</code> if no client
certificate was found. This snippet is intended to be used from your
protocol code.</p></div>
<div class="listingblock">
<div class="title">Retrieve the issuer ID from the certificate for the current connection</div>
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #000000">socket_to_issuer_id</span></span>(<span style="color: #009900">Socket</span>) <span style="color: #990000">-></span>
<span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">ssl:peercert</span></span>(<span style="color: #009900">Socket</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span>
{<span style="color: #FF6600">error</span>, <span style="color: #FF6600">no_peercert</span>} <span style="color: #990000">-></span>
<span style="color: #000080">false</span>;
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">Cert</span>} <span style="color: #990000">-></span>
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">IssuerID</span>} <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">public_key:pkix_issuer_id</span></span>(<span style="color: #009900">Cert</span>, <span style="font-weight: bold"><span style="color: #000080">self</span></span>),
<span style="color: #009900">IssuerID</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span></tt></pre></div></div>
<div class="paragraph"><p>You then only need to match the <code>IssuerID</code> value to authenticate the
user.</p></div>
</div>
</div>
<nav style="margin:1em 0">
<a style="float:left" href="https://ninenines.eu/docs/en/ranch/1.4/guide/parsers/">
Writing parsers
</a>
<a style="float:right" href="https://ninenines.eu/docs/en/ranch/1.4/guide/internals/">
Internals
</a>
</nav>
</div>
<div class="span3 sidecol">
<h3>
Ranch
1.4
User Guide
</h3>
<ul>
<li><a href="/docs/en/ranch/1.4/guide">User Guide</a></li>
<li><a href="/docs/en/ranch/1.4/manual">Function Reference</a></li>
</ul>
<h4 id="docs-nav">Navigation</h4>
<h4>Version select</h4>
<ul>
<li><a href="/docs/en/ranch/1.4/guide">1.4</a></li>
<li><a href="/docs/en/ranch/1.3/guide">1.3</a></li>
<li><a href="/docs/en/ranch/1.2/guide">1.2</a></li>
</ul>
</div>
</div>
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="span6">
<p id="scroll-top"><a href="#">↑ Scroll to top</a></p>
<nav>
<ul>
<li><a href="mailto:[email protected]" title="Contact us">Contact us</a></li><li><a href="https://github.com/ninenines/ninenines.github.io" title="Github repository">Contribute to this site</a></li>
</ul>
</nav>
</div>
<div class="span6 credits">
<p><img src="/img/footer_logo.png"></p>
<p>Copyright © Loïc Hoguin 2012-2018</p>
</div>
</div>
</div>
</footer>
<script src="/js/custom.js"></script>
</body>
</html>