greenpau / caddy-security

🔐 Authentication, Authorization, and Accounting (AAA) App and Plugin for Caddy v2. 💎 Implements Form-Based, Basic, Local, LDAP, OpenID Connect, OAuth 2.0 (Github, Google, Facebook, Okta, etc.), SAML Authentication. MFA/2FA with App Authenticators and Yubico. 💎 Authorization with JWT/PASETO tokens. 🔐
https://authcrunch.com/
Apache License 2.0
1.37k stars 70 forks source link

OAuth successfull login redirects back to /login #352

Closed alternativc closed 2 weeks ago

alternativc commented 1 month ago

Describe the issue

Hey team, I have successfully configured Google OAuth and receive successful login attempts in the logs, however the app always serves a 302 redirect back to /login. Effectively denying access to the portal.

Configuration

Caddyfile

{
        order authenticate before respond
        order authorize before basicauth

        security {
                oauth identity provider google {
                        realm google
                        driver google
                        client_id XXX.apps.googleusercontent.com
                        client_secret XXX
                        scopes openid email profile
                }

                authentication portal myportal {
                        crypto default token lifetime 3600
                        #crypto key sign-verify {env.JWT_SHARED_KEY}
                        crypto key sign-verify XXX
                        enable identity provider google
                        cookie domain xxx.dev
                        ui {
                                links {
                                        "My Identity" "/whoami" icon "las la-user"
                                        "Grafana" https://swarmgraf.xxx.dev
                                }
                        }

                        transform user {
                                match realm google
                                action add role authp/user
                                ui link "Portal Settings" /settings icon "las la-cog"
                        }

                }

                authorization policy mypolicy {
                    # disable auth redirect
                    set auth url https://auth.xxx.dev/oauth2/google
                    #crypto key verify {env.JWT_SHARED_KEY}
                    crypto key verify XXX
                    allow roles authp/user
                    validate bearer header
                    inject headers with claims
                }
        }
}

auth.xxx.dev {
        route {
                authenticate with myportal
        }
}

Debug logs:

