GitHub sign-in, for github.com and GitHub Enterprise Server.
Its own package because GitHub is not OpenID Connect
There is no identity token, so “verify” cannot mean “check a signature”. It means spending the authorization code for an access token over TLS, then reading the profile back from GitHub with it.
The port allows this — complete returns a profile and never promises how it
was obtained — which is exactly the flexibility a second protocol needed, and
the reason this exists rather than as a preset inside
the OIDC adapter.
It depends only on the identity domain package. No SDK: two endpoints and two
reads are plain fetch, and there is no cryptography here to get wrong.
Install
npm install @apograph/identity-provider-githubimport { createGithubProvider } from '@apograph/identity-provider-github';
IdentityPlugin(config.plugins.identity, {
sso: {
providers: [{ name: 'github', provider: createGithubProvider(settings) }]
}
});Configuration
| Variable | What it does |
|---|---|
SSO_GITHUB_CLIENT_ID | The OAuth app’s client id |
SSO_GITHUB_CLIENT_SECRET | Required — see below |
SSO_GITHUB_NAME | Registration name |
SSO_GITHUB_LABEL | The sign-in button’s text |
SSO_GITHUB_ENTERPRISE_URL | A GitHub Enterprise Server root. Empty for github.com |
SSO_GITHUB_ORG | Shapes GitHub’s account chooser. Cosmetic |
Three consequences of not being OIDC
The client secret is required. There is no PKCE in this flow, so the secret is the only thing proving the code is being redeemed by the application it was issued to. A configuration without one is refused.
state is the whole replay defence. There is no nonce to bind into a token,
so the adapter checks the echoed state itself rather than assuming the caller
did — and sends neither a nonce nor a PKCE challenge, because sending values a
provider ignores is noise that reads as protection.
The address comes from the verified-emails endpoint, never the profile. A profile address is something a person can set to anything, and it is frequently empty. Trusting it would break the port’s third clause in its most literal form: an unverified string used as if the provider had vouched for it.
No verified address is a refusal, not an unverified profile
An account with no verified address is refused outright rather than reported
as emailVerified: false.
The distinction matters. A false would still let a deployment link the account
if it ever relaxed that rule — and there is no address here worth linking, because
GitHub has told us it does not know whether anyone can be reached at it.
Other things worth knowing
The subject is the numeric id, as a string, never the login. A login can be changed, and a released login can be claimed by somebody else — the same failure mode that keeps an email out of that field.
accept: application/json on the token exchange. Without it GitHub answers
form-encoded, which parses as an empty object and reads as “no access token”
three lines later.
A 200 with an error field is a failure. GitHub reports a bad code that
way, so the status alone is not the check.
Enterprise Server serves its API under /api/v3, while github.com uses a
separate host. Getting that wrong is a 404 on the profile read, one step after a
token exchange that appeared to work.
SSO_GITHUB_ORG is cosmetic, like Google’s hd. It shapes the account
chooser; Apograph’s own rules decide who gets in.