I am working on converting an existing application to a multi-tenant one with subdomains enforcing the organization. Tenants have an “admin” panel but can also impersonate their own customers via an impersonator session.
The impersonator session takes a token (decoded with Guardian) adds information about the organization and the impersonator to the session and then redirects to the storefront.
The way the app is setup a redirect from admin to the storefront takes one from localhost:4000
to localhost:4002
.
For now I’m just playing with this locally so this isn’t an infrastructure question, per se, but if I redirect from a tenant admin, say customer1.localhost:4000
I loose the subdomain going to localhost:4002
. Is there something in the endpoint or a plug I could implement to enforce the subdomain while the impersonation finishes?
For reference:
The AdminApp.ImpersonatonController
looks like this (modified for brevity):
def impersonate(%Conn{} = conn, %{} = params) do
impersonator = Guardian.Plug.current_resource(conn)
org_id = Repo.get_org_id()
claims = %{
impersonator_id: impersonator.id,
organization: org_id
}
{_, token, _claims} = Guardian.encode_and_sign(impersonator, claims)
conn
|> authorize(action: :impersonate)
|> redirect(external: "#{url}/impersonate?token=#{token}))
end
Then the StorefrontWeb.SessionController has this action:
def impersonate(conn, %{"token" => impersonation_token}) do
conn
|> ... decode and verify token...
|> create_impersonator_session()
end
defp create_impersonator_session({:ok, token, conn}) do
organization = token["organization"]
conn =
conn
|> GuardianPlug.sign_in(user)
|> put_session(:impersonating, {token["impersonator_id"], token["user_id"]})
|> put_session(:organization, organization)
redirect(conn, to: successful_sign_in_redirect_path(conn, user))
end