{"level":"debug","ts":1721063270.4400585,"logger":"security","msg":"External login requested","session_id":"QdF02HTC6L8pjUyOYVTQtAIw7ThmpNeSiqYEl","request_id":"241f4ad3-658d-406d-b2a3-1a826b8d7081","base_url":"https://auth.xxx.dev","base_path":"/","auth_method":"oauth2","auth_realm":"google","request_path":"/oauth2/google"}
{"level":"debug","ts":1721063270.4404337,"logger":"security","msg":"redirecting to OAuth 2.0 endpoint","request_id":"241f4ad3-658d-406d-b2a3-1a826b8d7081","redirect_url":"https://accounts.google.com/o/oauth2/v2/auth?client_id=236153619145-4lge8uofv6mo7lo82hkevsegdcl0bruj.apps.googleusercontent.com&nonce=z70sdYCfv9TeCiYjHT3AasLYDdaZN9rj&redirect_uri=https%3A%2F%2Fauth.xxx.dev%2Foauth2%2Fgoogle%2Fauthorization-code-callback&response_type=code&scope=openid+email+profile&state=6970db71-f02e-4d1e-b877-06e8266ac43d"}
{"level":"debug","ts":1721063270.44059,"logger":"security","msg":"Redirect to authorization server","session_id":"QdF02HTC6L8pjUyOYVTQtAIw7ThmpNeSiqYEl","request_id":"241f4ad3-658d-406d-b2a3-1a826b8d7081","url":"https://accounts.google.com/o/oauth2/v2/auth?client_id=236153619145-4lge8uofv6mo7lo82hkevsegdcl0bruj.apps.googleusercontent.com&nonce=z70sdYCfv9TeCiYjHT3AasLYDdaZN9rj&redirect_uri=https%3A%2F%2Fauth.xxx.dev%2Foauth2%2Fgoogle%2Fauthorization-code-callback&response_type=code&scope=openid+email+profile&state=6970db71-f02e-4d1e-b877-06e8266ac43d"}
{"level":"debug","ts":1721063278.8783612,"logger":"security","msg":"External login requested","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","base_url":"https://auth.xxx.dev","base_path":"/","auth_method":"oauth2","auth_realm":"google","request_path":"/oauth2/google/authorization-code-callback"}
{"level":"debug","ts":1721063278.878742,"logger":"security","msg":"received OAuth 2.0 response","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","params":{"authuser":["0"],"code":["4/0AcvDMrAFXsM30gCGhPluLbcmhWm-mp6HKieb1WScZQqeKClic7QiIIovMhGwW2O4xBlsVQ"],"hd":["xxxx.swiss"],"prompt":["none"],"scope":["email profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid"],"state":["6970db71-f02e-4d1e-b877-06e8266ac43d"]}}
{"level":"debug","ts":1721063278.8792846,"logger":"security","msg":"received OAuth 2.0 code and state from the authorization server","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","state":"6970db71-f02e-4d1e-b877-06e8266ac43d","code":"4/0AcvDMrAFXsM30gCGhPluLbcmhWm-mp6HKieb1WScZQqeKClic7QiIIovMhGwW2O4xBlsVQ"}
{"level":"debug","ts":1721063278.9764767,"logger":"security","msg":"OAuth 2.0 access token response received","body":"ewogICJhY2Nlc3NfdG9rZW4iOiAieWEyOS5hMEFYb29DZ3VKcXVuRGNTVE16WEZOVC05dkxmMUpya3JDNlZPSHFHYldCLUdOMk5SMFk1VlhDVUdtY0tPazc2dkFMa1l5enpOT3lLUkRER2lWWGQ5R2RxVm9MLVJLRml5bmJtY3B0V1JpbWthYjNlM0swUVhFdDI2T1d3TWFfaWh5ZF82SnlvNElGUjB1MUxTQ18wM2xTS3NoYmttaURGVEFzd2FDZ1lLQWU4U0FSTVNGUUhHWDJNaTZGdkZJTlpPdzZIWV90c1ZHQmVpc0EwMTY5IiwKICAiZXhwaXJlc19pbiI6IDM1OTksCiAgInNjb3BlIjogIm9wZW5pZCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL3VzZXJpbmZvLmVtYWlsIGh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvdXNlcmluZm8ucHJvZmlsZSIsCiAgInRva2VuX3R5cGUiOiAiQmVhcmVyIiwKICAiaWRfdG9rZW4iOiAiZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklqQmxNelExWm1RM1pUUmhPVGN5TnpGa1ptWmhPVGt4WmpWaE9Ea3pZMlF4Tm1JNFpUQTRNamNpTENKMGVYQWlPaUpLVjFRaWZRLmV5SnBjM01pT2lKb2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwaUxDSmhlbkFpT2lJeU16WXhOVE0yTVRreE5EVXROR3huWlRoMWIyWjJObTF2TjJ4dk9ESm9hMlYyYzJWblpHTnNNR0p5ZFdvdVlYQndjeTVuYjI5bmJHVjFjMlZ5WTI5dWRHVnVkQzVqYjIwaUxDSmhkV1FpT2lJeU16WXhOVE0yTVRreE5EVXROR3huWlRoMWIyWjJObTF2TjJ4dk9ESm9hMlYyYzJWblpHTnNNR0p5ZFdvdVlYQndjeTVuYjI5bmJHVjFjMlZ5WTI5dWRHVnVkQzVqYjIwaUxDSnpkV0lpT2lJeE1EYzNNakV4TVRBek5qSTBOVEEzTmpFNU5URWlMQ0pvWkNJNkltSnBkR0p2ZUM1emQybHpjeUlzSW1WdFlXbHNJam9pZFhKaVlXNUFZbWwwWW05NExuTjNhWE56SWl3aVpXMWhhV3hmZG1WeWFXWnBaV1FpT25SeWRXVXNJbUYwWDJoaGMyZ2lPaUpTZEhsNVRWVjFObkZUU0dKQlZWQkljMk5YVnpkbklpd2libTl1WTJVaU9pSjZOekJ6WkZsRFpuWTVWR1ZEYVZscVNGUXpRV0Z6VEZsRVpHRmFUamx5YWlJc0ltNWhiV1VpT2lKVmNtSmhiaUJLZFhKallTSXNJbkJwWTNSMWNtVWlPaUpvZEhSd2N6b3ZMMnhvTXk1bmIyOW5iR1YxYzJWeVkyOXVkR1Z1ZEM1amIyMHZZUzlCUTJjNGIyTk1VbTlrT1VadGNsSkZlV1JqVG1KbFVITndhR1UyUlU5VlIwMDBTRXhDYzE5TE9XOTBjbEJ2U1VjNGIwRnBZazFKUFhNNU5pMWpJaXdpWjJsMlpXNWZibUZ0WlNJNklsVnlZbUZ1SWl3aVptRnRhV3g1WDI1aGJXVWlPaUpLZFhKallTSXNJbWxoZENJNk1UY3lNVEEyTXpJM09Dd2laWGh3SWpveE56SXhNRFkyT0RjNGZRLmxSTGotSEE5MkRBUGZhNGRBVVc4ajlQVURRaXFiZlV1WGlHeTZnQnZpQ09wRUFLZHhfbVoxOUhtVnM0ai03OXo0Mk1YYzEyZ2YyZGlMeXlHNzAxUGZ1RWd0ZlU0UXBLc3V3NW45OGVQbnFCdVI4dWxsNTVONERqRHUwRzZHUWpWanlNekRTVlBPeDVBZ3ZycFVISGFIanJmc2tJZ2VkX3ZKRm5NaG5hcHNBUlRpa1JHQWxOeEZnTFRZcmJINEFIbEp5dnN1aUoybDVIeXM5UDdhZFFOZkstUWY1bmN4TVp5X01PakFleW5hYWllZVRHQXhJRjhkMnlHLWhyVVRBcG1MNjhsWTBlYmdNZktkQnJzSGgxVUNCWGpVdjQ5TUVvcmhqYXdxY3B1ZWpBMXFoRUc3c0tKVnBqU1RRWG9ET044VzFxUVVRVUc5UzVhQWZreGNYQUhZQSIKfQ==","redirect_uri":"https://auth.xxx.dev/oauth2/google/authorization-code-callback"}
{"level":"debug","ts":1721063278.9772499,"logger":"security","msg":"OAuth 2.0 access token response decoded","body":{"access_token":"ya29.a0AXooCguJqunDcSTMzXFNT-9vLf1JrkrC6VOHqGbWB-GN2NR0Y5VXCUGmcKOk76vALkYyzzNOyKRDDGiVXd9GdqVoL-RKFiynbmcptWRimkab3e3K0QXEt26OWwMa_ihyd_6Jyo4IFR0u1LSC_03lSKshbkmiDFTAswaCgYKAe8SARMSFQHGX2Mi6FvFINZOw6HY_tsVGBeisA0169","expires_in":3599,"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjBlMzQ1ZmQ3ZTRhOTcyNzFkZmZhOTkxZjVhODkzY2QxNmI4ZTA4MjciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiIyMzYxNTM2MTkxNDUtNGxnZTh1b2Z2Nm1vN2xvODJoa2V2c2VnZGNsMGJydWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIyMzYxNTM2MTkxNDUtNGxnZTh1b2Z2Nm1vN2xvODJoa2V2c2VnZGNsMGJydWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDc3MjExMTAzNjI0NTA3NjE5NTEiLCJoZCI6ImJpdGJveC5zd2lzcyIsImVtYWlsIjoidXJiYW5AYml0Ym94LnN3aXNzIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF0X2hhc2giOiJSdHl5TVV1NnFTSGJBVVBIc2NXVzdnIiwibm9uY2UiOiJ6NzBzZFlDZnY5VGVDaVlqSFQzQWFzTFlEZGFaTjlyaiIsIm5hbWUiOiJVcmJhbiBKdXJjYSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NMUm9kOUZtclJFeWRjTmJlUHNwaGU2RU9VR000SExCc19LOW90clBvSUc4b0FpYk1JPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IlVyYmFuIiwiZmFtaWx5X25hbWUiOiJKdXJjYSIsImlhdCI6MTcyMTA2MzI3OCwiZXhwIjoxNzIxMDY2ODc4fQ.lRLj-HA92DAPfa4dAUW8j9PUDQiqbfUuXiGy6gBviCOpEAKdx_mZ19HmVs4j-79z42MXc12gf2diLyyG701PfuEgtfU4QpKsuw5n98ePnqBuR8ull55N4DjDu0G6GQjVjyMzDSVPOx5AgvrpUHHaHjrfskIged_vJFnMhnapsARTikRGAlNxFgLTYrbH4AHlJyvsuiJ2l5Hys9P7adQNfK-Qf5ncxMZy_MOjAeynaaieeTGAxIF8d2yG-hrUTApmL68lY0ebgMfKdBrsHh1UCBXjUv49MEorhjawqcpuejA1qhEG7sKJVpjSTQXoDON8W1qQUQUG9S5aAfkxcXAHYA","scope":"openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile","token_type":"Bearer"}}
{"level":"debug","ts":1721063278.9776447,"logger":"security","msg":"received OAuth 2.0 authorization server access token","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","token":{"access_token":"ya29.a0AXooCguJqunDcSTMzXFNT-9vLf1JrkrC6VOHqGbWB-GN2NR0Y5VXCUGmcKOk76vALkYyzzNOyKRDDGiVXd9GdqVoL-RKFiynbmcptWRimkab3e3K0QXEt26OWwMa_ihyd_6Jyo4IFR0u1LSC_03lSKshbkmiDFTAswaCgYKAe8SARMSFQHGX2Mi6FvFINZOw6HY_tsVGBeisA0169","expires_in":3599,"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjBlMzQ1ZmQ3ZTRhOTcyNzFkZmZhOTkxZjVhODkzY2QxNmI4ZTA4MjciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiIyMzYxNTM2MTkxNDUtNGxnZTh1b2Z2Nm1vN2xvODJoa2V2c2VnZGNsMGJydWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIyMzYxNTM2MTkxNDUtNGxnZTh1b2Z2Nm1vN2xvODJoa2V2c2VnZGNsMGJydWouYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDc3MjExMTAzNjI0NTA3NjE5NTEiLCJoZCI6ImJpdGJveC5zd2lzcyIsImVtYWlsIjoidXJiYW5AYml0Ym94LnN3aXNzIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF0X2hhc2giOiJSdHl5TVV1NnFTSGJBVVBIc2NXVzdnIiwibm9uY2UiOiJ6NzBzZFlDZnY5VGVDaVlqSFQzQWFzTFlEZGFaTjlyaiIsIm5hbWUiOiJVcmJhbiBKdXJjYSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NMUm9kOUZtclJFeWRjTmJlUHNwaGU2RU9VR000SExCc19LOW90clBvSUc4b0FpYk1JPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IlVyYmFuIiwiZmFtaWx5X25hbWUiOiJKdXJjYSIsImlhdCI6MTcyMTA2MzI3OCwiZXhwIjoxNzIxMDY2ODc4fQ.lRLj-HA92DAPfa4dAUW8j9PUDQiqbfUuXiGy6gBviCOpEAKdx_mZ19HmVs4j-79z42MXc12gf2diLyyG701PfuEgtfU4QpKsuw5n98ePnqBuR8ull55N4DjDu0G6GQjVjyMzDSVPOx5AgvrpUHHaHjrfskIged_vJFnMhnapsARTikRGAlNxFgLTYrbH4AHlJyvsuiJ2l5Hys9P7adQNfK-Qf5ncxMZy_MOjAeynaaieeTGAxIF8d2yG-hrUTApmL68lY0ebgMfKdBrsHh1UCBXjUv49MEorhjawqcpuejA1qhEG7sKJVpjSTQXoDON8W1qQUQUG9S5aAfkxcXAHYA","scope":"openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile","token_type":"Bearer"}}
{"level":"debug","ts":1721063278.9790304,"logger":"security","msg":"decoded claims from OAuth 2.0 authorization server access token","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","claims":{"email":"yyy@xxxx.swiss","exp":1721066878,"family_name":"yyyy","given_name":"yyy","iat":1721063278,"iss":"https://accounts.google.com","name":"yyy yyyy","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","sub":"107721110362450761951"}}
{"level":"info","ts":1721063278.9797318,"logger":"security","msg":"Successful login","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","auth_method":"oauth2","auth_realm":"google","user":{"email":"yyy@xxxx.swiss","exp":1721066878,"family_name":"yyyy","given_name":"yyy","iat":1721063278,"iss":"https://accounts.google.com","name":"yyy yyyy","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","sub":"107721110362450761951"}}
{"level":"debug","ts":1721063278.9803615,"logger":"security","msg":"user transformation ended","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","user":{"addr":"10.0.0.2","email":"yyy@xxxx.swiss","exp":1721066878,"family_name":"yyyy","frontend_links":["\"Portal Settings\" /settings icon \"las la-cog\""],"given_name":"yyy","iat":1721063278,"iss":"https://auth.xxx.dev/oauth2/google/","jti":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","name":"yyy yyyy","nbf":1721063218000,"origin":"google","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","realm":"google","roles":["authp/user"],"sub":"107721110362450761951"}}
{"level":"info","ts":1721063278.981167,"logger":"security","msg":"Successful login","session_id":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","request_id":"aa070893-079f-4a46-b04e-5a5b72e2f4a7","backend":{"name":"google","realm":"google","method":"oauth"},"user":{"addr":"10.0.0.2","email":"yyy@xxxx.swiss","exp":1721066878,"family_name":"yyyy","frontend_links":["\"Portal Settings\" /settings icon \"las la-cog\""],"given_name":"yyy","iat":1721063278,"iss":"https://auth.xxx.dev/oauth2/google/","jti":"SkiVCZNOUXFfXrZHpLyLU15ewyQ9SEC91c0BdPSKQ5p","name":"yyy yyyy","nbf":1721063218000,"origin":"google","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","realm":"google","roles":["authp/user","authp/guest"],"sub":"107721110362450761951"}}
{"level":"debug","ts":1721063279.0209444,"logger":"security","msg":"Redirect served","session_id":"C2f7nWZ1BzjcJkKWh7ooOxy6G0GappWOdeqraQ","request_id":"1d2195fb-c847-49af-9e3b-d903371e7dd9","redirect_url":"https://auth.xxx.dev/login","status_code":302}

