This guide explains how to integrate GitHub and Gitea OAuth authentication with AuthGate.
- Multiple OAuth Providers: Support for GitHub, Gitea, and extensible to other providers
- Email-based Account Linking: Automatically links OAuth accounts to existing users with the same email
- Auto-registration: New users can be automatically created via OAuth (controlled by
OAUTH_AUTO_REGISTERconfig) - Multiple Authentication Methods: Users can have both password and OAuth authentication
- Profile Sync: Avatar and profile information synced from OAuth providers
type User struct {
ID string
Username string // Unique
Email string // Unique and required
PasswordHash string // Empty for OAuth-only users
AvatarURL string // Synced from OAuth
// ...
}type OAuthConnection struct {
ID string
UserID string
Provider string // "github", "gitea"
ProviderUserID string // Provider's user ID
AccessToken string // OAuth access token
// ...
}- Existing OAuth Connection: User clicks "Sign in with GitHub" → Already linked → Login immediately
- Existing User (same email): OAuth email matches existing user → Automatically link and login
- New User: No existing user or connection → Create new user account (if
OAUTH_AUTO_REGISTER=true), otherwise show error
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click "New OAuth App"
- Fill in:
- Application name: AuthGate
- Homepage URL:
http://localhost:8080(for development) - Authorization callback URL:
http://localhost:8080/auth/callback/github
- Click "Register application"
- Copy the Client ID and generate a Client Secret
Add to .env:
# GitHub OAuth
GITHUB_OAUTH_ENABLED=true
GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
GITHUB_REDIRECT_URL=http://localhost:8080/auth/callback/github
GITHUB_SCOPES=user:email- Start AuthGate:
./bin/authgate server - Visit
http://localhost:8080/login - Click "Sign in with GitHub"
- Authorize the application
- You'll be logged in and redirected to
/device
- Log in to your Gitea instance
- Go to Settings → Applications → Manage OAuth2 Applications
- Click "Create a new OAuth2 Application"
- Fill in:
- Application Name: AuthGate
- Redirect URI:
http://localhost:8080/auth/callback/gitea
- Click "Create Application"
- Copy the Client ID and Client Secret
Add to .env:
# Gitea OAuth
GITEA_OAUTH_ENABLED=true
GITEA_URL=https://gitea.example.com
GITEA_CLIENT_ID=your_client_id_here
GITEA_CLIENT_SECRET=your_client_secret_here
GITEA_REDIRECT_URL=http://localhost:8080/auth/callback/gitea
GITEA_SCOPES=read:user- Start AuthGate:
./bin/authgate server - Visit
http://localhost:8080/login - Click "Sign in with Gitea"
- Authorize the application
- You'll be logged in and redirected to
/device
For production, use HTTPS URLs:
# Production URLs
BASE_URL=https://auth.example.com
GITHUB_REDIRECT_URL=https://auth.example.com/auth/callback/github
GITEA_REDIRECT_URL=https://auth.example.com/auth/callback/giteaUpdate your OAuth app settings in GitHub/Gitea to use the production callback URLs.
- HTTPS Required: Always use HTTPS in production
- Secure Secrets: Use environment variables or secret management for credentials
- Email Validation: OAuth providers return email addresses that are used for account linking
- Token Storage: OAuth tokens are stored in the database (consider encryption at rest)
- TLS Verification: Never set
OAUTH_INSECURE_SKIP_VERIFY=truein production - only use for development with self-signed certificates
1. User clicks "Sign in with GitHub"
2. GitHub callback: email=alice@example.com, username=alice
3. System checks:
- No OAuth connection exists
- No user with email=alice@example.com exists
4. System creates:
- New user: username=alice, email=alice@example.com, password=""
- OAuth connection: provider=github, provider_user_id=12345
5. User is logged in1. User Bob already exists:
- username: bob
- email: bob@example.com
- password: (set)
2. Bob clicks "Sign in with GitHub"
3. GitHub callback: email=bob@example.com
4. System checks:
- No OAuth connection exists
- User with email=bob@example.com exists ✓
5. System creates:
- OAuth connection linking Bob's account to GitHub
6. Bob is logged in
Bob can now login with:
- Username/password (existing method)
- GitHub OAuth (newly added)Alice can have:
- Local auth: alice / password123
- GitHub: alice-github (linked)
- Gitea: alice-work (linked)
All three methods log into the same AuthGate account.Problem: OAuth provider doesn't return an email address.
Solution:
- GitHub: Make sure your email is public or grant
user:emailscope - Gitea: Check that your Gitea account has an email address
Problem: OAuth username conflicts with existing local user.
Solution: System automatically appends provider name or number suffix:
alice→alice-githubalice-github→alice-github-1
Problem: Browser session expired during OAuth flow.
Solution: Clear cookies and try again.
Problem: OAuth fails with TLS certificate verification errors when using self-signed certificates.
Solution: For development/testing environments only:
# .env
OAUTH_INSECURE_SKIP_VERIFY=trueOAuth authentication adds these endpoints:
GET /auth/login/:provider- Initiates OAuth flow (provider: github, gitea)GET /auth/callback/:provider- OAuth callback endpoint
| Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_OAUTH_ENABLED |
No | false |
Enable GitHub OAuth |
GITHUB_CLIENT_ID |
If enabled | - | GitHub OAuth Client ID |
GITHUB_CLIENT_SECRET |
If enabled | - | GitHub OAuth Client Secret |
GITHUB_REDIRECT_URL |
If enabled | - | GitHub OAuth callback URL |
GITHUB_SCOPES |
No | user:email |
GitHub OAuth scopes |
GITEA_OAUTH_ENABLED |
No | false |
Enable Gitea OAuth |
GITEA_URL |
If enabled | - | Gitea instance URL |
GITEA_CLIENT_ID |
If enabled | - | Gitea OAuth Client ID |
GITEA_CLIENT_SECRET |
If enabled | - | Gitea OAuth Client Secret |
GITEA_REDIRECT_URL |
If enabled | - | Gitea OAuth callback URL |
GITEA_SCOPES |
No | read:user |
Gitea OAuth scopes |
OAUTH_AUTO_REGISTER |
No | true |
Allow auto-creation of accounts |
OAUTH_TIMEOUT |
No | 15s |
HTTP client timeout for OAuth requests |
OAUTH_INSECURE_SKIP_VERIFY |
No | false |
Skip TLS verification (dev/testing only) |
Note on Auto-Registration: When OAUTH_AUTO_REGISTER=false, only users with existing accounts (matched by email) can login via OAuth. New users attempting to login will see an error message asking them to contact the administrator. This is useful for organizations that want to restrict OAuth access to pre-approved users only.
To add a new OAuth provider (e.g., GitLab):
- Add provider in
internal/auth/oauth_provider.go:
func NewGitLabProvider(cfg OAuthProviderConfig) *OAuthProvider {
return &OAuthProvider{
provider: "gitlab",
config: &oauth2.Config{
ClientID: cfg.ClientID,
ClientSecret: cfg.ClientSecret,
RedirectURL: cfg.RedirectURL,
Scopes: cfg.Scopes,
Endpoint: gitlab.Endpoint,
},
}
}- Add config in
internal/config/config.go:
GitLabOAuthEnabled bool
GitLabClientID string
// ...- Initialize in
main.go:
if cfg.GitLabOAuthEnabled {
providers["gitlab"] = auth.NewGitLabProvider(...)
}- Update login template to add GitLab button
CREATE TABLE oauth_connections (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
provider TEXT NOT NULL,
provider_user_id TEXT NOT NULL,
provider_username TEXT,
provider_email TEXT,
avatar_url TEXT,
access_token TEXT,
refresh_token TEXT,
token_expiry TIMESTAMP,
last_used_at TIMESTAMP,
created_at TIMESTAMP,
updated_at TIMESTAMP,
UNIQUE(provider, provider_user_id),
UNIQUE(user_id, provider),
FOREIGN KEY(user_id) REFERENCES users(id)
);(provider, provider_user_id)- Unique, for OAuth provider lookup(user_id, provider)- Unique, ensures one connection per provider per useruser_id- For querying all connections for a user