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

breakfix: Adding groups to scopes ends in to many redirects

Open darox opened this issue 2 years ago • 11 comments

After adding groups to scopes, Caddy security isn't working anymore with first "to many redirects" from OIDB and afterwards unauthorised. Groups are visible in the log.

A clear and concise description of what the issue is.

Configuration

Paste full Caddyfile below:

{
	http_port 8080
	order authenticate before respond
	order authorize before basicauth

	security {
		oauth identity provider generic {
			realm generic
			driver generic
			client_id oauth2proxy
			client_secret x
			scopes openid email groups
			base_auth_url https://oidb
			metadata_url https://oidb
		}

		authentication portal myportal {
			crypto default token lifetime 3600
			crypto key sign-verify {env.JWT_SHARED_KEY}
			enable identity provider generic
                        cookie insecure on
			ui {
				links {
					"My Identity" "/whoami" icon "las la-user"
				}
			}

			transform user {
					match realm generic
					match role antora
					action add role authp/user
					
			}

		}

		authorization policy mypolicy {
			set auth url http://auth.site.example:3080/oauth2/generic/authorization-code-callback
			crypto key verify {env.JWT_SHARED_KEY}
			allow roles authp/admin authp/user
			validate bearer header
			inject headers with claims
		}
	}
}


http://auth.site.example {
	authenticate with myportal
}

http://antora.site.example {
	authorize with mypolicy
	root * /usr/share/caddy
	file_server
}

Version Information

Provide output of caddy list-modules -versions | grep git below:

dmin.api.load v2.5.2
admin.api.metrics v2.5.2
admin.api.pki v2.5.2
admin.api.reverse_proxy v2.5.2
caddy.adapters.caddyfile v2.5.2
caddy.config_loaders.http v2.5.2
caddy.listeners.http_redirect v2.5.2
caddy.listeners.tls v2.5.2
caddy.logging.encoders.console v2.5.2
caddy.logging.encoders.filter v2.5.2
caddy.logging.encoders.filter.cookie v2.5.2
caddy.logging.encoders.filter.delete v2.5.2
caddy.logging.encoders.filter.hash v2.5.2
caddy.logging.encoders.filter.ip_mask v2.5.2
caddy.logging.encoders.filter.query v2.5.2
caddy.logging.encoders.filter.regexp v2.5.2
caddy.logging.encoders.filter.rename v2.5.2
caddy.logging.encoders.filter.replace v2.5.2
caddy.logging.encoders.json v2.5.2
caddy.logging.writers.discard v2.5.2
caddy.logging.writers.file v2.5.2
caddy.logging.writers.net v2.5.2
caddy.logging.writers.stderr v2.5.2
caddy.logging.writers.stdout v2.5.2
caddy.storage.file_system v2.5.2
http v2.5.2
http.authentication.hashes.bcrypt v2.5.2
http.authentication.hashes.scrypt v2.5.2
http.authentication.providers.http_basic v2.5.2
http.encoders.gzip v2.5.2
http.encoders.zstd v2.5.2
http.handlers.acme_server v2.5.2
http.handlers.authentication v2.5.2
http.handlers.copy_response v2.5.2
http.handlers.copy_response_headers v2.5.2
http.handlers.encode v2.5.2
http.handlers.error v2.5.2
http.handlers.file_server v2.5.2
http.handlers.headers v2.5.2
http.handlers.map v2.5.2
http.handlers.metrics v2.5.2
http.handlers.push v2.5.2
http.handlers.request_body v2.5.2
http.handlers.reverse_proxy v2.5.2
http.handlers.rewrite v2.5.2
http.handlers.static_response v2.5.2
http.handlers.subroute v2.5.2
http.handlers.templates v2.5.2
http.handlers.tracing v2.5.2
http.handlers.vars v2.5.2
http.matchers.expression v2.5.2
http.matchers.file v2.5.2
http.matchers.header v2.5.2
http.matchers.header_regexp v2.5.2
http.matchers.host v2.5.2
http.matchers.method v2.5.2
http.matchers.not v2.5.2
http.matchers.path v2.5.2
http.matchers.path_regexp v2.5.2
http.matchers.protocol v2.5.2
http.matchers.query v2.5.2
http.matchers.remote_ip v2.5.2
http.matchers.vars v2.5.2
http.matchers.vars_regexp v2.5.2
http.precompressed.br v2.5.2
http.precompressed.gzip v2.5.2
http.precompressed.zstd v2.5.2
http.reverse_proxy.selection_policies.cookie v2.5.2
http.reverse_proxy.selection_policies.first v2.5.2
http.reverse_proxy.selection_policies.header v2.5.2
http.reverse_proxy.selection_policies.ip_hash v2.5.2
http.reverse_proxy.selection_policies.least_conn v2.5.2
http.reverse_proxy.selection_policies.random v2.5.2
http.reverse_proxy.selection_policies.random_choose v2.5.2
http.reverse_proxy.selection_policies.round_robin v2.5.2
http.reverse_proxy.selection_policies.uri_hash v2.5.2
http.reverse_proxy.transport.fastcgi v2.5.2
http.reverse_proxy.transport.http v2.5.2
http.reverse_proxy.upstreams.a v2.5.2
http.reverse_proxy.upstreams.srv v2.5.2
pki v2.5.2
tls v2.5.2
tls.certificates.automate v2.5.2
tls.certificates.load_files v2.5.2
tls.certificates.load_folders v2.5.2
tls.certificates.load_pem v2.5.2
tls.certificates.load_storage v2.5.2
tls.client_auth.leaf v2.5.2
tls.get_certificate.http v2.5.2
tls.get_certificate.tailscale v2.5.2
tls.handshake_match.remote_ip v2.5.2
tls.handshake_match.sni v2.5.2
tls.issuance.acme v2.5.2
tls.issuance.internal v2.5.2
tls.issuance.zerossl v2.5.2
tls.stek.distributed v2.5.2
tls.stek.standard v2.5.2

  Standard modules: 97

http.authentication.providers.authorizer v1.1.14
http.handlers.authenticator v1.1.14
http.handlers.trace v1.1.10
security v1.1.14

  Non-standard modules: 4

  Unknown modules: 0

Expected behavior

It's expected that groups can be verified with: match role antora

darox avatar Aug 18 '22 10:08 darox

Would love to release blog post about securing static sites with Caddy-Security soon. Would you have time to support me in fixing this issue?

darox avatar Aug 26 '22 11:08 darox

@darox , please upgrade to 1.1.15 (latest). The issue may be fixed there. Please report back on your findings

greenpau avatar Aug 26 '22 12:08 greenpau

Good morning

I have just updated to version 1.1.15. After adding groups to the configuration, the login isn't working anymore. See logs below.

oauth identity provider generic {
                                realm generic
                                driver generic
                                client_id oauth2proxy
                                client_secret x
                                scopes openid email groups
                                base_auth_url https://oidb
                                metadata_url https://oidb/.well-known/openid-configuration
                        }

Logs:

{"level":"info","ts":1661749878.4065108,"logger":"security","msg":"Successful login","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"1f78dd33-438a-4bb0-8d12-b6d663771e21","backend":{"name":"generic","realm":"generic","method":"oauth"},"user":{"addr":"127.0.0.1","email":"[email protected]","exp":1661753478,"iat":1661749878,"iss":"http://auth.site.example:3080/oauth2/generic/","jti":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","nbf":1661749818000,"origin":"generic","realm":"generic","roles":["test","authp/user"],"sub":"CiRlM2I0M2Q2MS03OWUwLTQzZjgtOGE0OS01ZTI2NjQxM2VhY2MSBG9pZGI"}}
{"level":"debug","ts":1661749878.5255866,"logger":"security","msg":"Detected cookie-based redirect","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"1f78dd33-438a-4bb0-8d12-b6d663771e21","redirect_url":"http://antora.site.example:3080/home/main/index.html"}
{"level":"debug","ts":1661749878.550247,"logger":"security","msg":"token validation error","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"f2c81172-c563-475c-b782-41a471aa7ff5","error":"no token found"}
{"level":"debug","ts":1661749878.5506225,"logger":"security","msg":"redirecting unauthorized user","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"f2c81172-c563-475c-b782-41a471aa7ff5","method":"location"}
{"level":"error","ts":1661749878.5508537,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed: src_ip=127.0.0.1, src_conn_ip=127.0.0.1, reason: no token found"}
{"level":"debug","ts":1661749878.551244,"logger":"http.log.error","msg":"not authenticated","request":{"remote_ip":"127.0.0.1","remote_port":"45888","proto":"HTTP/1.1","method":"GET","host":"antora.site.example:3080","uri":"/home/main/index.html","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"],"Referer":["http://antora.site.example:3080/"],"Cookie":[],"Connection":["keep-alive"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate"],"Accept-Language":["de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"],"Cache-Control":["max-age=0"],"Upgrade-Insecure-Requests":["1"]}},"duration":0.001085875,"status":401,"err_id":"b3dbwi57k","err_trace":"caddyauth.Authentication.ServeHTTP (caddyauth.go:88)"}
{"level":"debug","ts":1661749878.5514545,"logger":"http.stdlib","msg":"http: superfluous response.WriteHeader call from github.com/caddyserver/caddy/v2/modules/caddyhttp.(*Server).ServeHTTP (server.go:286)"}
{"level":"debug","ts":1661749878.5677576,"logger":"security","msg":"redirect recorded","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"7ca8aaf0-0b6a-4671-9b56-bbac595a13a8","redirect_url":"AUTHP_REDIRECT_URL=http://antora.site.example:3080/home/main/index.html; Domain=site.example; Path=/;"}
{"level":"debug","ts":1661749878.5678654,"logger":"security","msg":"External login requested","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"7ca8aaf0-0b6a-4671-9b56-bbac595a13a8","base_url":"http://auth.site.example:3080","base_path":"/","auth_method":"oauth2","auth_realm":"generic","request_path":"/oauth2/generic"}
{"level":"debug","ts":1661749878.5680022,"logger":"security","msg":"redirecting to OAuth 2.0 endpoint","request_id":"7ca8aaf0-0b6a-4671-9b56-bbac595a13a8","redirect_url":"https://oidb/auth?client_id=oauth2proxy&nonce=3cfgNUulUQ3ljNUM7xwMwqpXpqFCJqxd&redirect_uri=http%3A%2F%2Fauth.site.example%3A3080%2Foauth2%2Fgeneric%2Fauthorization-code-callback&response_type=code&scope=openid+email+groups&state=830aa347-d6fc-4529-8834-e945b98074f8"}
{"level":"debug","ts":1661749878.568098,"logger":"security","msg":"Redirect to authorization server","session_id":"EuGs9Ytav6XqZdwMJuII9Jyl4z6P2Ix9WL7f6ct1qZ","request_id":"7ca8aaf0-0b6a-4671-9b56-bbac595a13a8","url":"https://oidb/auth?client_id=oauth2proxy&nonce=3cfgNUulUQ3ljNUM7xwMwqpXpqFCJqxd&redirect_uri=http%3A%2F%2Fauth.site.example%3A3080%2Foauth2%2Fgeneric%2Fauthorization-code-callback&response_type=code&scope=openid+email+groups&state=830aa347-d6fc-4529-8834-e945b98074f8"}

Thank you

darox avatar Aug 29 '22 05:08 darox

@darox , does it work without “groups”?

greenpau avatar Aug 29 '22 07:08 greenpau

@darox , please add “cookie domain site.example“ to auth portal config.

greenpau avatar Aug 29 '22 07:08 greenpau

@greenpau Thank you for supporting me. Just donated 10$ to you.

I have tried with cookie domain *.site.example and cookie domain site.example

Both are not working as soon I add "groups" to scopes. It ends in a to many redirects and unauthorized in Caddy-Security.

I don't really understand the difference when "groups" is added, except that it is requested from the identity provider. Shouldn't it make no difference as long the following config makes use of "match email" rather than "match roles test"?

transform user {
                                  match realm generic
                                  match email [email protected]
                                  action add role authp/user
                                }

Side note: when I set cookie domain site.example no cookie is set at all. When cookie domain *.site.exampleis set, I can see the cookie in the chrome dev tools.

darox avatar Aug 29 '22 09:08 darox

@darox , the issue is likely that you oauth provider does not allow your use of the “group” scope and therefore rejects it. Here are some of the possibilities.

  1. it could be that the authorization granted initially with oauth scopes are limited to say email only. In that case you could reauthorize.
  2. the “group” scope is not supported by your oauth provider

greenpau avatar Aug 29 '22 12:08 greenpau

@darox , the issue is likely that you oauth provider does not allow your use of the “group” scope and therefore rejects it. Here are some of the possibilities.

  1. it could be that the authorization granted initially with oauth scopes are limited to say email only. In that case you could reauthorize.

  2. the “group” scope is not supported by your oauth provider

It's definitely supported. I can see the groups in the logs. With Oauth2-proxy I got it up and running.

darox avatar Aug 29 '22 13:08 darox

@darox , what is your timezone? We could hop on Google Meet and try looking at it closer.

greenpau avatar Aug 29 '22 13:08 greenpau

@darox , what is your timezone? We could hop on Google Meet and try looking at it closer.

GMT+2 sure

darox avatar Aug 29 '22 13:08 darox

@darox , i am est (ny). Please let me know a few timeslots for tomorrow via email greenpau at outlook.com

greenpau avatar Aug 29 '22 13:08 greenpau