theonedev/onedev · error · UnauthorizedException
Not authorized
Error message
Not authorized
What it means
getToken throws UnauthorizedException when a non-admin caller requests an access token they do not own. GET /{accessTokenId} loads the token and compares accessToken.getOwner() with the authenticated user; any mismatch without admin rights is rejected, preventing users from reading other users' token metadata.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/AccessTokenResource.java:55
public class AccessTokenResource {
private final AccessTokenService accessTokenService;
private final AuditService auditService;
@Inject
public AccessTokenResource(AccessTokenService accessTokenService, AuditService auditService) {
this.accessTokenService = accessTokenService;
this.auditService = auditService;
}
@Api(order=100)
@Path("/{accessTokenId}")
@GET
public AccessToken getToken(@PathParam("accessTokenId") Long accessTokenId) {
var accessToken = accessTokenService.load(accessTokenId);
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
throw new UnauthorizedException();
return accessToken;
}
@Api(order=150)
@Path("/{accessTokenId}/authorizations")
@GET
public Collection<AccessTokenAuthorization> getAuthorizations(@PathParam("accessTokenId") Long accessTokenId) {
var accessToken = accessTokenService.load(accessTokenId);
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
throw new UnauthorizedException();
return accessToken.getAuthorizations();
}
@Api(order=200, description="Create access token")
@POST
public Long createToken(@NotNull @Valid AccessToken accessToken) {
var owner = accessToken.getOwner();
if (!isAdministrator() && !owner.equals(getAuthUser()))View on GitHub (pinned to d44925c47c)
Solutions
- Call the API as the token's owner or as an administrator.
- List your own tokens first (GET /~access-tokens) and use an id you own.
- Confirm which user the Authorization credential belongs to.
- If admin access is intended, authenticate with an admin account.
Example fix
// before GET /~access-tokens/12 // token #12 belongs to 'alice', caller is 'bob' // after GET /~access-tokens/15 // token #15 belongs to 'bob' (the authenticated user)
Defensive patterns
Strategy: validation
Validate before calling
const myTokens = await listMyAccessTokens();
if (!myTokens.some(t => t.id === tokenId)) {
throw new Error(`Token ${tokenId} is not owned by the authenticated user`);
} Type guard
function ownsToken(myTokenIds: number[], tokenId: number): boolean {
return myTokenIds.includes(tokenId);
} Try / catch
try {
const token = await getToken(tokenId);
} catch (e) {
if (e.response?.status === 401) {
// wrong owner: list own tokens and use a valid id
} else throw e;
} Prevention
- Never hardcode token ids from examples or other users
- Discover token ids via the list endpoint scoped to your account
- Log which user your REST credential maps to
When it happens
Trigger: GET /~access-tokens/{accessTokenId} (AccessTokenResource.getToken) where accessToken.getOwner() != getAuthUser() and the caller is not an administrator.
Common situations: Using a hardcoded token id from documentation or a colleague's example while authenticated as yourself; a CI bot enumerating other users' token ids; stale ids copied from a different OneDev instance.
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
- Not authorized
- Access token owner should have permission to manage authoriz
- No permission to access issue: ${referenceString}
- No permission to write code in issue project
- Code write permission is required to edit auto merge
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/c658662b2ca964b7.
Report an issue: GitHub.