theonedev/onedev · error · UnauthorizedException

Not authorized

Error message

Not authorized

What it means

OneDev's REST API throws UnauthorizedException (HTTP 403, message 'Not authorized') when the authenticated caller lacks the required permission. getAuthorization loads a UserAuthorization by id and requires the caller to be able to manage the project the authorization belongs to. Even a valid, authenticated request is rejected if the project is outside the caller's management scope.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/UserAuthorizationResource.java:47

public class UserAuthorizationResource {

	private final UserAuthorizationService authorizationService;

	private final AuditService auditService;

	@Inject
	public UserAuthorizationResource(UserAuthorizationService authorizationService, AuditService auditService) {
		this.authorizationService = authorizationService;
		this.auditService = auditService;
	}

	@Api(order=100, description = "Get user authorization of specified id")
	@Path("/{authorizationId}")
	@GET
	public UserAuthorization getAuthorization(@PathParam("authorizationId") Long authorizationId) {
		UserAuthorization authorization = authorizationService.load(authorizationId);
		if (!SecurityUtils.canManageProject(authorization.getProject()))
			throw new UnauthorizedException();
		return authorization;
	}
	
	@Api(order=200, description="Create user authorization")
	@POST
	public Long createAuthorization(@NotNull UserAuthorization authorization) {
		if (!SecurityUtils.canManageProject(authorization.getProject()))
			throw new UnauthorizedException();
		authorizationService.createOrUpdate(authorization);
		var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
		auditService.audit(null, "created user authorization via RESTful API", null, newAuditContent);
		return authorization.getId();
	}

	@Api(order=300, description = "Delete user authorization of specified id")
	@Path("/{authorizationId}")
	@DELETE
	public Response deleteAuthorization(@PathParam("authorizationId") Long authorizationId) {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Use an access token belonging to a user who can manage the target project (project owner/maintainer) or an administrator.
  2. Verify the authorizationId actually refers to an authorization of the project you manage (load the entity and check its project).
  3. Grant the token's owner Project management permission (Project > Access/Settings > add user with Manage privilege).
  4. Check the request is authenticating at all — an anonymous or wrongly-scoped token yields the same 403.

Example fix

// before (token of a member without manage rights)
curl -H "Authorization: Bearer <member-token>" https://onedev/~api/users/authorizations/42
// after (token of project owner/admin)
curl -H "Authorization: Bearer <owner-token>" https://onedev/~api/users/authorizations/42
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check with a per-project endpoint the caller can access:
// GET /~api/projects/{projectPath} must succeed for the project of authorizationId
const projectAccessible = await fetch(`${baseUrl}/~api/projects/${projectPath}`, { headers }).then(r => r.ok);
if (!projectAccessible) throw new Error('caller cannot manage project; 403 expected');

Try / catch

try {
  const auth = await get(`/users/authorizations/${id}`);
} catch (e) {
  if (e.response?.status === 403) {
    // caller lacks manage rights on the authorization's project
    // fall back to admin credentials or skip
  } else throw e;
}

Prevention

When it happens

Trigger: GET /~api/users/authorizations/{authorizationId} (within UserAuthorizationResource) where SecurityUtils.canManageProject(authorization.getProject()) returns false — i.e. the authenticated user/token is not an administrator or a project manager of the project referenced by the authorization entity.

Common situations: Calling with an access token whose owner is a regular project member, not a project maintainer/owner; the authorization id exists but belongs to a different project than the caller manages; scripts configured with a personal access token of a non-admin user; recent permission changes removed the caller's manage rights.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/fdf520d0dbe6f47f. Report an issue: GitHub.