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

Multi domain authentication via a single auth portal

Open rhyst opened this issue 3 years ago • 3 comments

Hey,

Firstly thanks for this plugin, it made setting up authentication on my server very easy 🙇

Is authenticating on multiple domains via a single auth portal supported? I've seen a couple of issues about this and one link to a PR that implies it might be possible but I'm not sure. Sorry if I'm asking a question that is already answered somewhere.

My caddy config is roughly:

{
  "apps": {
    "security": {
      "config": {
        "authentication_portals": [
          {
            "name": "authportal",
            "user_transformer_configs": [...],
            "cookie_config": {
              "domains": {
                "domain1.com": {
                  "domain": "domain1.com",
                  "seq": 1,
                  "lifetime": 604800
                },
                "domain2.com": {
                  "domain": "domain2.com",
                  "seq": 2,
                  "lifetime": 604800
                },
              }
            },
            "crypto_key_configs": [...],
            "crypto_key_store_config": {...},
            "identity_stores": [...]
          }
        ],
        "identity_stores": [...],
        "authorization_policies": [
          {
            "name": "authpolicy",
            "auth_url_path": "https://auth.domain1.com",
            "auth_redirect_query_param": "redirect_url",
            "auth_redirect_status_code": 302,
            "access_list_rules": [...],
            "crypto_key_configs": [...]
          }
        ]
      }
    },
    "http": {
      "servers": {
        "https-server": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "auth.domain1.com",
                    "auth.domain2.com",
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "authenticator",
                  "portal_name": "authportal",
                  "route_matcher": "*"
                }
              ]
            },
            {
              "match": [
                {
                  "host": [
                    "authtest.domain1.com",
                    "authtest.domain2.com",
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "authentication",
                  "providers": {
                    "authorizer": {
                      "gatekeeper_name": "authpolicy",
                      "route_matcher": "*"
                    }
                  }
                },
                {
                  "handler": "static_response",
                  "body": "Authentication working!"
                }
              ],
              "terminal": true
            },
        },
      }
    },
}

Let me know if I truncated anything potentially useful.

So auth.domain1.com and authtest.domain1.com work perfectly. If can go to auth.domain2.com then I see the login page. If I go to to authtest.domain2.com I get redirected to auth.domain1.com where I log in, and then it goes into a redirect loop because (I assume) the cookie is on domain1.com.

I am confused about the purpose of the cookie_config domains given that this does not appear to work.

rhyst avatar Sep 12 '22 19:09 rhyst

Hello,

I think I have a similar issue, but possibly not.

I have a caddy server with portal at auth.domain.tld with the setting "cookie domain" set to domain.tld

and another caddy with portal at auth.hs.domain.tld with setting "cookie domain" set to hs.domain.tld

Both browser sessions/servers seem to use the first ones cookie when logged in and therefore the portal at auth.hs.domain.tld fails with reason: keystore: failed to parse token.

Regards, Lue.

lue30499 avatar Sep 23 '22 11:09 lue30499

In order to allow multi-domain auth, I need to create a system that would authenticate a user in a domain X and then through a series of redirects would take the user to domain Y and Z, where it would perform authorization without any user input (e.g. one time code) and issue tokens for the domain Y and Z.

greenpau avatar Sep 23 '22 14:09 greenpau

If I understand this right, I might be running a workaorund for this. If not, sorry to get it wrong, English is not my native language.

What I did is create templates which then do the grunt work for each of the domains:

(subdomain) {
	{args.0}.domain1.family {
		authorize with familyPolicy
		tls internal
		reverse_proxy {args.1}
	}

	{args.0}.domain2.me {
		authorize with dsPolicy
		reverse_proxy {args.1}
	}

	{args.0}.domain3.de {
		authorize with mainPolicy
		reverse_proxy {args.1}
	}
}

(subNoAuth) {
	{args.0}.domain1.family {
		tls internal
		reverse_proxy {args.1}
	}

	{args.0}.domain2.me, {args.0}.domain3.de {
		reverse_proxy {args.1}
	}
}

(subNoAuthAndSkip) {
	{args.0}.domain2.me {
		reverse_proxy * {
			to {args.1}

			transport http {
				tls
				tls_insecure_skip_verify
			}
		}
	}

	{args.0}.domain3.de {
		reverse_proxy * {
			to {args.1}

			transport http {
				tls
				tls_insecure_skip_verify
			}
		}
	}

	{args.0}.domain1.family {
		tls internal
		reverse_proxy * {
			to {args.1}

			transport http {
				tls
				tls_insecure_skip_verify
			}
		}
	}
}

{
	security {
		local identity store localdb {
			realm local
			path assets/config/users.json
		}

		authentication portal myportal {
			crypto default token lifetime 28800
			crypto key sign-verify {env.JWT_SECRET}
			cookie domain domain3.de
			cookie domain domain2.me
			cookie domain domain1.family
			enable identity store localdb
			ui {
				links {
					"DMS" "/dms" icon "las la-star"
					"My Identity" "/auth/whoami" icon "las la-user"
				}
			}
			transform user {
				match origin local
				action add role authp/user
				ui link "Portal Settings" /auth/settings icon "las la-cog"
			}
		}

		authorization policy mainPolicy {
			set auth url https://auth.domain3.de
			crypto key verify {env.JWT_SECRET}
			allow roles authp/admin authp/user
		}

		authorization policy dsPolicy {
			set auth url https://auth.domain2.me
			crypto key verify {env.JWT_SECRET}
			allow roles authp/admin authp/user
		}

		authorization policy familyPolicy {
			set auth url https://auth.domain1.family
			crypto key verify {env.JWT_SECRET}
			allow roles authp/admin authp/user
		}
	}

	order authenticate first
	order trace before reverse_proxy
	order authorize before reverse_proxy
}

auth.domain3.de, auth.domain2.me {
	authenticate with myportal
}

auth.domain1.family {
	tls internal
	authenticate with myportal
}

unrelatedFurtherDomain.de, 172.16.0.61 {
	route /version* {
		respond * "1.0.0" 200
	}

	route /auth* {
		authenticate * with myportal
	}

	route /xauth* {
		authenticate * with myportal
	}

	route /dms {
		authorize with mainPolicy
		file_server {
			root ./assets/config
		}
	}

	route {
		redir https://{hostport}/auth 302
	}
}

domain1.family, domain2.me {
	tls internal
	reverse_proxy * {
		to 172.16.0.50:5001

		transport http {
			tls
			tls_insecure_skip_verify
		}
	}
}

import subNoAuth audiobook 172.16.0.50:10819
import subdomain backup 172.16.0.55:8001
import subdomain bragibooks 172.16.0.50:10820
import subNoAuthAndSkip calendar 172.16.0.50:5001/calendar
import subdomain dms 172.16.0.50:10807
import subNoAuthAndSkip dsm 172.16.0.50:5001
import subdomain firefly 172.16.0.50:10824
import subdomain fireimp 172.16.0.50:10924
import subNoAuth jellyfin 172.16.0.50:10812

Hoempi avatar Feb 01 '23 08:02 Hoempi