Client Cert Authentication is common for internal government sites and involves the user installing a private certificate on their PC which the server asks the browser to send while negotiation the SSL connection. Client certs are a PKI cert, and often times are stored on a CAC which is a physical card issued to the user.
It is a requirement that the user hit your site via SSL in order for their browser to send their client cert OR for you to opt into accepting upstream client cert HTTP headers from a proxy or web server that is negotiating your SSL connection. It is recommended you configure your server to either disable HTTP or automatically redirect all HTTP traffic to HTTPS, which can be enabled with the web.SSL.forceSSLRedirect
setting.
Configuring your SSL connection to accept or require client certs is covered in the SSL Client Cert portion of the docs. It's important to note configuring your server to accept SSL client certs and using these certs to authenticate a user two different things. It's possible to accept (or even require) your client (browser) to send a client cert in your web.ssl.clientCert
settings but not use the authentication mechanism to protect parts of your site automatically. Any time a browser has sent a client cert, you will be able to access those details from the CGI
and request
scopes to do your own custom authentication. It is also possible to use Client Cert authentication but not have.
If you have configured your SSL Client Cert settings to accept, but not require client certs, this will allow a user to visit your site and not be challenged to provide a cert until they hit a page that your authPredicate
kicks in and requires authentication. Only then will the user's browser prompt them for a cert.
SSL Renegotiation, when enabled, will disable HTTP/2 AND TLSv1.3. Both of these are not compatible with SSL Renegotiation.
Even if CommandBox is not using SSL directly, but is sitting behind a proxy or web server that takes care of negotiating the client cert, you can still use client cert auth to protect pages on your site if you configure CommandBox to trust any SSL_CLIENT_CERT
HTTP request header.
Only enable this setting if you TRUST your upstream proxy and you know it will overwrite any potentially-malicious SSL_CLIENT_CERT
header from the client. SSL Certs received through this header will appear in the CGI
and request
scope and will be trusted the same as a client cert directly negotiated through CommandBox, but there will be NO trust chain verification. The header will be trusted blindly from your upstream server. This setting is off by default.
You can enable the client cert auth mechanism like so:
Once enabled, all pages on your site will be secured if you have no authPredicate
configured. Otherwise, only pages that match the predicate will be secured.
By default, when you enable client cert auth, CommandBox simply checks that some client cert is present. Remember, your SSL settings require you to provide a Trust Store or a list of trusted root CAs and only client certs which are trusted by one of those CAs will be negotiated. This may be enough security for you right there if you are only allowing certs signed/trusted by a specific root cert. The client cert trust store requires you to explicitly provide every single CA you want trusted. It does NOT use your Operating system's trust store, nor does it use Java's trust store, nor does it use Lucee Servers.
If a request is authorized via a client cert, the Subject distinguished name of the client cert will be present in cgi.remote_user
just like basic auth works.
You can filter down a subset of client certs you want to be accepted for client cert auth by specifying a full or partial subject DN. This will not limit the certs which are negotiated and appear in the CGI
scope. It will only limit the certs which are allowed to provide authentication for pages secured by the authPredicate
. A Subject Distinguished Name (SDN) contains one or more parts known as Relative Distinguished Names, or RDNs. They follow an LDAP name RFC and look like this:
You may provide a single Subject DN ...
or an array of Subject DNs to filter on...
The RDNs can be in any order and you can supply a PARTIAL Subject DN. CommandBox will match all RDNs regardless of order or case sensitivity. You are not required to provide the full Subject DN, but all RDNs you provide MUST be present in the incoming cert or it will be rejected.
You can also filter down a subset of client certs you want to be accepted for client cert auth by specifying a full or partial Issuer DN. This will not limit the certs which are negotiated and appear in the CGI
scope. It will only limit the certs which are allowed to provide authentication for pages secured by the authPredicate
. An Issuer Distinguished Name (IDN) look and work the same as Subject DNs.
You may provide a single Issuer DN ...
or an array of Issuer DNs to filter on...
The RDNs can be in any order and you can supply a PARTIAL Issuer DN. CommandBox will match all RDNs regardless of order or case sensitivity. You are not required to provide the full Issuer DN, but all RDSs you provide MUST be present in the incoming cert or it will be rejected.
If you require more specific parsing of the cert pieces, then you’ll need to disable the built in security in CommandBox and write your own code that runs on every request and parses the CGI variables manually to decide if you accept the cert.
server.json
ConfigurationHere is a look at what your full config could look like in your server.json
. Note this doesn't show the web.ssl.clientCert
settings which are covered here.
It is common to protect pages on your site through your CF code that runs on every request. This does not protect static files like images, plus it can still expose extra surface area of your site for attack. CommandBox has a security system to block certain paths on your site at the web server level, so these requests never reach CF.
There are currently two authentication mechanisms you can enable in CommandBox. Any combination of them can be used to secure the protected portions of your site. When CommandBox determines that the current page requires authentication, it will check each enabled auth mechanism until it finds one that can validate the user.
Basic Authentication is built on a simple username/password list and challenges the user to provide credentials in their browser. Read more here
Client Cert auth is common for internal government sites and involves the user installing a private certificate on their PC which the server asks the browser to send while negotiation the SSL connection. Client certs are a PKI cert, and often times are stored on a CAC which is a physical card issued to the user. Read more here
There are more auth mechanisms we will add in the future including Digest Auth, Header Auth, and SSO. Contact us if you're wanting to sponsor any of these.
If you do not provide an auth predicate but you enable at least one auth mechanism, ALL PAGES on the entire site will be secured. This is quite secure, but often times you only want to protect a subfolder such as /CFIDE/administrator
or /lucee/admin
.
To limit the scope of what pages required authentication, you can specify an auth predicate, which follows the same syntax as Server Rules.
We don't recommend using path()
or path-prefix()
as they are not case sensitive, which can lead to them being easily worked around if you are on Windows. Even regex()
is case-sensitive by default. Only use a case sensitive predicate matcher if your file system and web server are set to be case sensitive! If your server is case sensitive, then the example above can be simplified to this:
The most common auth predicates match a subfolder, but you are not limited to this. Anything valid in a server rule predicate can be used here, including HTTP method, headers, remote IP, etc.
CommandBox's web server supports enabling Basic Auth on your sites.
That will create the following data in your server.json
, which will be picked up the next time you start your server.
If there is no authPredicate
set, basic auth with secure ALL PAGES on the site. Once you set an authPredicate
, only the pages matching the predicate will require authentication.
The old setting location for Basic Auth (web.basicAuth
) will STILL WORK until the next major version of CommandBox, but should be considered deprecated. If both the settings exist (Ex: web.basicAuth.enable
and web.security.basicAuth.enable
), the new location will be given precedence.