How to Troubleshoot Gitea Authentication Issues: A Complete Technical Guide
To troubleshoot Gitea authentication issues, enable trace logging to capture the authPathDetector evaluation, verify credential flows through the pluggable auth methods in services/auth/auth.go, and inspect token parsing logic in oauth2.go to isolate failures in path detection, validation, or session persistence.
Gitea’s authentication system relies on a pluggable "auth method" framework that processes requests through a structured detection and validation pipeline. When users report login failures or API access denials, understanding the internal flow—from path detection in services/auth/auth.go to token parsing in oauth2.go—is essential for rapid diagnosis. This guide provides a source-code-backed approach to identify and resolve authentication failures in the go-gitea/gitea repository.
Understanding Gitea's Authentication Architecture
Path Detection and Protected Routes
In services/auth/auth.go, the newAuthPathDetector function examines incoming HTTP requests to determine if authentication is required. The detector returns true for protected paths including API endpoints, Git raw content, archives, attachments, and feeds (lines 63-80). If the detector misidentifies a path as public, the request bypasses authentication entirely.
Auth Method Selection and Verification
Once a path is flagged for protection, Gitea iterates through registered auth.Method implementations until one returns a valid user. These methods include password-based, LDAP, SMTP, OAuth2, WebAuthn, and token-based API authentication. Each method implements its own credential validation logic in the services/auth/source/ directory.
Session Management and Regeneration
Successful authentication triggers handleSignIn (lines 23-64 in auth.go), which regenerates the session ID to prevent fixation attacks. This function stores the user ID, username, and language preferences, while clearing stale WebAuthn assertion data. Failures here typically manifest as "Error regenerating session" messages in the logs.
Common Authentication Failure Points
-
Invalid credentials (password, LDAP, SMTP): Occurs when passwords mismatch, accounts are disabled, or external sources fail to connect. Check
services/auth/source/ldap/source_authenticate.goand corresponding SMTP authentication handlers to verify bind DN settings and TLS configurations. -
API token rejected: Results from missing tokens, expired grants, or
DISABLE_QUERY_AUTH_TOKENbeing set totruewhile clients still transmit tokens via query strings. Inspect theparseTokenfunction inservices/auth/oauth2.go(lines 84-98) to confirm token extraction logic. -
OAuth2 login failures: Stems from provider misconfiguration (client ID/secret mismatches), invalid redirect URLs, or JWT signature verification failures. The
GetOAuthAccessTokenScopeAndUserIDfunction (lines 40-55 inoauth2.go) validates token signatures and expiration claims. -
WebAuthn/2FA failures: Caused by missing assertions, incorrect FIDO2 device registration, or lost session cookies. Note that
handleSignInexplicitly clearswebauthnAssertiondata during sign-in, requiring clients to maintain persistent session cookies. -
Git raw/attachment 401 errors: Happens when
authPathDetectorfails to recognize paths as authenticated resources. VerifyisGitRawOrAttachPathandisArchivePathmethods (lines 96-112 inauth.go) if protected assets return unexpected 401 status codes. -
Session regeneration errors: Indicate underlying storage failures in Redis, memory, or file-based session stores when
session.RegenerateSessioncannot create new session IDs. -
Feed authentication disabled: Occurs when
setting.Other.EnableFeedisfalsebut clients attempt to access RSS/Atom endpoints. CheckauthPathDetector.isFeedRequest(lines 82-90 inauth.go).
Step-by-Step Troubleshooting Checklist
-
Enable detailed logging: Set
APP_LOG_LEVEL=traceinapp.iniand restart Gitea. Monitor output frommodules/logforTrace,Warn, andErrorentries during authentication attempts. -
Verify auth source configuration: Review
[auth]sections inapp.ini(e.g.,[ldap],[smtp]). Confirm host, port, bind DN, TLS settings, and network connectivity between Gitea and external authentication servers. -
Validate OAuth2 settings: Inspect the
[oauth2]section forCLIENT_ID,CLIENT_SECRET, andJWT_SECRETmismatches. Ensure signing keys align with external provider configurations. -
Inspect token contents: Decode JWT tokens using standard JWT debuggers to verify
exp,iat, andgrant_idclaims without requiring the signing secret. -
Query the database directly:
- Check
access_tokentable for API tokens:SELECT * FROM access_token WHERE sha256 = ... - Verify OAuth grants in
oauth2_grant:SELECT * FROM oauth2_grant WHERE id = ... - Confirm user status in
usertable:is_active,login_type, andlogin_sourcecolumns
- Check
-
Verify session persistence: Ensure the
i_like_giteacookie (or the name specified insetting.CookieUsername) accompanies every request. Validate that the session store (memory, Redis, or file) has write permissions and adequate storage. -
Test request paths manually: Use
curl -vto examine endpoints, observing returned status codes andWWW-Authenticateheaders for detailed rejection reasons. -
Run integration tests: Execute
make test-integrationto exercise LDAP, OAuth2, and token authentication paths viatests/integration/auth_ldap_test.goandoauth_test.go.
Debugging with Code Examples
Manually Parsing Tokens from HTTP Requests
When debugging API authentication, you can replicate Gitea's internal token extraction logic:
// Re-use Gitea's internal helper – it respects DISABLE_QUERY_AUTH_TOKEN.
token, ok := parseToken(req)
if !ok {
// No token found – authentication will be skipped for this request.
}
Reference: parseToken in services/auth/oauth2.go (lines 84-100).
Forcing Session Regeneration After Password Changes
To manually regenerate sessions during custom authentication workflows:
// Regenerate the session (same logic as handleSignIn)
newSess, err := session.RegenerateSession(w, r)
if err != nil {
log.Error("Failed to regenerate session: %v", err)
}
sess = newSess
sess.Set("uid", user.ID)
sess.Set("uname", user.Name)
Reference: handleSignIn in services/auth/auth.go (lines 23-45).
Decoding OAuth2 JWT Access Tokens for Debugging
For troubleshooting OAuth2 token validation:
import "code.gitea.io/gitea/services/oauth2_provider"
func decodeAccessToken(tokenStr string) {
token, err := oauth2_provider.ParseToken(tokenStr, oauth2_provider.DefaultSigningKey)
if err != nil {
log.Error("Invalid JWT: %v", err)
return
}
log.Info("GrantID=%d, Owner=%d, Scope=%s", token.GrantID, token.OwnerID, token.Scope)
}
Reference: Token parsing in GetOAuthAccessTokenScopeAndUserID (lines 40-55 in oauth2.go).
Checking Whether a Request Requires Authentication
To verify if a specific endpoint triggers authentication checks:
detector := newAuthPathDetector(req)
if detector.isAPIPath() || detector.isGitRawOrAttachPath() ||
detector.isArchivePath() || detector.isAttachmentDownload() {
// Authentication required – invoke the appropriate auth method.
}
Reference: authPathDetector methods in services/auth/auth.go (lines 63-112).
Key Source Files for Authentication Debugging
Understanding these core files accelerates troubleshooting:
services/auth/auth.go: ContainsnewAuthPathDetector,handleSignIn, and the core authentication orchestration logic.services/auth/oauth2.go: ImplementsparseTokenandGetOAuthAccessTokenScopeAndUserIDfor OAuth2 and API token validation.services/auth/source/ldap/source_authenticate.go: Handles LDAP bind operations and directory authentication.services/auth/source/smtp/auth.go: Manages email-based authentication workflows.modules/auth/httpauth/httpauth.go: ProvidesAuthorizationheader parsing for Bearer and Basic schemes.modules/session/session.go: Abstracts session regeneration and storage mechanisms.models/auth/access_token.go: Database model for API token persistence and SHA256 hashing.models/auth/oauth2_grant.go: Stores OAuth2 grant relationships and token metadata.routers/web/auth/oauth.go: Web interface OAuth2 flow handlers for sign-in and callbacks.routers/web/auth/auth.go: Generic login page processing for password, LDAP, and SMTP methods.
Summary
- Gitea uses a pluggable auth framework with
authPathDetectordetermining which requests require authentication based on URL patterns inservices/auth/auth.go. - Token validation occurs in
oauth2.go, whereparseTokenextracts credentials from headers or query strings, respecting theDISABLE_QUERY_AUTH_TOKENsetting. - Session regeneration happens in
handleSignIn, which clears WebAuthn data and creates new session IDs to prevent fixation attacks. - LDAP and SMTP failures typically stem from connection issues or bind DN misconfigurations in
services/auth/source/directories. - Database verification of
access_token,oauth2_grant, andusertables often reveals account status or token expiration issues. - Trace logging via
APP_LOG_LEVEL=traceprovides visibility into the authentication decision chain.
Frequently Asked Questions
Why does my API token work in the header but not in the query string?
Gitea respects the DISABLE_QUERY_AUTH_TOKEN setting in app.ini. When enabled, the parseToken function in services/auth/oauth2.go (lines 84-98) ignores tokens passed as query parameters for security reasons. Use the Authorization: Bearer <token> header instead, which is always evaluated regardless of this setting.
How does Gitea decide which requests need authentication?
The newAuthPathDetector function in services/auth/auth.go (lines 63-80) evaluates URL paths against patterns for API endpoints, Git raw content, archives, attachments, and feeds. If a path matches protected patterns, Gitea iterates through registered auth methods until one validates the request, otherwise returning 401 or 403 responses.
What causes "Error regenerating session" during login?
This error originates from handleSignIn in services/auth/auth.go when session.RegenerateSession fails. Common causes include full disk space (for file-based sessions), Redis connection failures, or permission issues on session storage directories. Verify that your configured session store (memory, file, or Redis) is accessible and writable by the Gitea process.
Why does OAuth2 authentication fail with valid credentials?
OAuth2 failures typically occur in GetOAuthAccessTokenScopeAndUserID (lines 40-55 in oauth2.go) due to JWT signature mismatches, expired tokens, or incorrect JWT_SECRET configurations in app.ini. Verify that the [oauth2] section's JWT_SECRET matches between Gitea and your OAuth2 provider, and decode the token to confirm the exp claim has not passed.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →