Securing subdomains in Caddy with Google Auth
In a previous post I described how to setup a simple blog running Ghost behind Caddy. In this post I will cover adding subdomains to Caddy and securing them behind Google authentication (other authentication methods are possible, but out of scope for this post).
To do this, we'll use the excellent caddy-security module.
First, we'll get a custom build of caddy with the help of xcaddy:
$ go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
$ xcaddy build --with github.com/greenpau/caddy-security
Next, we'll update our Caddyfile as follow (based on this). Here I'm using example.com
as the base domain.
{
order authenticate before respond
order authorize before reverse_proxy
security {
oauth identity provider google {
realm google
driver google
client_id <CLIENT_ID>
client_secret <CLIENT_SECRET>
scopes openid email profile
}
authentication portal myportal {
enable identity provider google
cookie domain example.com
ui {
links {
"My Identity" "/whoami" icon "las la-user"
}
}
transform user {
match realm google
action add role authp/user
}
transform user {
match realm google
// Give this account admin role in the auth portal
match email me@example.com
action add role authp/admin
}
}
authorization policy mypolicy {
set auth url https://auth.example.com/oauth2/google
allow roles authp/admin authp/user
validate bearer header
inject headers with claims
}
}
}
Follow the instructions here to obtain CLIENT_ID and CLIENT_SECRET
Now, to secure any subdomain behind this Google oauth login, you can just add an authorize with
clause, like so:
secure.example.com {
authorize with mypolicy
// other details
}
That's it! You should now get a Google login flow when you try to access secure.example.com
If you are using Plausible with Caddy and wish to secure it behind Google auth, you'll want to exclude the endpoints / assets that it requires client-side for capturing analytics. Something like this worked for me:
analytics.example.com {
handle /js/* {
reverse_proxy <pass through to plausible>
}
handle /api/* {
reverse_proxy <pass through to plausible>
}
authorize with mypolicy
reverse_proxy <pass through to plausible>
}