83dd847b7449dd0fa83c22a4d60854f8d20d2847 max Fri Sep 18 08:51:14 2026 -0700 hgLogin: stop telling a CILogon user that CILogon shares no email address #Preview2 week - bugs introduced now will need a build patch to fix QA found three messages on the social sign-in pages claiming the provider does not give us an address. That was written when ORCID, which really releases none, was the only provider reaching those pages. CILogon does release the institution's address; we drop it because CILogon never marks it verified and login.oauth.cilogon.trustEmail is what says we may take it anyway. Once the address is dropped, nothing downstream could tell "released nothing" from "released something we would not take". oauthFetchIdentity now keeps the dropped address in a separate field that matching and sign-in never look at, and the three messages read it: the choose a username page, the confirmation page, and the one that turns down a typed address that already belongs to an account. The address box on the choose a username page starts from it as well, since retyping what we were just handed is the last thing a person wants to do. It still has to clear the duplicate check and be confirmed by mail, exactly as a typed address does. Three more things on the confirmation page, all from the same QA pass: The generic "a confirmation email has been sent" paragraph printed below the "use this address instead" form, so it read as if a mail had already gone to whatever was about to be typed in. It now goes above the form. Correcting the address redisplayed the same page with the new address swapped in and nothing to say the change had worked. It now says so. The rejection reason for an address that is already in use was set but never printed, so a refused change looked like nothing happening at all; that is printed now too. Reworded the unconfirmed-account explanation as QA suggested. refs #38339 diff --git src/hg/hgLogin/oauthLogin.h src/hg/hgLogin/oauthLogin.h index 6b74dff85a1..a2bf80bdbcf 100644 --- src/hg/hgLogin/oauthLogin.h +++ src/hg/hgLogin/oauthLogin.h @@ -1,68 +1,73 @@ /* oauthLogin - social login for hgLogin via OAuth 2.0 / OpenID Connect. * * Providers are configured entirely in hg.conf. List the ones to offer with: * login.oauth.providers = google,orcid,github,myuni * and give each a block of settings: * login.oauth.<name>.label Button text (defaults to <name>) * login.oauth.<name>.clientId OAuth client id (required) * login.oauth.<name>.clientSecret OAuth client secret (required) * login.oauth.<name>.type "oidc" (default) or "github" * login.oauth.<name>.issuer OIDC issuer; endpoints are auto-discovered from * <issuer>/.well-known/openid-configuration * login.oauth.<name>.authUrl Explicit endpoints (used when there is no issuer, * login.oauth.<name>.tokenUrl or to override discovery) * login.oauth.<name>.userinfoUrl * login.oauth.<name>.scopes Space-separated (default "openid email profile") * login.oauth.<name>.trustEmail Accept this provider's address even when it does not * say email_verified (default off). Turn it on only for * a provider that gets the address from somewhere the * user cannot type into, e.g. a federation that reads it * from the user's own institution. Without it, an * unverified address is discarded and the user is asked * for one and has to confirm it by mail. * * "google", "orcid" and "github" are known names with built-in endpoints, so those only * need clientId/clientSecret. The older login.<name>.clientId/clientSecret keys are still * honored. A provider is offered only when both its clientId and clientSecret are set. */ /* Copyright (C) 2026 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #ifndef OAUTHLOGIN_H #define OAUTHLOGIN_H struct oauthIdentity /* An authenticated identity returned by an external OAuth/OpenID provider. */ { struct oauthIdentity *next; char *provider; /* provider short name, e.g. "google" */ char *subject; /* stable, unique id from the provider */ char *email; /* email reported by provider, or NULL */ boolean emailVerified; /* TRUE if the provider asserts the email is verified */ + char *emailUnverified; /* an address the provider released that we would not take: it did + * not say the address is verified and hg.conf does not trust this + * provider (see trustEmail). Never used to match an account or to + * sign anyone in -- only to say why we are asking the user for an + * address, and to offer it back as a starting point. */ char *displayName; /* full name from provider, or NULL */ }; boolean oauthAnyProviderEnabled(); /* Return TRUE if at least one social login provider is configured. */ boolean oauthProviderEnabled(char *name); /* Return TRUE if the named provider is configured (clientId and clientSecret set). */ struct slName *oauthProviderNames(); /* Return the short names of all configured providers, in the order listed in hg.conf. * Do not free (owned by an internal cache). */ char *oauthProviderLabel(char *name); /* Return the display label for a provider (falls back to the name). Do not free. */ char *oauthLoginUrl(char *name, char *redirectUri, char *state); /* Return the provider's authorization URL to redirect the browser to, or NULL. Allocd. */ struct oauthIdentity *oauthFetchIdentity(char *name, char *code, char *redirectUri); /* Exchange the authorization code for tokens and fetch the authenticated identity, or NULL * on any failure. Dispose of the result with oauthIdentityFree(). */ void oauthIdentityFree(struct oauthIdentity **pId); /* Free an oauthIdentity. */ #endif /* OAUTHLOGIN_H */