Working model · desktop-to-web SSO · no customer-side infrastructure
A concrete architecture for carrying an already-authenticated Windows user from a .NET WPF application into HubSpot private content (Private – SSO required with Segments) — with no AD FS, no Entra, no agents, no gateways, and nothing installed at customer sites. The demo further down mints real, verifiable tokens in your browser.
Prepared by Yinka Aderibigbe, August 2026.
Kerberos and NTLM — the protocols behind Windows Integrated Authentication — terminate at the customer's network boundary. HubSpot's private-content SSO (SAML or OIDC; HubSpot sunset JWT SSO for new apps in Feb 2025) can only talk to an identity provider it can reach over the internet, and the customer's on-prem AD can never be that IdP directly. The standard bridges — AD FS, Entra Connect, customer-side agents — are all excluded by your constraints. That leaves exactly one compliant trust path: the WPF application itself, which already holds the authenticated Windows identity, asserts that identity to a centrally hosted service under your control.
This generates real cryptographic material in your browser — an HMAC-signed site assertion, a one-time token, and an RS256-signed OIDC id_token you can paste into any JWT debugger. Nothing is transmitted anywhere.
Your spec is explicit that email domain cannot determine site access. In this model the domain is never used for authorization at all: the central service holds the UPN → contact → customer/site mapping, writes it to HubSpot contact properties via the CRM API, and segment membership derives from those properties. Two users at the same customer domain can hold different site permissions, one user can sit in several segments, and removing a contact from a segment revokes access on their next request. Try it:
Pick a signed-in user. The table shows the knowledge base exactly as HubSpot would render it — unauthorized articles are absent entirely, titles included.
| Knowledge base view | Authorized segments | Visible to this user |
|---|
One small client, shipped through your existing ClickOnce channel. No customer AD is touched — the app only reads the identity Windows already established.
// Identity: read, never re-authenticate
var upn = UserPrincipal.Current?.UserPrincipalName
?? WindowsIdentity.GetCurrent().Name;
// Assertion: signed with this site's provisioned key (rotatable, revocable)
var payload = new { upn, site = Config.SiteId, nonce = Guid.NewGuid(), iat = Now() };
var assertion = Sign(payload, Config.SiteKey); // HMAC-SHA256 or per-site cert
// Exchange for a one-time token, then hand off to the default browser
var ott = await idp.PostAsync("/handoff/token", assertion);
Process.Start(new ProcessStartInfo {
FileName = $"{Config.IdpUrl}/start?ott={ott}&return={KbUrl}",
UseShellExecute = true // system browser, not embedded
});
This page is a working model prepared for the project discussion: the flows, code, and token formats are the real proposed design; the demo above executes the cryptographic steps locally in your browser so the mechanism can be inspected, not just described. HubSpot protocol facts (SAML/OIDC support, segment-gated private content, JWT sunset) verified against HubSpot's current documentation, August 2026.