See last log line serving a 302 redirect

Build information:

# Dockerfile
ARG CADDY_VERSION=2.8.4
FROM caddy:${CADDY_VERSION}-builder AS builder

RUN xcaddy build \
    --with github.com/lucaslorentz/caddy-docker-proxy/v2 \
    --with github.com/greenpau/caddy-security

FROM caddy:${CADDY_VERSION}-alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

CMD ["caddy", "docker-proxy"]

Expected behavior

Successful login leads to portal screen

Additional context n/a

greenpau commented 1 month ago

@alternativc , you need to serve auth portal from “/auth*”. The my identity link should be “/auth/whoami”. See issue #337 for more context.

greenpau commented 1 month ago

@alternativc , this would be different too

https://auth.xxx.dev/oauth2/google

alternativc commented 1 month ago

Thanks for the quick reply. Let me try that now and come back.

The config above was adopted from the docs, where the /auth URI is not present -> https://github.com/authcrunch/authcrunch.github.io/blob/main/assets/conf/oauth/google/Caddyfile

greenpau commented 1 month ago

@alternativc , the default config is outdated.

alternativc commented 1 month ago

The result is the same with the /auth URI adjustment as well.

The Caddyfile:

{
        debug
        order authenticate before respond
        order authorize before basicauth

        security {
                oauth identity provider google {
                        realm google
                        driver google
                        client_id XXX.apps.googleusercontent.com
                        client_secret XXX
                        scopes openid email profile
                }

                authentication portal myportal {
                        crypto default token lifetime 3600
                        #crypto key sign-verify {env.JWT_SHARED_KEY}
                        crypto key sign-verify XXX
                        enable identity provider google
                        cookie domain xxx.dev
                        ui {
                                links {
                                        "My Identity" "/auth/whoami" icon "las la-user"
                                        "Grafana" https://swarmgraf.xxx.dev
                                }
                        }

                        transform user {
                                match realm google
                                action add role authp/user
                                ui link "Portal Settings" /settings icon "las la-cog"
                        }

                }

                authorization policy mypolicy {
                                        # disable auth redirect
                                        set auth url https://auth.xxx.dev/auth/oauth2/google
                                        #crypto key verify {env.JWT_SHARED_KEY}
                                        crypto key verify XXX
                                        allow roles authp/user
                                        validate bearer header
                                        inject headers with claims
                                }
        }
}

