breakfix: Token validation error/No token found
Describe the issue
I upgraded from 1.0.5 to the latest 1.1.14 release. I am now seeing odd behavior. I am using caddy-security to provide inline Google authentication to certain directories on two internal sites on different subdomains. One site is https while the other is http. The https site usually works, while the http site repeatedly asks for authentication or gets stuck in a redirect loop. When I start changing settings, restarting Caddy, and flushing caches, the result is usually both sites stop working for a while.
The main change after the upgrade was removing the old "backend" directive and adding
oauth identity provider google <client_id>.apps.googleusercontent.com <client_secret>
And under the authentication portal:
enable identity provider google
Otherwise, the configuration is the same. Since I am mixing http and https, I am using cookie insecure on and cookie domain my-domain. I’ve also tried cookie strip domain
Configuration
Paste full Caddyfile below:
{
order authorize before reverse_proxy
order authenticate before authorize
security {
oauth identity provider google <client_id>.googleusercontent.com <client_secret>
authentication portal myportal {
enable identity provider google
cookie insecure on
cookie domain my.domain
# cookie strip domain
ui {
links {
"My Identity" "/auth/whoami" icon "las la-star"
}
}
transform user {
match origin google
suffix match email @my.domain
action add role authp/user host2_user
ui link "Host1 Access" "https://host1.my.domain/folder"
}
transform user {
match origin google
suffix match email @sub.my.domain
action add role host2_user
}
transform user {
match origin google
match email [email protected]
action add role authp/admin
}
transform user {
match origin google
suffix match email @gmail.com
block
}
}
authorization policy host1policy {
set auth url https://auth.my.domain/auth/oauth2/google
allow roles authp/admin authp/user
}
authorization policy host2policy {
set auth url https://auth.my.domain/auth/oauth2/google
allow roles host2_user
}
}
}
auth.my.domain {
route /auth* {
authenticate * with myportal
}
log {
output file auth.log
}
}
host1.my.domain {
route /folder* {
authorize with host1policy
reverse_proxy https://host1.my.domain
}
# Access to all other directories pass through without authentication
route {
reverse_proxy https://host1.my.domain
}
log {
output file host1.log
}
}
http://host2.my.domain {
route /folder* {
authorize with host2policy
reverse_proxy http://host2.my.domain
}
# No other access is allowed to this server
log {
output file host2.log
}
}
This is running on a Windows virtual machine
Version Information
Provide output of caddy list-modules -versions | grep git below:
admin.api.load
admin.api.metrics
admin.api.load v2.5.1
admin.api.metrics v2.5.1
admin.api.pki v2.5.1
admin.api.reverse_proxy v2.5.1
caddy.adapters.caddyfile v2.5.1
caddy.config_loaders.http v2.5.1
caddy.listeners.http_redirect v2.5.1
caddy.listeners.tls v2.5.1
caddy.logging.encoders.console v2.5.1
caddy.logging.encoders.filter v2.5.1
caddy.logging.encoders.filter.cookie v2.5.1
caddy.logging.encoders.filter.delete v2.5.1
caddy.logging.encoders.filter.hash v2.5.1
caddy.logging.encoders.filter.ip_mask v2.5.1
caddy.logging.encoders.filter.query v2.5.1
caddy.logging.encoders.filter.regexp v2.5.1
caddy.logging.encoders.filter.rename v2.5.1
caddy.logging.encoders.filter.replace v2.5.1
caddy.logging.encoders.json v2.5.1
caddy.logging.writers.discard v2.5.1
caddy.logging.writers.file v2.5.1
caddy.logging.writers.net v2.5.1
caddy.logging.writers.stderr v2.5.1
caddy.logging.writers.stdout v2.5.1
caddy.storage.file_system v2.5.1
http v2.5.1
http.authentication.hashes.bcrypt v2.5.1
http.authentication.hashes.scrypt v2.5.1
http.authentication.providers.http_basic v2.5.1
http.encoders.gzip v2.5.1
http.encoders.zstd v2.5.1
http.handlers.acme_server v2.5.1
http.handlers.authentication v2.5.1
http.handlers.copy_response v2.5.1
http.handlers.copy_response_headers v2.5.1
http.handlers.encode v2.5.1
http.handlers.error v2.5.1
http.handlers.file_server v2.5.1
http.handlers.headers v2.5.1
http.handlers.map v2.5.1
http.handlers.metrics v2.5.1
http.handlers.push v2.5.1
http.handlers.request_body v2.5.1
http.handlers.reverse_proxy v2.5.1
http.handlers.rewrite v2.5.1
http.handlers.static_response v2.5.1
http.handlers.subroute v2.5.1
http.handlers.templates v2.5.1
http.handlers.tracing v2.5.1
http.handlers.vars v2.5.1
http.matchers.expression v2.5.1
http.matchers.file v2.5.1
http.matchers.header v2.5.1
http.matchers.header_regexp v2.5.1
http.matchers.host v2.5.1
http.matchers.method v2.5.1
http.matchers.not v2.5.1
http.matchers.path v2.5.1
http.matchers.path_regexp v2.5.1
http.matchers.protocol v2.5.1
http.matchers.query v2.5.1
http.matchers.remote_ip v2.5.1
http.matchers.vars v2.5.1
http.matchers.vars_regexp v2.5.1
http.precompressed.br v2.5.1
http.precompressed.gzip v2.5.1
http.precompressed.zstd v2.5.1
http.reverse_proxy.selection_policies.cookie v2.5.1
http.reverse_proxy.selection_policies.first v2.5.1
http.reverse_proxy.selection_policies.header v2.5.1
http.reverse_proxy.selection_policies.ip_hash v2.5.1
http.reverse_proxy.selection_policies.least_conn v2.5.1
http.reverse_proxy.selection_policies.random v2.5.1
http.reverse_proxy.selection_policies.random_choose v2.5.1
http.reverse_proxy.selection_policies.round_robin v2.5.1
http.reverse_proxy.selection_policies.uri_hash v2.5.1
http.reverse_proxy.transport.fastcgi v2.5.1
http.reverse_proxy.transport.http v2.5.1
http.reverse_proxy.upstreams.a v2.5.1
http.reverse_proxy.upstreams.srv v2.5.1
pki v2.5.1
tls v2.5.1
tls.certificates.automate v2.5.1
tls.certificates.load_files v2.5.1
tls.certificates.load_folders v2.5.1
tls.certificates.load_pem v2.5.1
tls.certificates.load_storage v2.5.1
tls.get_certificate.http v2.5.1
tls.get_certificate.tailscale v2.5.1
tls.handshake_match.remote_ip v2.5.1
tls.handshake_match.sni v2.5.1
tls.issuance.acme v2.5.1
tls.issuance.internal v2.5.1
tls.issuance.zerossl v2.5.1
tls.stek.distributed v2.5.1
tls.stek.standard v2.5.1
Standard modules: 96
http.authentication.providers.authorizer v1.1.14
http.handlers.authenticator v1.1.14
security v1.1.14
Non-standard modules: 3
Unknown modules: 0
Expected behavior
Should authenticate and then proceed to the directories on the internal web servers.
Additional context
Below is a section of the error log showing "token validation" and "no token found" errors. Whoami shows that I am authenticated with the correct roles.
{"level":"debug","ts":1657308602.3051364,"logger":"security","msg":"Detected cookie-based redirect","session_id":"5wgAaqP0t3VYQLy29qBebpTziBkIfISwVt2DepmV04Pat","request_id":"8938c7d3-2c9f-4a93-b1eb-c416c63f97cb","redirect_url":"http://host2.my.domain/folder/"}
{"level":"debug","ts":1657308602.3097517,"logger":"security","msg":"token validation error","session_id":"","request_id":"7d29e514-f6d0-4473-b9a9-66a4b151c6e9","error":"no token found"}
{"level":"debug","ts":1657308602.3097517,"logger":"security","msg":"redirecting unauthorized user","session_id":"","request_id":"7d29e514-f6d0-4473-b9a9-66a4b151c6e9","method":"location"}
{"level":"error","ts":1657308602.3097517,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed: src_ip=ip-address, src_conn_ip=ip-address, reason: no token found"}
{"level":"debug","ts":1657308602.3097517,"logger":"http.log.error.log2","msg":"not authenticated","request":{"remote_ip":"ip-address","remote_port":"52357","proto":"HTTP/1.1","method":"GET","host":"host2.my.domain","uri":"/folder/","headers":{"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0"],"Accept-Language":["en-US,en;q=0.5"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"],"Cookie":[],"Cache-Control":["max-age=0"]}},"duration":0,"status":401,"err_id":"fspb0we2z","err_trace":"caddyauth.Authentication.ServeHTTP (caddyauth.go:88)"}
Checking if you have any thoughts on this @greenpau
@cceslick , apologies, will try finding time to look into this over the next weekend. Busy at work.
I changed
cookie domain my.domain
to
cookie domain *.my.domain
and it started working. This allowed the cookies to work for host1.my.domain (https) and host2.my.domain (http) without the redirect loop. This was not necessary with older version I was using (1.0.5) and I don't see any mention of a wildcard being required. Was there a change?
Does the rest of the Caddyfile look correct? I'm not entirely sure when "route" should be used over "handle"