123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- == SSL client authentication
- === Purpose
- 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.
- 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.
- 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 `Transport:name/0`.
- === Obtaining client certificates
- 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.
- Following are the steps you need to take to create a CAcert.org
- account, generate a certificate and install it in your favorite
- browser.
- * Open http://cacert.org in your favorite browser
- * Root Certificate link: install both certificates
- * Join (Register an account)
- * Verify your account (check your email inbox!)
- * Log in
- * Client Certificates: New
- * Follow instructions to create the certificate
- * Install the certificate in your browser
- You can optionally save the certificate for later use, for example
- to extract the `IssuerID` information as will be detailed later on.
- === Transport configuration
- The SSL transport does not request a client certificate by default.
- You need to specify the `{verify, verify_peer}` option when starting
- the listener to enable this behavior.
- .Configure a listener for SSL authentication
- [source,erlang]
- {ok, _} = ranch:start_listener(my_ssl,
- ranch_ssl, [
- {port, SSLPort},
- {certfile, PathToCertfile},
- {cacertfile, PathToCACertfile},
- {verify, verify_peer}
- ],
- my_protocol, []
- ).
- In this example we set the required `port` and `certfile`, but also
- the `cacertfile` containing the CACert.org root certificate, and
- the option to request the client certificate.
- If you enable the `{verify, verify_peer}` 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.
- === Authentication
- 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.
- .Retrieve the issuer ID from a certificate
- [source,erlang]
- ----
- certfile_to_issuer_id(Filename) ->
- {ok, Data} = file:read_file(Filename),
- [{'Certificate', Cert, not_encrypted}] = public_key:pem_decode(Data),
- {ok, IssuerID} = public_key:pkix_issuer_id(Cert, self),
- IssuerID.
- ----
- The `IssuerID` 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.
- To retrieve the `IssuerID` 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 `ssl:peercert/1` function. Once you have the
- certificate, you can again use the `public_key:pkix_issuer_id/2` to
- extract the `IssuerID` value.
- The following function returns the `IssuerID` or `false` if no client
- certificate was found. This snippet is intended to be used from your
- protocol code.
- .Retrieve the issuer ID from the certificate for the current connection
- [source,erlang]
- ----
- socket_to_issuer_id(Socket) ->
- case ssl:peercert(Socket) of
- {error, no_peercert} ->
- false;
- {ok, Cert} ->
- {ok, IssuerID} = public_key:pkix_issuer_id(Cert, self),
- IssuerID
- end.
- ----
- You then only need to match the `IssuerID` value to authenticate the
- user.
|