ssl_auth.asciidoc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. == SSL client authentication
  2. === Purpose
  3. SSL client authentication is a mechanism allowing applications to
  4. identify certificates. This allows your application to make sure that
  5. the client is an authorized certificate, but makes no claim about
  6. whether the user can be trusted. This can be combined with a password
  7. based authentication to attain greater security.
  8. The server only needs to retain the certificate serial number and
  9. the certificate issuer to authenticate the certificate. Together,
  10. they can be used to uniquely identify a certicate.
  11. As Ranch allows the same protocol code to be used for both SSL and
  12. non-SSL transports, you need to make sure you are in an SSL context
  13. before attempting to perform an SSL client authentication. This
  14. can be done by checking the return value of `Transport:name/0`.
  15. === Obtaining client certificates
  16. You can obtain client certificates from various sources. You can
  17. generate them yourself, or you can use a service like CAcert.org
  18. which allows you to generate client and server certificates for
  19. free.
  20. Following are the steps you need to take to create a CAcert.org
  21. account, generate a certificate and install it in your favorite
  22. browser.
  23. * Open http://cacert.org in your favorite browser
  24. * Root Certificate link: install both certificates
  25. * Join (Register an account)
  26. * Verify your account (check your email inbox!)
  27. * Log in
  28. * Client Certificates: New
  29. * Follow instructions to create the certificate
  30. * Install the certificate in your browser
  31. You can optionally save the certificate for later use, for example
  32. to extract the `IssuerID` information as will be detailed later on.
  33. === Transport configuration
  34. The SSL transport does not request a client certificate by default.
  35. You need to specify the `{verify, verify_peer}` option when starting
  36. the listener to enable this behavior.
  37. .Configure a listener for SSL authentication
  38. [source,erlang]
  39. {ok, _} = ranch:start_listener(my_ssl,
  40. ranch_ssl, [
  41. {port, SSLPort},
  42. {certfile, PathToCertfile},
  43. {cacertfile, PathToCACertfile},
  44. {verify, verify_peer}
  45. ],
  46. my_protocol, []
  47. ).
  48. In this example we set the required `port` and `certfile`, but also
  49. the `cacertfile` containing the CACert.org root certificate, and
  50. the option to request the client certificate.
  51. If you enable the `{verify, verify_peer}` option and the client does
  52. not have a client certificate configured for your domain, then no
  53. certificate will be sent. This allows you to use SSL for more than
  54. just authenticated clients.
  55. === Authentication
  56. To authenticate users, you must first save the certificate information
  57. required. If you have your users' certificate files, you can simply
  58. load the certificate and retrieve the information directly.
  59. .Retrieve the issuer ID from a certificate
  60. [source,erlang]
  61. ----
  62. certfile_to_issuer_id(Filename) ->
  63. {ok, Data} = file:read_file(Filename),
  64. [{'Certificate', Cert, not_encrypted}] = public_key:pem_decode(Data),
  65. {ok, IssuerID} = public_key:pkix_issuer_id(Cert, self),
  66. IssuerID.
  67. ----
  68. The `IssuerID` variable contains both the certificate serial number
  69. and the certificate issuer stored in a tuple, so this value alone can
  70. be used to uniquely identify the user certificate. You can save this
  71. value in a database, a configuration file or any other place where an
  72. Erlang term can be stored and retrieved.
  73. To retrieve the `IssuerID` from a running connection, you need to first
  74. retrieve the client certificate and then extract this information from
  75. it. Ranch does not provide a function to retrieve the client certificate.
  76. Instead you can use the `ssl:peercert/1` function. Once you have the
  77. certificate, you can again use the `public_key:pkix_issuer_id/2` to
  78. extract the `IssuerID` value.
  79. The following function returns the `IssuerID` or `false` if no client
  80. certificate was found. This snippet is intended to be used from your
  81. protocol code.
  82. .Retrieve the issuer ID from the certificate for the current connection
  83. [source,erlang]
  84. ----
  85. socket_to_issuer_id(Socket) ->
  86. case ssl:peercert(Socket) of
  87. {error, no_peercert} ->
  88. false;
  89. {ok, Cert} ->
  90. {ok, IssuerID} = public_key:pkix_issuer_id(Cert, self),
  91. IssuerID
  92. end.
  93. ----
  94. You then only need to match the `IssuerID` value to authenticate the
  95. user.