An APIac.Authenticator
plug implementing section 2 of
OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
(RFC8705)
Using this scheme, authentication is performed thanks to 2 elements:
- TLS client certificate authentication
- the
client_id
parameter of theapplication/x-www-form-urlencoded
body
TLS client certificate authentication may be performed thanks to two methods:
- authentication with a certificate issued by a Certificate Authority (CA) which is called
PKI Mutual-TLS Method.
In this case, one of the following certificate attribute is checked against
this attribute registered for the
client_id
:- Distinguished name
- SAN DNS
- SAN URI
- SAN IP address
- SAN email
- authentication with a self-signed, self-issued certificate which is called
Self-Signed Certificate Mutual-TLS Method.
In this case, the certificate is checked against the subject public key info
of the registered certificates of the
client_id
def deps do
[
{:apiac_auth_mtls, "~> 1.0"},
]
end
:allowed_methods
: one of:pki
,:selfsigned
or:both
. No default value, mandatory option:pki_callback
: a(String.t -> String.t | {tls_client_auth_subject_value(), String.t()} | nil)
function that takes theclient_id
as a parameter and returns its DN as aString.t()
or{tls_client_auth_subject_value(), String.t()}
ornil
if no DN is registered for that client. When not:tls_client_auth_subject_value/0
is specified, defaults to:tls_client_auth_subject_dn
:selfsigned_callback
: a(String.t -> binary() | [binary()] | nil)
function that takes theclient_id
as a parameter and returns the certificate or the list of the certificate forthe client_id
, ornil
if no certificate is registered for that client. Certificates can be returned in DER-encoded format, or native OTP certificate structure:cert_data_origin
: origin of the peer cert data. Can be set to::native
: the peer certificate data is retrieved from the connection. Only works when this plug is used at the TLS termination endpoint. This is the default value{:header_param, "Header-Name"}
: the peer certificate data, and more specifically the parameter upon which the decision is to be made, is retrieved from an HTTP header. When using this feature, make sure that this header is filtered by a n upstream system (reverse-proxy...) so that malicious users cannot inject the value themselves. For instance, the configuration could be set to:{:header_param, "SSL_CLIENT_DN"}
. If there are several values for the parameter (for instance severaldNSName
), they must be sent in separate headers. Not compatible with self-signed certiticate authentication:header_cert
: the whole certificate is forwarded in the"Client-Cert"
HTTP header as a Base64 encoded value of the certificate's DER serialization, in conformance with Client-Cert HTTP Header: Conveying Client Certificate Information from TLS Terminating Reverse Proxies to Origin Server Applications (draft-bdc-something-something-certificate-01){:header_cert, "Header-Name"}
: the whole certificate is forwarded in the "Header-Name" HTTP header as a Base64 encoded value of the certificate's DER serialization{:header_cert_pem, "Header-Name"}
: the whole certificate is forwarded in the "Header-Name" as a PEM-encoded string and retrieved by this plug
:set_error_response
: function called when authentication failed. Defaults toAPIacAuthMTLS.send_error_response/3
:error_response_verbosity
: one of:debug
,:normal
or:minimal
. Defaults to:normal
plug APIacAuthMTLS, allowed_methods: :both,
selfsigned_callback: &selfsigned_certs/1,
pki_callback: &get_dn/1
# further
defp selfsigned_certs(client_id) do
:ets.lookup_element(:clients, :client_id, 5)
end
defp get_dn("client-1") do
"/C=US/ST=ARI/L=Chicago/O=Agora/CN=API access certificate"
end
defp get_dn(_), do: nil
See the module's information for further information, examples, and the security considerations.