Client cert auth vs basicauth vs no auth


Within one site/domain, I’d like to be able to do the following things at the same time:

  • let a user in without any auth for a specific path
  • let a user in with either client cert OR basic auth for all the other paths

I’ve followed these topics:

and ended up with the following configuration: {
	root * /usr/share/webapps/example

	handle /noauth.php {
		php_fastcgi unix//run/example/php-fpm.sock

	tls {
		client_auth {
			mode verify_if_given
			trusted_ca_cert_file /etc/caddy/tls.d/ca.crt
	@notlsauth expression {tls_client_subject} == null

	handle {
		basicauth @notlsauth {
			import ../users.d/example

		php_fastcgi unix//run/example/php-fpm.sock

When the site (path /) is opened for the first time, the browser asks if a client cert should be sent (as expected) and then once the cert is sent, the site opens (as expected). However, if the site is reloaded with F5/Ctrl+R, basic auth form pops up.

Is that because tls_client_subject is gone after initial TLS auth? If so, what do I do then to avoid basic auth on a page refresh?

Thank you.

I’m not sure, but I suppose it has to do with how the browser is remembering the TLS client auth. Maybe there’s even a bug where it’s not applying the previously-selected certificate from the last TLS connection, who knows.

Test with curl – always – and if it works there, it’s definitely a browser quirk.

How do I test this with curl properly?

With this:

$ curl -vL --cert-type P12 --cert ~/client.pfx ''

the site “opens” just fine, but this is the first load. How do I simulate page refresh in curl?

Thank you.

I’ve also found out that if Ctrl+Shift+R is pressed in Firefox when basic auth pops up, the site reloads just fine as if FF decides to send the client cert again. But then the issue reoccurs.

I’m confused. Is this about caching? Connection reuse?

mTLS on client machines is a bit more complicated because it involves how your OS manages its secured storage, and how individual browsers manage their encrypted key value storage. Even then, sometimes browsers on Linux will just see the web server requested a cert and just fail the request instead of using Basic Auth, depending on how you set up your credential store (I.e. TPM vs software).

Honestly I would not even bother with both mTLS on end user browsers, I would look into the module caddy-security so you can tie it into your SSO provider and it has much more flexible ways to set rules. Otherwise go mTLS-only, you really should not have Basic Auth deployed anywhere outside of a testing environment or homelab as some lazy security because it doesn’t support MFA.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.