Skip to content

Add GitLab Duo management OAuth and PAT endpoints#433

Open
LuxVTZ wants to merge 1 commit intorouter-for-me:mainfrom
LuxVTZ:feat/gitlab-duo-auth-plus
Open

Add GitLab Duo management OAuth and PAT endpoints#433
LuxVTZ wants to merge 1 commit intorouter-for-me:mainfrom
LuxVTZ:feat/gitlab-duo-auth-plus

Conversation

@LuxVTZ
Copy link

@LuxVTZ LuxVTZ commented Mar 11, 2026

Summary

  • add management API endpoints for GitLab Duo OAuth and PAT login
  • add GitLab callback handling and OAuth session support for the control panel
  • add management tests for GitLab PAT persistence and callback file handling

Why

This makes GitLab Duo usable from the management control panel instead of requiring CLI-only login flows, which is important for Windows/release users.

Testing

  • go test ./internal/api/handlers/management ./internal/auth/gitlab ./sdk/auth
  • go test ./... (still fails in unrelated existing amp test)

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the management control panel by integrating GitLab Duo authentication capabilities. It provides users with the flexibility to authenticate using either OAuth or Personal Access Tokens, moving beyond CLI-only login methods. This change is particularly beneficial for Windows and release users, offering a more accessible and user-friendly experience for managing GitLab Duo access.

Highlights

  • GitLab Duo Authentication Endpoints: Added new management API endpoints to support GitLab Duo OAuth and Personal Access Token (PAT) login flows.
  • GitLab Callback Handling: Implemented GitLab callback handling and integrated OAuth session support within the control panel, enabling a seamless web-based authentication experience.
  • New Test Coverage: Introduced new test cases to validate GitLab PAT persistence and the correct handling of OAuth callback files.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • internal/api/handlers/management/auth_files.go
    • Imported the GitLab authentication package.
    • Added constants for GitLab OAuth and PAT login modes.
    • Introduced new helper functions for GitLab base URL resolution, authentication metadata construction, direct access metadata merging, user email and account identification, file name sanitization, and token masking.
    • Implemented RequestGitLabToken handler for GitLab OAuth flow.
    • Implemented RequestGitLabPATToken handler for GitLab Personal Access Token flow.
  • internal/api/handlers/management/auth_files_gitlab_test.go
    • Added a new test file for GitLab authentication.
    • Included TestRequestGitLabPATToken_SavesAuthRecord to verify PAT saving and metadata.
    • Added TestPostOAuthCallback_GitLabWritesPendingCallbackFile to test OAuth callback file creation.
    • Included TestNormalizeOAuthProvider_GitLab to ensure correct provider normalization.
  • internal/api/handlers/management/oauth_sessions.go
    • Updated the NormalizeOAuthProvider function to recognize 'gitlab' as a valid OAuth provider.
  • internal/api/server.go
    • Registered a new GET endpoint /gitlab/callback to process GitLab OAuth redirects.
    • Added new management routes: a GET endpoint for /gitlab-auth-url to initiate OAuth, and a POST endpoint for /gitlab-auth-url to handle PAT requests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@LuxVTZ
Copy link
Author

LuxVTZ commented Mar 11, 2026

Related Web UI PR for the management panel GitLab cards: router-for-me/Cli-Proxy-API-Management-Center#143

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds management API endpoints for GitLab Duo, including OAuth and PAT login flows, and callback handling. However, two significant security issues were identified in the RequestGitLabToken endpoint: sensitive OAuth credentials are passed via query parameters, leading to leakage in logs, and the lack of validation for the base_url parameter combined with the use of a GET route for state-changing operations creates a risk of SSRF and credential harvesting via CSRF or social engineering. Additionally, there's a critical panic risk in the OAuth flow due to unhandled errors, a medium-severity issue where raw errors are exposed to the client, and several medium-severity maintainability issues related to logging, error handling, and code redundancy. Addressing these security and maintainability concerns is crucial.

