Repository navigation
GitHub
GitHub OAuth login with PKCE; access only for members of AllowedTeams, auth.RoleAdmin for AdminTeams members, teams re-checked every minute. The OAuth token stays server-side; Provider.HTTPClient calls the GitHub API as the user.
From examples/github/main.go (gin; tested against the in-repo fake GitHub). On net/http mount the routes with auth.RegisterRoutes as on the Password page.
provider, err := github.New(&github.Options{
ClientID: options.ClientID,
ClientSecret: options.ClientSecret,
ExternalURL: options.ExternalURL,
AllowedTeams: options.AllowedTeams,
AdminTeams: options.AdminTeams,
AuthorizeURL: options.AuthorizeURL,
TokenURL: options.TokenURL,
APIURL: options.APIURL,
Sessions: store,
Observer: ginadapter.Observe, // auth.* fields on the request's wide event
})
if err != nil {
return nil, err
}
guard, err := session.NewGuard(&session.GuardOptions{
Store: store,
LoginURL: provider.LoginURL(),
Refreshers: []session.Refresher{provider}, // refetches teams every minute
Observer: ginadapter.Observe,
})Register ExternalURL + "/auth/github/callback" as the OAuth app's callback URL. Empty AuthorizeURL, TokenURL and APIURL mean github.com; set all three for GitHub Enterprise (https, http only on loopback hosts; APIURL without query or fragment, e.g. https://ghe.example.com/api/v3).
Prefix PathPrefix, default /auth/github.
| Method and path | Purpose |
|---|---|
GET /login |
starts the login, 302 to GitHub; ?return_to=<path> as for OIDC |
GET /callback |
checks teams, rotates the session, stores identity and token, revokes the token of the session it replaced (a re-login; a failure only shows in the outcome), 302 to the return path |
GET /logout |
ends the session, revokes the token at GitHub (a failure only shows in the outcome), 302 to PostLogoutURL
|
POST /refresh-teams |
re-checks teams now; 200 identity, 401/403 ends the session (500 when it cannot end it), 409 conflict (see Refresh) |
Provider github, Subject the numeric GitHub user ID, Username the login, Teams only the teams named in AllowedTeams, AdminTeams or RelevantTeams (org/team-slug, lower-case, sorted), Roles [admin] for admin team members.
Every refresh (the Guard's every minute, POST /refresh-teams) re-derives auth.RoleAdmin from AdminTeams: it adds the role for an admin team member and removes it otherwise, whatever OnLogin did. An OnLogin that strips admin is undone within a minute; gate your application on a role of its own that OnLogin grants (HasRole("app-admin")), not on removing admin.
| Option | Default | Note |
|---|---|---|
ClientID, ClientSecret, ExternalURL, Sessions
|
required |
Sessions must not be SameSite Strict |
AllowedTeams |
required, at least one |
org/team-slug, case-insensitive; everybody else gets 403 and no session |
AdminTeams |
none | admin only together with an allowed team |
RelevantTeams |
none | extra teams kept in Identity.Teams for your own checks |
Scopes |
read:org |
must include read:org, write:org, admin:org, user or repo
|
PostLogoutURL, ErrorURL
|
ExternalURL + "/", none |
as for OIDC |
The provider as Refresher refetches teams once per GuardOptions.RefreshInterval (default 1 min). Removed from every allowed team or token revoked: the session ends. GitHub down or rate-limiting: the session keeps its teams for at most GuardOptions.MaximumUnverifiedAge (default 1 h) since the last successful check, then ends. See Sessions.
The provider is also a session.Revoker: whenever the Guard ends a session it refused (team removal, token rejected, MaximumUnverifiedAge), /refresh-teams ends one, or a re-login replaces one, the token is revoked at GitHub first (DELETE /applications/{client_id}/token, detached from the request, 10 s). A failed revocation only degrades the outcome; the session ends anyway. Not covered, so the token stays valid at GitHub until the user revokes the app: a session that simply expires (MaximumAge; nothing runs at expiry), a GitHub session ended by another provider's logout or replaced by another provider's login on the same Store.
POST /refresh-teams never overwrites a change another request saved while it called GitHub: it applies the teams to that save once more, and answers 409 conflict when that save changed the membership, the admin role or the user (it may be a newer refresh) or the session changed again. Like logout it refuses a cross-site request (Sec-Fetch-Site: cross-site) with 403 before GitHub is called.
login_expired, state_mismatch (400), login_denied, login_failed (401) on the callback; forbidden (403) for users outside AllowedTeams and cross-site /logout or /refresh-teams; conflict (409) on /refresh-teams; internal (500) when GitHub is down. GitHub refusing the code is 401 login_failed.
- Do not forget
Refreshers: []session.Refresher{provider}: without it team removals never reach running sessions. -
HTTPClient(ctx, session)needs the session handle fromstore.Open(request); it sends the token only toAPIURL's host; a redirect to another host (archive downloads,uploads.github.com) goes without it. Example:ExampleProvider_HTTPClientin github/example_test.go. - Logout and refresh-teams refuse
Sec-Fetch-Site: cross-sitewith 403.
Source: github/ (provider.go, handlers.go, teams.go, api.go).
Mirror of docs/wiki at v1.3.0 (486bfa3). Edit the repository, not this wiki.