Documentation
¶
Overview ¶
Package github implements the OAuth provider interface for GitHub OAuth Apps. It supports user authentication, token exchange, and access to GitHub APIs.
GitHub OAuth differs from OIDC providers in several key ways:
- No OIDC discovery: Endpoints are hardcoded (not dynamically discovered)
- Non-expiring tokens: Standard OAuth Apps issue tokens that don't expire
- No refresh tokens: Standard OAuth Apps don't provide refresh tokens
- Email privacy: User emails may be private, requiring a separate API call
Default Scopes ¶
When no custom scopes are provided, the provider uses:
- user:email: Read user email addresses (required for UserInfo.Email)
- read:user: Read user profile data
Organization Access Control ¶
The provider supports restricting authentication to members of specific GitHub organizations. When AllowedOrganizations is configured:
- The "read:org" scope is automatically added if not present
- User membership is validated on every token validation
- Users not in allowed organizations receive an access denied error
Security Considerations ¶
GitHub tokens don't expire by default, making secure storage critical. Use the library's encryption features (security package) for token storage. Consider implementing periodic token rotation or user re-authentication.
Rate Limiting ¶
GitHub API has rate limits (5,000 requests/hour for authenticated requests). The provider handles 403 rate limit responses gracefully, but high-volume applications should implement their own rate limiting.
Example Usage ¶
provider, err := github.NewProvider(&github.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
RedirectURL: "http://localhost:8080/oauth/callback",
})
if err != nil {
log.Fatal(err)
}
// With organization restriction
provider, err := github.NewProvider(&github.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
RedirectURL: "http://localhost:8080/oauth/callback",
AllowedOrganizations: []string{"giantswarm"},
})
Index ¶
- Variables
- type Config
- type Provider
- func (p *Provider) AuthorizationURL(state string, codeChallenge string, codeChallengeMethod string, ...) string
- func (p *Provider) DefaultScopes() []string
- func (p *Provider) ExchangeCode(ctx context.Context, code string, verifier string) (*oauth2.Token, error)
- func (p *Provider) GetProviderToken(accessToken string) *oauth2.Token
- func (p *Provider) GetUserOrganizations(ctx context.Context, accessToken string) ([]string, error)
- func (p *Provider) HealthCheck(ctx context.Context) error
- func (p *Provider) Name() string
- func (p *Provider) RefreshToken(_ context.Context, _ string) (*oauth2.Token, error)
- func (p *Provider) RevokeToken(_ context.Context, _ string) error
- func (p *Provider) ValidateToken(ctx context.Context, accessToken string) (*providers.UserInfo, error)
Constants ¶
This section is empty.
Variables ¶
var ErrOrganizationRequired = errors.New("user is not a member of any allowed organization")
ErrOrganizationRequired is returned when a user is not a member of any allowed organization.
var ErrRefreshNotSupported = errors.New("github oauth apps do not support token refresh")
ErrRefreshNotSupported is returned when attempting to refresh a token. GitHub OAuth Apps issue non-expiring access tokens and don't support refresh.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// ClientID is the GitHub OAuth App client ID.
ClientID string
// ClientSecret is the GitHub OAuth App client secret.
ClientSecret string
// RedirectURL is the OAuth callback URL.
RedirectURL string
// Scopes are optional custom scopes (defaults to ["user:email", "read:user"]).
Scopes []string
// RequireVerifiedEmail requires the user's email to be verified (default: true).
RequireVerifiedEmail *bool
// AllowedOrganizations restricts login to members of specific organizations.
// When set, the "read:org" scope is automatically added if not present.
AllowedOrganizations []string
// HTTPClient is an optional custom HTTP client.
HTTPClient *http.Client
// RequestTimeout is the timeout for GitHub API calls (default: 30s).
RequestTimeout time.Duration
}
Config holds GitHub OAuth configuration.
type Provider ¶
Provider implements the providers.Provider interface for GitHub OAuth.
func NewProvider ¶
NewProvider creates a new GitHub OAuth provider.
func (*Provider) AuthorizationURL ¶
func (p *Provider) AuthorizationURL(state string, codeChallenge string, codeChallengeMethod string, scopes []string, authOpts *providers.AuthorizationURLOptions) string
AuthorizationURL generates the GitHub OAuth authorization URL with optional PKCE. If scopes is empty, the provider's default configured scopes are used. GitHub supports PKCE but doesn't require it for confidential clients. opts contains optional OIDC parameters like login_hint (nil for defaults). Note: GitHub doesn't support all OIDC parameters, but login is supported as "login" param.
func (*Provider) DefaultScopes ¶
DefaultScopes returns a deep copy of the provider's configured default scopes so callers cannot mutate the provider's slice.
func (*Provider) ExchangeCode ¶
func (p *Provider) ExchangeCode(ctx context.Context, code string, verifier string) (*oauth2.Token, error)
ExchangeCode exchanges an authorization code for tokens with optional PKCE verification. Returns standard oauth2.Token. Note: GitHub OAuth Apps don't return refresh tokens.
func (*Provider) GetProviderToken ¶
GetProviderToken returns a token suitable for making additional GitHub API calls. This is useful for applications that need to access GitHub APIs beyond basic auth.
func (*Provider) GetUserOrganizations ¶
GetUserOrganizations returns the list of organizations the user belongs to. This is useful for applications that want to display org membership or implement custom authorization logic beyond simple org validation.
Requires the "read:org" scope.
func (*Provider) HealthCheck ¶
HealthCheck verifies that the GitHub API is reachable. It performs a lightweight check by calling the rate limit endpoint.
Security Considerations:
- This method is designed for server-side health monitoring
- DO NOT expose error details to untrusted clients
- For public endpoints, return generic "healthy/unhealthy" status only
func (*Provider) RefreshToken ¶
RefreshToken attempts to refresh an expired token. Returns ErrRefreshNotSupported because GitHub OAuth Apps don't support token refresh. Standard GitHub OAuth Apps issue non-expiring access tokens.
func (*Provider) RevokeToken ¶
RevokeToken revokes a token at GitHub. GitHub doesn't have a public revocation endpoint for OAuth tokens. This method returns nil (graceful degradation) since server-side revocation isn't supported. Users must revoke tokens through GitHub settings.