Comment on lines +1794 to +1796
var payload map[string]string
_ = json.Unmarshal(data, &payload)
_ = os.Remove(waitFile)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There's a potential panic here. If os.ReadFile succeeds but the file content is not valid JSON, json.Unmarshal will return an error, which is currently ignored. payload will be nil, and the subsequent access payload["error"] on line 1797 will cause a panic. You should handle the error from json.Unmarshal to prevent this.

var payload map[string]string
if err := json.Unmarshal(data, &payload); err != nil {
    log.Errorf("Failed to unmarshal gitlab oauth callback file for state %s: %v", state, err)
    SetOAuthSessionError(state, "Invalid callback data received")
    _ = os.Remove(waitFile) // Attempt to clean up
    return
}
_ = os.Remove(waitFile)

Comment on lines +1714 to +1722
func (h *Handler) RequestGitLabToken(c *gin.Context) {
ctx := context.Background()
ctx = PopulateAuthContext(ctx, c)

fmt.Println("Initializing GitLab Duo authentication...")

baseURL := gitLabBaseURLFromRequest(c)
clientID := strings.TrimSpace(c.Query("client_id"))
clientSecret := strings.TrimSpace(c.Query("client_secret"))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The RequestGitLabToken handler retrieves sensitive information like client_id and client_secret from query parameters. Sensitive information like OAuth client secrets should never be passed in query strings as they are logged in plain text by web servers, proxies, and browser history, leading to credential leakage. Additionally, this endpoint performs state-changing operations (registering sessions, starting goroutines) but is defined as a GET route. According to RFC 7231, GET methods should be idempotent and not have side effects. Using GET for such operations also makes the endpoint vulnerable to Cross-Site Request Forgery (CSRF) attacks, especially given the permissive CORS configuration in this project. It is recommended to convert this endpoint to a POST route and pass all parameters in the request body. Furthermore, the fmt.Println call on line 1718, and similar calls within this block, should be replaced with calls to the structured logger (e.g., log.Info or log.Infof). Using the project's logger ensures consistent, level-based logging which is more maintainable and useful, especially in production.


fmt.Println("Initializing GitLab Duo authentication...")

baseURL := gitLabBaseURLFromRequest(c)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The RequestGitLabToken handler accepts an arbitrary base_url from query parameters without validation. This URL is subsequently used to make server-side requests, including POST requests to the /oauth/token endpoint where the client_secret is transmitted.

An attacker could potentially trick an authenticated administrator into clicking a specially crafted link that initiates this flow with an attacker-controlled base_url. This would result in the server sending the OAuth client secret to the attacker's server (SSRF / Credential Leakage).

Comment on lines +1085 to +1092
if provider := strings.TrimSpace(direct.ModelDetails.ModelProvider); provider != "" {
modelDetails["model_provider"] = provider
metadata["model_provider"] = provider
}
if model := strings.TrimSpace(direct.ModelDetails.ModelName); model != "" {
modelDetails["model_name"] = model
metadata["model_name"] = model
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The model_provider and model_name fields are being added to both the top-level metadata map and a nested model_details map. This seems redundant. To improve maintainability and reduce duplication, consider storing these values only in the model_details map. If both are required for backward compatibility, adding a comment to explain this would be beneficial.

Comment on lines +1902 to +1904
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": err.Error()})
return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Returning err.Error() directly in the API response can leak internal implementation details or sensitive information from upstream services, which could be a security risk. It's better to log the detailed error on the server and return a more generic error message to the client.

if err != nil {
		log.Errorf("Failed to get GitLab current user: %v", err)
		c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": "failed to validate personal access token"})
		return
	}

errStr = c.Query("error_description")
}
if state != "" {
_, _ = managementHandlers.WriteOAuthCallbackFileForPendingSession(s.cfg.AuthDir, "gitlab", state, code, errStr)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error returned from WriteOAuthCallbackFileForPendingSession is being ignored. This function can fail for several reasons (e.g., invalid state, file system errors). Ignoring the error can make debugging difficult if the OAuth flow fails. It's recommended to log this error.

if _, err := managementHandlers.WriteOAuthCallbackFileForPendingSession(s.cfg.AuthDir, "gitlab", state, code, errStr); err != nil {
				log.Warnf("Failed to write gitlab oauth callback file for state %s: %v", state, err)
			}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant