-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add third-party OAuth login and extend user authentication #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
appleboy
commented
Jan 24, 2026
- Add support for third-party OAuth 2.0 login using GitHub and Gitea
- Extend .env and configuration to handle OAuth settings, client credentials, OAuth timeouts, and auto-registration options
- Integrate OAuth provider models and database tables, including user-to-OAuth account linking
- Introduce flexible user authentication: link OAuth to existing users by email or create new users via OAuth
- Add robust handler logic for OAuth login/callback, CSRF (state) protection, error handling, and session management
- Render "Sign in with GitHub/Gitea" buttons and branding on the login page when providers are enabled
- Enhance user model with required email, full name, and avatar fields; refactor for OAuth compatibility
- Add extensive documentation and setup guides for OAuth provider integration, flows, and security considerations
- Refine error template to display more user-friendly error messages
- Update database logic for user and OAuth connection operations and make "oauth_clients" pluralized
- Improve config and parsing utilities for OAuth scopes and settings
- Add OAuth-related dependencies to go.mod for OAuth2 library support
- Add support for third-party OAuth 2.0 login using GitHub and Gitea - Extend .env and configuration to handle OAuth settings, client credentials, OAuth timeouts, and auto-registration options - Integrate OAuth provider models and database tables, including user-to-OAuth account linking - Introduce flexible user authentication: link OAuth to existing users by email or create new users via OAuth - Add robust handler logic for OAuth login/callback, CSRF (state) protection, error handling, and session management - Render "Sign in with GitHub/Gitea" buttons and branding on the login page when providers are enabled - Enhance user model with required email, full name, and avatar fields; refactor for OAuth compatibility - Add extensive documentation and setup guides for OAuth provider integration, flows, and security considerations - Refine error template to display more user-friendly error messages - Update database logic for user and OAuth connection operations and make "oauth_clients" pluralized - Improve config and parsing utilities for OAuth scopes and settings - Add OAuth-related dependencies to go.mod for OAuth2 library support Signed-off-by: appleboy <appleboy.tw@gmail.com>
✅ Deploy Preview for authgate-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds comprehensive OAuth 2.0 third-party authentication support to AuthGate, enabling users to sign in with GitHub and Gitea accounts. The implementation includes email-based account linking, auto-registration, and flexible user authentication flows.
Changes:
- OAuth provider integration for GitHub and Gitea with extensible architecture
- User and OAuth connection models with database migrations
- OAuth login/callback handlers with CSRF protection and session management
- Configuration extensions for OAuth settings, client credentials, and HTTP client options
- Login page enhancements with OAuth provider buttons and branding
- Comprehensive documentation including setup guides and troubleshooting
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| main.go | Initializes OAuth providers, creates custom HTTP client with TLS config, registers OAuth routes |
| internal/handlers/oauth_handler.go | Implements OAuth login/callback flow with state validation and user authentication |
| internal/handlers/auth.go | Extends login page handler to accept and render OAuth providers |
| internal/services/user.go | Adds OAuth authentication logic with account linking and user creation |
| internal/models/user.go | Makes Email required and adds FullName/AvatarURL fields for OAuth integration |
| internal/models/oauth_connection.go | New model for OAuth provider connections with token storage |
| internal/models/oauth_client.go | Updates table name from singular to plural |
| internal/store/sqlite.go | Adds CRUD operations for OAuth connections and user email lookups |
| internal/config/config.go | Adds OAuth configuration fields and custom string parsing utilities |
| internal/auth/oauth_provider.go | Implements GitHub and Gitea OAuth providers with user info retrieval |
| internal/templates/login.html | Adds OAuth provider buttons with conditional rendering |
| internal/templates/error.html | Enhances error display with optional message field |
| docs/OAUTH_SETUP.md | Comprehensive OAuth setup guide with examples and troubleshooting |
| README.md | Documents OAuth features, endpoints, and configuration |
| .env.example | Adds OAuth configuration examples |
| go.mod/go.sum | Adds golang.org/x/oauth2 dependency |
Comments suppressed due to low confidence (2)
internal/models/oauth_client.go:23
- Changing the table name from "oauth_client" to "oauth_clients" is a breaking change for existing deployments. This will cause the application to create a new table instead of using the existing one, potentially losing all registered OAuth clients. A database migration strategy is needed to rename the table or the code should maintain backward compatibility.
internal/models/oauth_client.go:21 - The comment still refers to "oauth_client" (singular) but the return value is "oauth_clients" (plural). Update the comment to match the actual table name for consistency.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| session.Delete("oauth_provider") | ||
|
|
||
| // Save user ID in session | ||
| session.Set("user_id", user.ID) |
Copilot
AI
Jan 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The OAuth callback does not set the SessionUsername in the session, only the user_id. This creates an inconsistency with the regular login flow which sets both. This could cause issues in pages that rely on SessionUsername (like device.html which displays the username). Add session.Set("username", user.Username) after line 169.
| session.Set("user_id", user.ID) | |
| session.Set("user_id", user.ID) | |
| session.Set("username", user.Username) |
| bytes := make([]byte, length) | ||
| if _, err := rand.Read(bytes); err != nil { | ||
| // Fallback to timestamp-based generation if crypto rand fails | ||
| return fmt.Sprintf("%d", time.Now().UnixNano())[:length] |
Copilot
AI
Jan 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback string slicing in generateShortRandomString could panic if UnixNano returns a value shorter than the requested length. For example, if length is 15 but the string representation is only 13 characters, this will cause an index out of range panic. Consider using a safer approach like encoding the timestamp with base64 or repeating it to ensure sufficient length.
| return fmt.Sprintf("%d", time.Now().UnixNano())[:length] | |
| ts := fmt.Sprintf("%d", time.Now().UnixNano()) | |
| // Ensure the fallback string is at least the requested length | |
| for len(ts) < length { | |
| ts += ts | |
| } | |
| return ts[:length] |
| // Extract base URL from endpoint | ||
| baseURL := p.config.Endpoint.AuthURL | ||
| // Remove "/login/oauth/authorize" to get base URL | ||
| apiURL := baseURL[:len(baseURL)-len("/login/oauth/authorize")] + "/api/v1/user" |
Copilot
AI
Jan 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API URL construction using string slicing is fragile and will panic if the AuthURL doesn't contain the expected suffix "/login/oauth/authorize". Consider using url.Parse and path manipulation functions from the net/url package for safer URL construction, or store the base URL separately in the provider configuration.
- Fix table name override comment to reference OAuthConnection and its correct table name - Refactor username sanitization to remove regexp dependency and improve clarity by using a rune map Signed-off-by: appleboy <appleboy.tw@gmail.com>
- Refactor string splitting and trimming logic to use standard library functions for improved simplicity and reliability - Remove custom implementations for splitting strings and trimming whitespace Signed-off-by: appleboy <appleboy.tw@gmail.com>