-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Describe the bug
When Apache Answer is configured in private mode (LoginRequired=true), API requests authenticated with a valid API Key are rejected with 401 Unauthorized. The middleware EjectUserBySiteInfo() currently only checks for user session cookies and does not verify API Keys, which prevents programmatic access to private instances.
To Reproduce
- Configure Apache Answer with
LoginRequired=true(private mode) - Create a valid API Key via Admin Panel → API Keys
- Make an API request to a public endpoint (e.g.,
/answer/api/v1/question/page) with the API Key in theAuthorizationheader:curl -H "Authorization: sk_xxxxxxxxxxxxx" \ "http://localhost:9080/answer/api/v1/question/page?page=1&page_size=10"
- Observe the response:
{"code":401,"reason":"base.unauthorized_error","msg":"Unauthorized.","data":null}
Expected behavior
API requests with a valid API Key should be allowed to access public endpoints, even when the site is in private mode. API Keys are specifically designed for programmatic access and should bypass the user session requirement.
Actual Behavior
All API requests without a user session cookie are rejected with 401 Unauthorized, regardless of whether a valid API Key is provided.
Root Cause
File: internal/base/middleware/auth.go (lines 79-108)
The EjectUserBySiteInfo() middleware checks if the site is in private mode and then verifies only user sessions via GetUserInfoFromContext(ctx). It does not check for API Keys before rejecting the request.
func (am *AuthUserMiddleware) EjectUserBySiteInfo() gin.HandlerFunc {
return func(ctx *gin.Context) {
mustLogin := false
siteInfo, _ := am.siteInfoCommonService.GetSiteSecurity(ctx)
if siteInfo != nil {
mustLogin = siteInfo.LoginRequired
}
if !mustLogin {
ctx.Next()
return
}
// If site in private mode, user must login.
userInfo := GetUserInfoFromContext(ctx) // ❌ Only checks user session
if userInfo == nil {
handler.HandleResponse(ctx, errors.Unauthorized(reason.UnauthorizedError), nil)
ctx.Abort()
return
}
// ...
}
}Impact
This limitation currently prevents some valuable use cases for private Answer instances:
- Automated data synchronization with external systems
- Integration with third-party tools and services
- Headless/API-only clients for programmatic access
- CI/CD pipelines and automated testing
Supporting API Keys in private mode would enable these scenarios while maintaining the security benefits of restricted access.
Environment
- Apache Answer version: [latest from main branch]
- Configuration:
LoginRequired=true(private mode) - API Key scope:
read-onlyorread-write
Workaround
Currently, the only workaround is to disable private mode (LoginRequired=false), which is not ideal for instances that need to restrict public access.