auth.xxx.dev {
        route /auth* {
                authenticate * with myportal
        }
}

The final log file from the debug output always posts a 302 redirect back to /auth/login:

{"level":"debug","ts":1721068507.3144,"logger":"security","msg":"user transformation ended","session_id":"WOlqf3dP4SIjreTI4aAj0mfW6k30PIB2SRf4BaPdypEs","request_id":"4d9fa95e-f810-4195-b7b2-f5c5ba42bae4","user":{"addr":"10.0.0.2","email":"name@xxx.swiss","exp":1721072107,"family_name":"surname","frontend_links":["\"Portal Settings\" /settings icon \"las la-cog\""],"given_name":"name","iat":1721068507,"iss":"https://auth.domain.dev/auth/oauth2/google/","jti":"WOlqf3dP4SIjreTI4aAj0mfW6k30PIB2SRf4BaPdypEs","name":"name surname","nbf":1721068447000,"origin":"google","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","realm":"google","roles":["authp/user"],"sub":"107721110362450761951"}}
{"level":"info","ts":1721068507.3183973,"logger":"security","msg":"Successful login","session_id":"WOlqf3dP4SIjreTI4aAj0mfW6k30PIB2SRf4BaPdypEs","request_id":"4d9fa95e-f810-4195-b7b2-f5c5ba42bae4","backend":{"name":"google","realm":"google","method":"oauth"},"user":{"addr":"10.0.0.2","email":"name@xxx.swiss","exp":1721072107,"family_name":"surname","frontend_links":["\"Portal Settings\" /settings icon \"las la-cog\""],"given_name":"name","iat":1721068507,"iss":"https://auth.domain.dev/auth/oauth2/google/","jti":"WOlqf3dP4SIjreTI4aAj0mfW6k30PIB2SRf4BaPdypEs","name":"name surname","nbf":1721068447000,"origin":"google","picture":"https://lh3.googleusercontent.com/a/ACg8ocLRod9FmrREydcNbePsphe6EOUGM4HLBs_K9otrPoIG8oAibMI=s96-c","realm":"google","roles":["authp/user","authp/guest"],"sub":"107721110362450761951"}}
{"level":"debug","ts":1721068507.3570325,"logger":"security","msg":"Redirect served","session_id":"wkPqLh7PDNk0jxZcPAg8tKhSY9YDFyNFY467foL0TP9Ug","request_id":"17d2f956-ebbb-4fc1-bad5-38f7bd064050","redirect_url":"https://auth.domain.dev/auth/login","status_code":302}

