From 519f8f8879d47174220cb7261bcdac257f9f1724 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Thu, 11 Jun 2026 11:03:27 -0700 Subject: [PATCH] sso: add PublicURL for browser authorize (split from backend MciasURL) Lets services point the browser SSO authorize redirect at the public MCIAS hostname while keeping the server-to-server code exchange on the internal/Tailnet address (efficient, edge-independent). PublicURL is optional and falls back to MciasURL. Co-Authored-By: Claude Opus 4.8 --- sso/sso.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sso/sso.go b/sso/sso.go index e2d7a79..1c5ea14 100644 --- a/sso/sso.go +++ b/sso/sso.go @@ -39,9 +39,18 @@ const ( // Config holds the SSO client configuration. The values must match the // SSO client registration in MCIAS config. type Config struct { - // MciasURL is the base URL of the MCIAS server. + // MciasURL is the base URL of the MCIAS server used for the + // server-to-server authorization-code exchange. This is typically the + // internal/Tailnet address so the exchange does not depend on the public + // edge. MciasURL string + // PublicURL, when set, is the browser-facing MCIAS base URL used to build + // the authorize redirect. It must be resolvable and reachable by end-user + // browsers (e.g. the public hostname). When empty, MciasURL is used for + // both, which only works when MciasURL is itself browser-reachable. + PublicURL string + // ClientID is the registered SSO client identifier. ClientID string @@ -104,9 +113,19 @@ func New(cfg Config) (*Client, error) { }, nil } -// AuthorizeURL returns the MCIAS authorize URL with the given state parameter. +// authorizeBase returns the browser-facing MCIAS base URL: PublicURL when +// configured, otherwise MciasURL. +func (c *Client) authorizeBase() string { + if c.cfg.PublicURL != "" { + return c.cfg.PublicURL + } + return c.cfg.MciasURL +} + +// AuthorizeURL returns the MCIAS authorize URL (browser-facing) with the +// given state parameter. func (c *Client) AuthorizeURL(state string) string { - base := strings.TrimRight(c.cfg.MciasURL, "/") + base := strings.TrimRight(c.authorizeBase(), "/") return base + "/sso/authorize?" + url.Values{ "client_id": {c.cfg.ClientID}, "redirect_uri": {c.cfg.RedirectURI},