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

question: after successfull oidc login, I'm always redirected to /login when accessing portal

Open Tropaion opened this issue 8 months ago • 4 comments

A clear and concise description of what you want to accomplish.

I'm using oidc with keycloak. I can succesfully login and access my domains. But when I try to access auth.xxx.at/portal or auth.xxx.at/auth/portal I always get redirected to auth.xxx.at/login or auth.xxx.at/auth/login.

The log when successfully accessing a subdomain:

Apr 25 22:23:32 ReverseProxy caddy[2758]: {"level":"info","ts":1745619812.4317904,"logger":"security","msg":"Successful login","session_id":"VTkhbeMM7IeHVPxgMq6G37cIxf3HyGc5iuFc","request_id":"aa5c3f3a-543a-4a90-b8be-092f4800b4cf","backend":{"name":"keycloak","realm":"xxx","method":"oauth"},"user":{"addr":"192.168.44.10","email":"[email protected]","exp":1745623412,"family_name":"test","given_name":"test","iat":1745619812,"iss":"https://auth.xxx.at/oauth2/xxx/","jti":"VTkhbeMM7IeHVPxgMq6G37cIxf3HyGc5iuFc","name":"test test","nbf":1745619752000,"origin":"xxx","roles":["auth/database","manage-account","manage-account-links","view-profile"],"sub":"7eeb4ec2-557a-4151-851c-084037d14f7e"}}

Surprisingly, when I add to the role "authp/guest" in keycloak to this user, the portal works perfectly fine. But I want to portal to be available for all logged in users without considering roles, how can I achieve this?

Another small question, when a login is required, I have to manually select the login provider to be redirected to the login page, how can I be a automatically redirected?

If I access auth.xxx.at and i'm not logged in, I want to be directly redirected to the login page. If not logged in, I want to be redirected to the portal. Is this possible?

Sometimes this is in my logs, even when doing nothing, maybe this is relevant:

Apr 25 22:30:21 ReverseProxy caddy[2758]: {"level":"error","ts":1745620221.2369118,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed: src_ip=154.28.229.234, src_conn_ip=154.28.229.234, reason: no token found"}

Thank you for your help!

My config:

# =========== AUTH-PORTAL SETTINGS ===========
# ===== Important notes =====
# === Create JWT Key ===
# Generate Key: openssl rand -hex 32
# Set Key in Service: systemctl edit caddy
# [Service]
# Environment="JWT_SHARED_KEY=KEY"
# systemctl daemon-reload
# systemctl restart caddy
#
# === Force KeyCloak Access over Caddy ===
# nano /etc/hosts
# systemd-resolve --flush-caches
{
    order authenticate before respond
    order authorize before reverse_proxy

    security {
        # ======= OIDC Connect (Keycloak) ========
        oauth identity provider keycloak {
            driver generic
            realm xxx
            client_id caddy
            client_secret xxx
            scopes openid email profile

            # Login url
            metadata_url https://sso.xxx.at/realms/xxx/.well-known/openid-configuration

            # Wait for caddy to start before verifying url
            delay_start 5
            retry_attempts 5
            retry_interval 5
        }

        # ======= Auth Portal ========
        authentication portal myportal {
            crypto default token lifetime 3600
            crypto key sign-verify {env.JWT_SHARED_KEY}
            cookie domain xxx.at

            # Enable both identity stores
            enable identity provider keycloak

            # Automatically redirect to identity provider (only in json)
            #auto_redirect yes

            ui {
                links {
                    "My Identity"    "/whoami"         icon "las la-user"
                    "Manage Account" "https://sso.xxx.at/realms/xxx/account" icon "las la-id-badge"
                }
            }
        }

        # ======= Authorization Policies ========
        authorization policy network_policy {
            set auth url https://auth.xxx.at
            allow roles auth/network
            crypto key verify {env.JWT_SHARED_KEY}
        }

        authorization policy proxmox_policy {
            set auth url https://auth.xxx.at
            allow roles auth/proxmox
            crypto key verify {env.JWT_SHARED_KEY}
        }

        authorization policy database_policy {
            set auth url https://auth.xxx.at
            allow roles auth/database
            crypto key verify {env.JWT_SHARED_KEY}
        }
    }
}

# Authentication-Portal
auth.xxx.at {
        # Import security and privacy headers
        import security_header
        import content_policy_inline

        # Use this subdomain for the portal
        authenticate with myportal
}

Tropaion avatar Apr 25 '25 22:04 Tropaion

Hi, just want to chime in here, I think I'm hitting the same issue with the portal always redirecting to the login URL. Looking at the requests in the developer console I see that the portal responds with this header:

set-cookie access_token=delete; Domain=mydomain.fr; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT;

maybe that's related ?

I can also confirm that if I access a protected URL directly (like mydomain.fr/grafana) and then login it works fine, it's just the portal that doesn't work.

Finally, I think it's a recent issue. I upgraded to v2.10.0 last week with the latest caddy-security version (built with xcaddy) so I'm guessing an upgrade broke this.

vrischmann avatar May 05 '25 08:05 vrischmann

Surprisingly, when I add to the role "authp/guest" in keycloak to this user, the portal works perfectly fine.

We're seeing the same thing, the authp/guest role used to be given automatically but no longer seems to be in the list, so we can't access /whoami etc for troubleshooting

heapdavid avatar Jun 25 '25 11:06 heapdavid

  • authp/guest role do not assign to users automatically.
  • If the user do not have authp/admin, authp/guest or authp/user role then Portal is inaccessible.
  • We found a workaround with adding authp/guest to all transform blocks.

vedatkamer avatar Aug 16 '25 19:08 vedatkamer

Thank you so much. I was so confused that I did not manage to get authorization working but found it working with allowing authp/guest

I'd like to understand what is the reason that authp/guest is necessary here. First it seemed like a variable creation in 'add role' but it wasn't working either(see my tests below). Is it a fixed authorization scheme and therefore a fixed role list where I can choose between authp/admin, authp/guest or authp/user? I'd love to provide this information in the docs as this seems to me very necessary because even without the directive it wasn't working at all.

Unless there is no docs written, people should be able to find the solution here. I'll add some details of my setup and testing instead of opening a second issue.

Setup

  • All apps containered with Docker-compose
  • caddy
  • caddy-security
  • Pocket-ID
  • An Otter Wiki

Example 1:

action add role authp/admin
allow roles authp/admin

wiki.mydomain.com {
    import pocket-id-authentication
    respond "Wiki was here."
}

Response: "Forbidden" with caddy log:

2025/11/08 11:37:04.061 ERROR   http.handlers.authentication    auth provider returned error    {"provider": "authorizer", "error": "user authorization failed: src_ip=<>, src_conn_ip=<>, jti=<>, sub=<>, email=<>, name=<>, reason: user role is valid, but not allowed by access list"}

Example 2:

action add role authp/admin
allow roles authp/admin authp/guest

wiki.mydomain.com {
    import pocket-id-authentication
    respond "Wiki was here."
}

Response: Wiki was here.

Edit: The codeblocks are strongly simplified to show the main differences for testing purposes.

After rethinking of the issue, I might came to the guess, that this might be another bug. As @vedatkamer postet, they are missing the auto assignment of authp/guest to the user and using a workaround to do it themself. My tests show, that the user is extended but I need to allow the authp/guest explicitly.

canoez avatar Nov 08 '25 11:11 canoez