Skip to content

feat: allow no auth for api, close #1104#1107

Merged
looplj merged 1 commit intorelease/v0.9.xfrom
dev-tmp
Mar 20, 2026
Merged

feat: allow no auth for api, close #1104#1107
looplj merged 1 commit intorelease/v0.9.xfrom
dev-tmp

Conversation

@looplj
Copy link
Copy Markdown
Owner

@looplj looplj commented Mar 19, 2026

No description provided.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

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 introduces the concept of a 'noauth' API key, designed to allow certain API endpoints to be accessed without authentication. This feature is controlled by a new configuration option, server.api.auth.allow_no_auth. The changes include modifications to the API key model, authentication middleware, and API key management logic to accommodate this new type of API key.

Highlights

  • No-Auth API Key: Introduces a new 'noauth' API key type, allowing certain API endpoints to be accessed without authentication when the server.api.auth.allow_no_auth configuration is enabled.
  • Configuration Option: Adds a server.api.auth.allow_no_auth configuration option to enable or disable the use of 'noauth' API keys.
  • Middleware Changes: Updates the API key authentication middleware to support the new 'noauth' API key type when the allow_no_auth configuration is enabled.
  • API Key Restrictions: Restricts the creation, updating, and status modification of 'noauth' API keys through regular API operations; these keys are intended for system-level use only.
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.

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.

Copy link
Copy Markdown
Contributor

@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 introduces a new 'noauth' API key type, which is integrated across the application's schema, backend logic, and frontend. The changes include updating database schemas, GraphQL definitions, and API key management services to support this new type, along with a configuration option to enable or disable its use. When enabled, a system-managed 'noauth' API key is ensured on startup, and authentication middleware is adjusted to handle it. Review comments highlight a potential issue in the authentication middleware where malformed API keys might be incorrectly treated as 'noauth' requests, and consistently point out a typo in the AnthenticateAPIKey function name across multiple files.

Comment on lines +37 to +39
if err != nil && allowNoAuth {
key = biz.NoAuthAPIKeyValue
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The logic if err != nil && allowNoAuth { key = biz.NoAuthAPIKeyValue } might be too broad. If ExtractAPIKeyFromRequest returns an error because the key is malformed (e.g., "Bearer malformed_key"), and allowNoAuth is true, this code will treat it as a request for NoAuthAPIKeyValue. This could mask actual invalid key attempts. It might be better to only default to NoAuthAPIKeyValue if err specifically indicates that no key was provided (e.g., http.ErrNoCookie or similar, or a custom error indicating absence). If a key was provided but was invalid, it should still result in an unauthorized error.

require.Contains(t, err.Error(), "api key project not valid")
}

func TestAuthService_AnthenticateAPIKey_NoAuthKeyRequiresDisabledMode(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey_NoAuthKeyRequiresDisabledMode appears to have a typo and should be AuthenticateAPIKey_NoAuthKeyRequiresDisabledMode. This should be corrected for clarity and consistency.

Suggested change
func TestAuthService_AnthenticateAPIKey_NoAuthKeyRequiresDisabledMode(t *testing.T) {
func TestAuthService_AuthenticateAPIKey_NoAuthKeyRequiresDisabledMode(t *testing.T) {

require.Error(t, err)
require.Contains(t, err.Error(), "noauth api key is only available when api auth is disabled")

authenticatedAPIKey, err := authService.AnthenticateAPIKey(ctx, noAuthKey.Key, true)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
authenticatedAPIKey, err := authService.AnthenticateAPIKey(ctx, noAuthKey.Key, true)
authenticatedAPIKey, err := authService.AuthenticateAPIKey(ctx, noAuthKey.Key, true)


// Test invalid API key
_, err = authService.AnthenticateAPIKey(ctx, "invalid-api-key")
_, err = authService.AnthenticateAPIKey(ctx, "invalid-api-key", false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
_, err = authService.AnthenticateAPIKey(ctx, "invalid-api-key", false)
_, err = authService.AuthenticateAPIKey(ctx, "invalid-api-key", false)

authService.APIKeyService.APIKeyCache.Invalidate(buildAPIKeyCacheKey(apiKeyString))

_, err = authService.AnthenticateAPIKey(ctx, apiKeyString)
_, err = authService.AnthenticateAPIKey(ctx, apiKeyString, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
_, err = authService.AnthenticateAPIKey(ctx, apiKeyString, false)
_, err = authService.AuthenticateAPIKey(ctx, apiKeyString, false)


// Second call - cache should be expired, should hit database again
authenticatedAPIKey2, err := authService.AnthenticateAPIKey(ctx, apiKeyString)
authenticatedAPIKey2, err := authService.AnthenticateAPIKey(ctx, apiKeyString, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
authenticatedAPIKey2, err := authService.AnthenticateAPIKey(ctx, apiKeyString, false)
authenticatedAPIKey2, err := authService.AuthenticateAPIKey(ctx, apiKeyString, false)


// Test successful API key authentication
authenticatedAPIKey, err := authService.AnthenticateAPIKey(ctx, apiKeyString)
authenticatedAPIKey, err := authService.AnthenticateAPIKey(ctx, apiKeyString, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
authenticatedAPIKey, err := authService.AnthenticateAPIKey(ctx, apiKeyString, false)
authenticatedAPIKey, err := authService.AuthenticateAPIKey(ctx, apiKeyString, false)

key = biz.NoAuthAPIKeyValue
}

apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, allowNoAuth)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, allowNoAuth)
apiKey, err := auth.AuthenticateAPIKey(c.Request.Context(), key, allowNoAuth)

}

apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key)
apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, false)
apiKey, err := auth.AuthenticateAPIKey(c.Request.Context(), key, false)

}

apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key)
apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, false)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function name AnthenticateAPIKey appears to have a typo and should be AuthenticateAPIKey. This should be corrected for clarity and consistency.

Suggested change
apiKey, err := auth.AnthenticateAPIKey(c.Request.Context(), key, false)
apiKey, err := auth.AuthenticateAPIKey(c.Request.Context(), key, false)

@looplj
Copy link
Copy Markdown
Owner Author

looplj commented Mar 20, 2026

@gemini-code-assist review

Copy link
Copy Markdown
Contributor

@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 introduces a new 'noauth' API key type, enabling API access without explicit authentication when configured. The changes involve updating API key type enums across frontend, backend, and GraphQL schemas, adding a configuration option server.api.auth.allow_no_auth, and modifying the API key service and authentication middleware to handle this new type. A lifecycle hook ensures the 'noauth' key is present if the feature is enabled. Overall, the implementation is robust and includes necessary checks to prevent unauthorized manipulation of the 'noauth' key. The addition of new test cases for the authentication middleware is also a positive step.

Comment on lines +57 to +89
func TestWithAPIKeyConfig_AllowsMissingAuthorizationWhenNoAuthAllowed(t *testing.T) {
gin.SetMode(gin.TestMode)

router := gin.New()
router.Use(func(c *gin.Context) {
key, err := ExtractAPIKeyFromRequest(c.Request, &APIKeyConfig{
Headers: []string{"Authorization"},
RequireBearer: true,
})
if errors.Is(err, ErrAPIKeyRequired) {
c.Status(http.StatusNoContent)
c.Abort()

return
}

if err != nil || key != "" {
c.Status(http.StatusTeapot)
c.Abort()

return
}
})

req := httptest.NewRequest(http.MethodGet, "/test", nil)

recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, req)

if recorder.Code != http.StatusNoContent {
t.Fatalf("expected status %d, got %d", http.StatusNoContent, recorder.Code)
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The test TestWithAPIKeyConfig_AllowsMissingAuthorizationWhenNoAuthAllowed directly tests ExtractAPIKeyFromRequest within a custom middleware, rather than testing the WithAPIKeyConfig middleware's behavior for this scenario. The WithAPIKeyConfig middleware has specific logic (if errors.Is(err, ErrAPIKeyRequired) && allowNoAuth) that should be tested directly to ensure it correctly sets key = biz.NoAuthAPIKeyValue and proceeds with authentication when allowNoAuth is true and no API key is provided. The current test bypasses this specific middleware logic.

func TestWithAPIKeyConfig_AllowsMissingAuthorizationWhenNoAuthAllowed(t *testing.T) {
	gin.SetMode(gin.TestMode)

	authService := &biz.AuthService{} // Mock or setup a real AuthService if needed

	router := gin.New()
	router.Use(WithAPIKeyConfig(authService, true, &APIKeyConfig{
		Headers:       []string{"Authorization"},
		RequireBearer: true,
	}))
	router.GET("/test", func(c *gin.Context) {
		// If the middleware correctly processed the missing key as noauth, this handler should be reached.
		c.Status(http.StatusOK)
	})

	req := httptest.NewRequest(http.MethodGet, "/test", nil)

	recorder := httptest.NewRecorder()
	router.ServeHTTP(recorder, req)

	if recorder.Code != http.StatusOK {
		t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
	}
}

@looplj looplj merged commit 3ca8cae into release/v0.9.x Mar 20, 2026
2 checks passed
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