gotify/server · error
basic auth required
Error message
basic auth required
What it means
This error is returned by the Login endpoint (SessionAPI.Login) when the HTTP request carries no Basic Authentication credentials at all. gin's ctx.Request.BasicAuth() fails to parse an Authorization header of type 'Basic', so the handler aborts with 401 before ever looking up the user. It is an authentication-transport problem, not a wrong-password problem.
Source
Thrown at api/session.go:69
// type: string
// description: session cookie
// 401:
// description: Unauthorized
// schema:
// $ref: "#/definitions/Error"
// 403:
// description: Forbidden
// schema:
// $ref: "#/definitions/Error"
func (a *SessionAPI) Login(ctx *gin.Context) {
if !a.LocalAuthEnabled {
ctx.AbortWithError(403, errors.New("local authentication is disabled"))
return
}
name, pass, ok := ctx.Request.BasicAuth()
if !ok {
ctx.AbortWithError(401, errors.New("basic auth required"))
return
}
user, err := a.DB.GetUserByName(name)
if err != nil {
ctx.AbortWithError(500, err)
return
}
if user == nil || !password.ComparePassword(user.Pass, []byte(pass)) {
ctx.AbortWithError(401, errors.New("invalid credentials"))
return
}
clientParams := ClientParams{}
if err := ctx.Bind(&clientParams); err != nil {
return
}
View on GitHub (pinned to 14bfc25627)
Solutions
- Send a proper Basic auth header: curl -u name:pass ... or Authorization: Basic <base64(name:pass)>
- Verify the header survives to the backend (no proxy stripping it); check with curl -v
- base64-encode username:password correctly (username may contain a colon; encode as 'user:pass')
- If token auth is intended, use the endpoint/route that accepts client tokens instead of the local-login basic-auth route
Example fix
// before
fetch('/api/session', { method: 'POST' })
// after
fetch('/api/session', { method: 'POST', headers: { 'Authorization': 'Basic ' + btoa(username + ':' + password) } }) Defensive patterns
Strategy: validation
Validate before calling
function hasBasicAuth(headers) {
const h = headers['Authorization'] || headers['authorization'] || '';
return /^Basic\s+[A-Za-z0-9+/=]+$/.test(h);
}
if (!hasBasicAuth(myHeaders)) throw new Error('attach Authorization: Basic base64(user:pass) before calling login'); Type guard
function isBasicAuthHeader(v) {
return typeof v === 'string' && /^Basic\s+[A-Za-z0-9+/=]+$/.test(v);
} Prevention
- Always build the Authorization header with a battle-tested helper (btoa/axios auth config), never by hand
- Use curl -v once to confirm the header reaches the server unstripped
- Document that the login endpoint only accepts Basic auth, not Bearer tokens
- Check proxies (nginx/ingress) for auth modules that consume the Authorization header
When it happens
Trigger: POST to the login/session endpoint without an Authorization header; using a Bearer token, cookie, or custom header instead of 'Authorization: Basic base64(user:pass)'; a client/proxy stripping the Authorization header; malformed base64 or a colon-less username so BasicAuth() returns ok=false.
Common situations: Clients using OAuth/bearer flows against an API that only accepts basic auth; curl users forgetting -u user:pass; reverse proxies (nginx) configured with their own basic-auth layer consuming the header; frontend fetch calls setting headers: {'Content-Type': 'json'} but never the Authorization header; API changes where token-based login replaced basic auth.
Related errors
- local authentication is disabled
- invalid credentials
- token exchange failed: %w
- cannot delete internal application
- file with key 'file' must be present
AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05).
Data as JSON: /api/errors/50d100d6ad3d4ca6.
Report an issue: GitHub.