theonedev/onedev · error · UnauthorizedException
Authentication required
Error message
Authentication required
What it means
When the same lookup fails (project not found or inaccessible) but SecurityUtils.getUser() is null — i.e. the request carries no authentication at all — GitFilter throws UnauthorizedException("Authentication required") instead of entity-not-found. This steers anonymous clients toward authenticating rather than leaking project existence.
Source
Thrown at server-core/src/main/java/io/onedev/server/git/GitFilter.java:111
private Long getProjectId(String projectPath, boolean clusterAccess, boolean upload) {
var facade = projectService.findFacadeByPath(projectPath);
if (facade == null && projectPath.endsWith(".git")) {
projectPath = StringUtils.substringBeforeLast(projectPath, ".");
facade = projectService.findFacadeByPath(projectPath);
}
if (StringUtils.isBlank(projectPath))
throw new ExplicitException("Project not specified");
if (facade == null)
reportProjectNotFoundOrInaccessible(projectPath);
return facade.getId();
}
private void reportProjectNotFoundOrInaccessible(String projectPath) {
if (SecurityUtils.getUser() != null)
throw new EntityNotFoundException("Project not found or inaccessible: " + projectPath);
else
throw new UnauthorizedException("Authentication required");
}
private void doNotCache(HttpServletResponse response) {
response.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate");
}
protected void processPack(final HttpServletRequest request, final HttpServletResponse response)
throws IOException, InterruptedException, ExecutionException {
boolean upload = GitSmartHttpTools.isUploadPack(request);
String pathInfo = getPathInfo(request);
String service = StringUtils.substringAfterLast(pathInfo, "/");
String projectInfo = StringUtils.substringBeforeLast(pathInfo, "/");
String principal = (String) SecurityUtils.getSubject().getPrincipal();
boolean clusterAccess = SecurityUtils.isSystem(principal);View on GitHub (pinned to d44925c47c)
Solutions
- Authenticate: embed a valid access token or use a credential helper (git config credential.helper) before cloning
- Regenerate an expired/revoked access token and update the remote
- If the project is meant to be public, grant anonymous read access in project settings
- Run git fetch manually to trigger the credential prompt and store credentials
Example fix
// before git clone https://onedev.example.com/privateproject.git // after git clone https://oauth2:<access-token>@onedev.example.com/privateproject.git
Defensive patterns
Strategy: validation
Validate before calling
if (!accessToken || isExpired(accessToken)) {
throw new Error('Provide a valid OneDev access token before git operations');
} Try / catch
try {
git.clone(url);
} catch (UnauthorizedException e) {
if (e.getMessage().equals("Authentication required")) {
promptForCredentialsAndRetry();
}
} Prevention
- Configure a credential helper or embed a valid access token in CI
- Rotate access tokens before expiry
- Test anonymous access expectations: private projects always require credentials
When it happens
Trigger: Any git smart-HTTP request (refs/pack) from an unauthenticated session whose project path does not resolve; typical when credentials are absent, the access token expired, or the credential helper stopped supplying credentials.
Common situations: Clone/fetch from CI without configured credentials; expired or revoked access token in the remote URL; credential helper not initialized; anonymous access disabled on the server while the project is not public.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Project not specified
- Project not found or inaccessible: <projectPath>
- Unauthorized
- Unauthenticated
- Not authenticated
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/88f94f4fb85dd55c.
Report an issue: GitHub.