Is there a more recent config I can use as a reference if the official docs are outdated on this?

alternativc commented 1 month ago

One thing that bothers me as well is that I do not see any cookies for auth.domain.dev present in my browser.

greenpau commented 1 month ago

One thing that bothers me as well is that I do not see any cookies for auth.domain.dev present in my browser.

Are you using HTTPS or HTTP?

See https://docs.authcrunch.com/docs/authenticate/auth-cookie#intra-domain-cookies

and if necessary, add cookie insecure on

alternativc commented 1 month ago

Its HTTPS only. As you can see in the caddy file I use: cookie domain xxx.dev

Even with *.xxx.dev as the domain, the result is the same. So appears different from #134

greenpau commented 1 month ago

Its HTTPS only. As you can see in the caddy file I use: cookie domain xxx.dev

Where is your redirect 302 comes from?

@alternativc , what if you do this?

auth.xxx.dev {
        route /auth* {
                authenticate * with myportal
        }
        redir https://auth.xxx.dev/auth/portal 302
}
alternativc commented 1 month ago

The redirect comes from /auth/portal

Screenshot 2024-07-15 at 22 16 40
greenpau commented 1 month ago

The redirect comes from /auth/portal

@alternativc , It is somehow related to OAuth process not being completed successfully. Please check logs again. It could be timing (NTP issue).

