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 the Authorization header:
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-only or read-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.
Describe the bug
When Apache Answer is configured in private mode (
LoginRequired=true), API requests authenticated with a valid API Key are rejected with401 Unauthorized. The middlewareEjectUserBySiteInfo()currently only checks for user session cookies and does not verify API Keys, which prevents programmatic access to private instances.To Reproduce
LoginRequired=true(private mode)/answer/api/v1/question/page) with the API Key in theAuthorizationheader:{"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 viaGetUserInfoFromContext(ctx). It does not check for API Keys before rejecting the request.Impact
This limitation currently prevents some valuable use cases for private Answer instances:
Supporting API Keys in private mode would enable these scenarios while maintaining the security benefits of restricted access.
Environment
LoginRequired=true(private mode)read-onlyorread-writeWorkaround
Currently, the only workaround is to disable private mode (
LoginRequired=false), which is not ideal for instances that need to restrict public access.