theonedev/onedev · error · UnauthorizedException

Not authorized

Error message

Not authorized

What it means

createWorkspace throws UnauthorizedException when there is no authenticated user on the request subject. Workspace creation requires a real user identity; anonymous or token-less requests cannot create workspaces. This is the first of two authorization checks in the endpoint.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/WorkspaceResource.java:104

			@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~workspaces'>workspaces page</a>", example="active") String query,
			@QueryParam("offset") @Api(example="0") int offset,
			@QueryParam("count") @Api(example="100") int count) {
		var subject = SecurityUtils.getSubject();
		if (!SecurityUtils.isAdministrator(subject) && count > RestConstants.MAX_PAGE_SIZE)
			throw new NotAcceptableException("Count should not be greater than " + RestConstants.MAX_PAGE_SIZE);

		var parsedQuery = WorkspaceQuery.parse(null, query, true);

		return workspaceService.query(subject, null, parsedQuery, offset, count);
	}

	@Api(order=300, description="Create new workspace")
	@POST
	public Long createWorkspace(@NotNull @Valid WorkspaceCreateData data) {
		var subject = SecurityUtils.getSubject();
		var user = SecurityUtils.getUser(subject);
		if (user == null)
			throw new UnauthorizedException();

		Project project = projectService.load(data.getProjectId());
		if (!SecurityUtils.canCreateWorkspaces(subject, project))
			throw new UnauthorizedException();

		if (project.getHierarchyWorkspaceSpecs().stream()
				.noneMatch(it -> it.getName().equals(data.getSpecName()))) {
			throw new NotAcceptableException("Workspace spec not found: " + data.getSpecName());
		}

		ObjectId commitId = ObjectId.fromString(data.getCommitHash());
		var commit = project.getRevCommit(commitId, false);
		if (commit == null) 
			throw new NotAcceptableException("Commit not found: " + data.getCommitHash());

		Issue issue = null;
		if (data.getIssueId() != null) {
			issue = issueService.get(data.getIssueId());

View on GitHub (pinned to d44925c47c)

Solutions

  1. Send a valid Authorization header with a personal access token of a real user
  2. Verify the token works via GET /users/me before calling the endpoint
  3. Re-generate the access token if it was revoked or expired

Example fix

// before
post("/workspaces", data); // no auth
// after
post("/workspaces", data, auth: bearerToken(userAccessToken));
Defensive patterns

Strategy: validation

Validate before calling

User me = tryGetAuthenticatedUser(); if (me == null) throw new IllegalStateException("no valid credentials");

Type guard

boolean hasUserIdentity(Subject s) { return SecurityUtils.getUser(s) != null; }

Try / catch

try { createWorkspace(data); } catch (UnauthorizedException e) { throw new ConfigurationException("invalid or missing access token"); }

Prevention

When it happens

Trigger: POSTing to /workspaces without credentials, or with a token/job credential that does not resolve to a User (SecurityUtils.getUser(subject) returns null).

Common situations: Calling the API with a malformed or revoked access token; missing Authorization header in a script; using a machine credential that authenticates but carries no user identity.

Related errors


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