Add local auth to the portal and see whether you can authenticate locally. see https://github.com/authcrunch/authcrunch.github.io/blob/main/docs/authenticate/local/50-static-users.md

alternativc commented 1 month ago

Ok, I think something is fairly wrong with this Caddy setup.

Just to point out:

This is the Caddy file with the localdb option now (the original public/live URI is translated to domain.dev, other than that everything is as is):

{
    debug
    order authenticate before respond
    order authorize before basicauth

    security {
        local identity store localdb {
            realm local
            path {$HOME}/.local/caddy/localdb/users.json
            user jsmith {
                name John Smith
                email jsmith@domain.dev
                password "My@Password123"
                roles authp/user
            }
        }

        authentication portal myportal {
            enable identity store localdb
            crypto default token lifetime 3600
            crypto key sign-verify random_key
            cookie domain domain.dev
            ui {
                links {
                    "My Identity" "/auth/whoami" icon "las la-user"
                    "Grafana" https://swarmgraf.domain.dev
                }
            }

            transform user {
                match realm local
                action add role authp/user
                ui link "Portal Settings" /auth/settings icon "las la-cog"
            }
        }

        authorization policy mypolicy {
            # disable auth redirect
            set auth url https://auth.domain.dev/auth
            allow roles authp/user
            crypto key verify random_key
        }
    }

}

