Proposal: GitHub username identities with the GitHub IdP
Summarizing a thread on Slack:
Currently, when users sign with Sigstore via the GitHub IdP (i.e., federated through Dex), they get an identity token that's bound to the primary email identity for their GitHub account. This is fine in many circumstances, but not fine in others:
- Many GitHub users have multiple emails on their accounts, with the "primary" email not reflecting the identity they intend to sign with. For example: work emails, project-specific emails, etc. This can result in surprising scenarios for users; cf. https://github.com/sigstore/sigstore-python/issues/600#issuecomment-1638624381
- Not all GitHub users mark their email address as public, and instead prefer to use one of GitHub's "noreply" aliases. However, signing with Sigstore through the GitHub IdP leaks their primary email; this poses anonymity and privacy concerns.
- Conceptually, email identities coming from GitHub's IdP are a little "wonky": GitHub isn't itself an email service provider, so these identities reflect the result of GitHub's trust relationship with an email identity (which, in turn, is probably tied to a conventional email verification flow).
This raises the question: what Sigstore used GitHub usernames from the GitHub IdP, rather than emails? This presents some advantages, as well as some challenges:
- Advantage: (1) and (2) are "resolved" in the sense that there are no emails anymore: users would instead be signing with an identity that looks like
woodruffw!github.com. - Advantage: In many contexts, signing with a GitHub username makes more sense than with the user's underlying primary email: GitHub identities more closely track developer identities than emails do, since emails can be reused by companies, etc.
- Challenge: How do we communicate this? User identities are a fuzzier concept than emails, and this would be the first instance of Sigstore actually using them (AFAIK).
- Challenge: How do we prevent client breakage? Not all clients necessarily support user identities yet.
As noted by @bobcallaway, this would require some changes to Dex (configuration only, possibly): we'd need to switch to useLoginAsID: https://dexidp.io/docs/connectors/github/#configuration
cc @sethmlarson @wlynch @haydentherapper additionally as Slack convo members 🙂
As a follow-on to the above: one of the proposed solutions here was to relax Sigstore/Fulcio's current "one-SAN" rule, and allow multiple SANs: zero or more per email associated with the account, plus an OtherName SAN for the username.
This would (in theory) be backwards compatible with existing clients, but might also cause breakage (since clients may currently assume only a single SAN) and introduces some ambiguity (it's unclear which among the SANs is "preferred," or whether they're all equally valid, as well as whether they all refer to the same logical entity.)
I think my personal preference here would be to preserve the "one-SAN" rule, and improve the OAuth/Dex flow page to emphasize the different kind of identity being obtained (e.g. have different sections for email vs. user identities). I'm not sure how hard that would be to do on the Dex side, through (is it possible to have the same IdP registered multiple times, but with different configurations for the resulting ID?)
@wlynch suggested another format which would be using GHs noreply format used for private emails, [email protected]. This might be the best of both worlds - We get username, we get userid for immutability, the format is an email so no clients would need to be updated.
We'd need to patch our instance of Dex to include https://github.com/dexidp/dex/pull/2618, and would likely still need to configure Dex to add both username and user ID.
That solution is nice, although perhaps it should be all or nothing: having it be the user's primary email in some cases rather than the noreply email means that we lose the consistency of having a GitHub "username" identity that we can mangle out of the email identity.
Perhaps it's too much work, but IMO the ideal solution here is:
- Adopt https://github.com/dexidp/dex/pull/2618 for the current GitHub IdP connector, plugging the privacy concern noted above;
- Add another GitHub IdP connector that supports username identities. Visually separate this one in the OAuth flow to help users avoid confusing the two.
OTOH, having two separate GitHub IdP connectors might cause a lot of user confusion, even if visually separated.