caddy-security icon indicating copy to clipboard operation
caddy-security copied to clipboard

breakfix: Token validation error/No token found

Open cceslick opened this issue 3 years ago • 3 comments

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)"}


cceslick avatar Jul 08 '22 20:07 cceslick

Checking if you have any thoughts on this @greenpau

cceslick avatar Jul 11 '22 15:07 cceslick

@cceslick , apologies, will try finding time to look into this over the next weekend. Busy at work.

greenpau avatar Jul 11 '22 16:07 greenpau

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"

cceslick avatar Jul 19 '22 00:07 cceslick