auth.domain.dev {
    route /auth* {
        authenticate * with myportal
    }
}

With this Caddyfile, I get the following debug logs, when I try to login:

{"level":"debug","ts":1721113664.4065711,"logger":"security","msg":"user transformation ended","session_id":"SBqRAnDKzOBHIEYaALMSJpQm1Ia7Bken9vIHyHNUPH79","request_id":"5d9be208-1ae4-4db2-a516-0d7891170dc4","user":{"addr":"10.0.0.2","email":"jsmith@domain.dev","exp":1721113669,"frontend_links":["\"Portal Settings\" /auth/settings icon \"las la-cog\""],"iat":1721113664,"iss":"https://auth.domain.dev/auth/login","jti":"SBqRAnDKzOBHIEYaALMSJpQm1Ia7Bken9vIHyHNUPH79","name":"Smith, John","nbf":1721113604,"origin":"local","realm":"local","roles":["authp/user"],"sub":"jsmith"}}
{"level":"debug","ts":1721113664.4466288,"logger":"security","msg":"failed sandbox request","session_id":"QXRfIqoHabtU6TWQlmlzoCEfrpjTCgdx5JrgvCsb","request_id":"eb0d9e88-d356-4f6d-92ba-aa80576917bc","error":"sandbox secret not found"}

This is the result when I enter jsmith (or webadmin) and hit Enter:

image

Please note that we are using https only for this request as per logs, so I am not sure why it is requesting a sandbox session?

This is the full generated config at runtime for this Caddy instance (please note only HTTPS active):

