{"record":{"id":"c658662b2ca964b7","repo":"theonedev/onedev","slug":"not-authorized-c65866","errorCode":null,"errorMessage":"Not authorized","messagePattern":"Not authorized","errorType":"http","errorClass":"UnauthorizedException","httpStatus":403,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/AccessTokenResource.java","lineNumber":55,"sourceCode":"public class AccessTokenResource {\n\t\n\tprivate final AccessTokenService accessTokenService;\n\n\tprivate final AuditService auditService;\n\t\n\t@Inject\n\tpublic AccessTokenResource(AccessTokenService accessTokenService, AuditService auditService) {\n\t\tthis.accessTokenService = accessTokenService;\n\t\tthis.auditService = auditService;\n\t}\n\n\t@Api(order=100)\n\t@Path(\"/{accessTokenId}\")\n\t@GET\n\tpublic AccessToken getToken(@PathParam(\"accessTokenId\") Long accessTokenId) {\n\t\tvar accessToken = accessTokenService.load(accessTokenId);\n    \tif (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser())) \n\t\t\tthrow new UnauthorizedException();\n    \treturn accessToken;\n\t}\n\n\t@Api(order=150)\n\t@Path(\"/{accessTokenId}/authorizations\")\n\t@GET\n\tpublic Collection<AccessTokenAuthorization> getAuthorizations(@PathParam(\"accessTokenId\") Long accessTokenId) {\n\t\tvar accessToken = accessTokenService.load(accessTokenId);\n\t\tif (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))\n\t\t\tthrow new UnauthorizedException();\n\t\treturn accessToken.getAuthorizations();\n\t}\n\t\n\t@Api(order=200, description=\"Create access token\")\n\t@POST\n\tpublic Long createToken(@NotNull @Valid AccessToken accessToken) {\n\t\tvar owner = accessToken.getOwner();\n\t\tif (!isAdministrator() && !owner.equals(getAuthUser()))","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/AccessTokenResource.java#L37-L73","documentation":"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.","triggerScenarios":"GET /~access-tokens/{accessTokenId} (AccessTokenResource.getToken) where accessToken.getOwner() != getAuthUser() and the caller is not an administrator.","commonSituations":"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.","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."],"exampleFix":"// before\nGET /~access-tokens/12  // token #12 belongs to 'alice', caller is 'bob'\n// after\nGET /~access-tokens/15  // token #15 belongs to 'bob' (the authenticated user)","handlingStrategy":"validation","validationCode":"const myTokens = await listMyAccessTokens();\nif (!myTokens.some(t => t.id === tokenId)) {\n  throw new Error(`Token ${tokenId} is not owned by the authenticated user`);\n}","typeGuard":"function ownsToken(myTokenIds: number[], tokenId: number): boolean {\n  return myTokenIds.includes(tokenId);\n}","tryCatchPattern":"try {\n  const token = await getToken(tokenId);\n} catch (e) {\n  if (e.response?.status === 401) {\n    // wrong owner: list own tokens and use a valid id\n  } else throw e;\n}","preventionTips":["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"],"tags":["rest","authorization","access-token"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}