{
  "admin": {
    "listen": "tcp/localhost:2019"
  },
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "10.0.1.6:9000"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "swarmtainer.domain.dev"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "authentication",
                          "providers": {
                            "authorizer": {
                              "gatekeeper_name": "mypolicy",
                              "route_matcher": "*"
                            }
                          }
                        },
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "10.0.1.26:3000"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "swarmgraf.domain.dev"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "handler": "subroute",
                                  "routes": [
                                    {
                                      "handle": [
                                        {
                                          "handler": "authenticator",
                                          "portal_name": "myportal",
                                          "route_matcher": "*"
                                        }
                                      ]
                                    }
                                  ]
                                }
                              ],
                              "match": [
                                {
                                  "path": [
                                    "*"
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "/auth*"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "auth.domain.dev"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "security": {
      "config": {
        "authentication_portals": [
          {
            "api": {
              "profile_enabled": true
            },
            "cookie_config": {
              "domains": {
                "domain.dev": {
                  "domain": "domain.dev",
                  "seq": 1
                }
              }
            },
            "crypto_key_configs": [
              {
                "algorithm": "hmac",
                "id": "0",
                "source": "config",
                "token_lifetime": 3600,
                "token_name": "access_token",
                "token_secret": "random_key",
                "usage": "sign-verify"
              }
            ],
            "crypto_key_store_config": {
              "token_lifetime": 3600
            },
            "identity_stores": [
              "localdb"
            ],
            "name": "myportal",
            "portal_admin_roles": {
              "authp/admin": true
            },
            "portal_guest_roles": {
              "authp/guest": true
            },
            "portal_user_roles": {
              "authp/user": true
            },
            "token_grantor_options": {},
            "token_validator_options": {},
            "ui": {
              "private_links": [
                {
                  "icon_enabled": true,
                  "icon_name": "las la-user",
                  "link": "/auth/whoami",
                  "title": "My Identity"
                },
                {
                  "link": "https://swarmgraf.domain.dev",
                  "title": "Grafana"
                }
              ]
            },
            "user_transformer_configs": [
              {
                "actions": [
                  "action add role authp/user",
                  "ui link \"Portal Settings\" /auth/settings icon \"las la-cog\""
                ],
                "matchers": [
                  "exact match realm local"
                ]
              }
            ]
          }
        ],
        "authorization_policies": [
          {
            "access_list_rules": [
              {
                "action": "allow log debug",
                "conditions": [
                  "match roles authp/user"
                ]
              }
            ],
            "auth_redirect_query_param": "redirect_url",
            "auth_redirect_status_code": 302,
            "auth_url_path": "https://auth.domain.dev/auth",
            "crypto_key_configs": [
              {
                "algorithm": "hmac",
                "id": "0",
                "source": "config",
                "token_lifetime": 900,
                "token_name": "access_token",
                "token_secret": "random_key",
                "usage": "verify"
              }
            ],
            "name": "mypolicy"
          }
        ],
        "identity_stores": [
          {
            "kind": "local",
            "name": "localdb",
            "params": {
              "path": "/root/.local/caddy/localdb/users.json",
              "realm": "local",
              "users": [
                {
                  "email_address": "jsmith@domain.dev",
                  "name": "John Smith",
                  "password": "My@Password123",
                  "roles": [
                    "authp/user"
                  ],
                  "username": "jsmith"
                }
              ]
            }
          }
        ]
      }
    }
  },
  "logging": {
    "logs": {
      "default": {
        "level": "DEBUG"
      }
    }
  }
}

Package version information:

/srv # caddy list-modules --versions | grep -E "(auth|security)"
http.authentication.hashes.bcrypt v2.8.4
http.authentication.providers.http_basic v2.8.4
http.handlers.authentication v2.8.4
tls.client_auth.verifier.leaf v2.8.4
http.authentication.providers.authorizer v1.1.29
http.handlers.authenticator v1.1.29
security v1.1.29
greenpau commented 1 month ago

@alternativc , the missing sandbox secret has to do with cookie not being visible. Which browsers did you try?

greenpau commented 1 month ago

The error stems from here: https://github.com/greenpau/go-authcrunch/blob/12d1bf76734ba7ec502beb89f9df758cce3b6c07/pkg/authn/handle_http_sandbox.go#L67

alternativc commented 1 month ago

I have tried on MacOS {firefox, chrome, safari}, iphone {safari, chrome} all resulting in the same outcome.

greenpau commented 1 month ago

@alternativc , please reach to me over linkedin. I will get on meet with you and we will troubleshoot together.

alternativc commented 1 month ago

Thanks for the call.

As discussed the issue is the samesite attribute between the authentication cookie and the session cookie. We changed the cookie samesite directive to tshoot:

        authentication portal myportal {
            ....
            cookie domain auth.domain.dev
            cookie samesite lax
            crypto key sign-verify testtest
            ....
            }
        }

The resulting cookies are as follows -> different samesite settings for cookies is the issue:

Screenshot 2024-07-17 at 15 42 07
greenpau commented 1 month ago

@alternativc , here are how my cookies looking like. I don't get the same cookie warning as you get. Here, I use local auth to authenticate. Entered sandbox and ready to provide password. Could you please paste the warning from DevTools console?

image

I did the same in Firefox and it worked too. No warnings.

image

In sum, let's see what the warning you get is saying.

greenpau commented 1 month ago

@alternativc , what is strange that you are getting the same warnings with both Chrome and Firefox. Good challenge here 😃

alternativc commented 1 month ago

Sure. Here is the error message when cookie domain is set to .domain.net or domain.net. This error is not present however if we set the cookie domain to auth.domain.net

image

The firefox version is the same as yours :D

image image
alternativc commented 1 month ago

After a lot of digging around I found that the domain I was trying to protect was listed in the public suffix list - https://publicsuffix.org/ . The reason for this inclusion goes beyond my time and is being researched.

For any other poor souls: if a domain is listed in the PSL list, you can only issue an authentication cookie for your (one) subdomain, it cannot be granted for anyother subdomain in that TLD. Imagine if you have a dynamicDNS recorda.dyndns.org that can also be authenticated agains recordb.dyndns.org.

The only way I could come up with the error message was through authelia, which has an explicit check for those domains. Caddy-security runs without a problem, but in the end the browser will throw those away.

@greenpau let me know if I can add any more information as this one was a doozie.

qrkourier commented 3 weeks ago

There must be at least one additional cause for this symptom that I'm experiencing with a domain name I have never submitted to the PSL. I suspect my problem is caused by incorrectly configured provider, Caddy Security authorization policy, or both.