{"record":{"id":"b7fa7caa8c449366","repo":"goharbor/harbor","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"src/core/api/base.go","lineNumber":70,"sourceCode":"\n// Prepare inits security context and project manager from request\n// context\nfunc (b *BaseController) Prepare() {\n\tctx, ok := security.FromContext(b.Context())\n\tif !ok {\n\t\tlog.Errorf(\"failed to get security context\")\n\t\tb.SendInternalServerError(errors.New(\"\"))\n\t\treturn\n\t}\n\tb.SecurityCtx = ctx\n\tb.ProjectCtl = projectcontroller.Ctl\n}\n\n// RequireAuthenticated returns true when the request is authenticated\n// otherwise send Unauthorized response and returns false\nfunc (b *BaseController) RequireAuthenticated() bool {\n\tif !b.SecurityCtx.IsAuthenticated() {\n\t\tb.SendError(errors.UnauthorizedError(errors.New(\"Unauthorized\")))\n\t\treturn false\n\t}\n\treturn true\n}\n\n// HasProjectPermission returns true when the request has action permission on project subresource\nfunc (b *BaseController) HasProjectPermission(projectIDOrName any, action rbac.Action, subresource ...rbac.Resource) (bool, error) {\n\t_, _, err := utils.ParseProjectIDOrName(projectIDOrName)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tproject, err := b.ProjectCtl.Get(b.Context(), projectIDOrName)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tresource := rbac_project.NewNamespace(project.ProjectID).Resource(subresource...)","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/core/api/base.go#L52-L88","documentation":"BaseController.RequireAuthenticated (src/core/api/base.go:70) returns false and sends HTTP 401 Unauthorized when the request's security context reports an unauthenticated caller. It is the standard gate for core API endpoints; the companion Prepare must already have succeeded (a security context exists, but the caller is anonymous).","triggerScenarios":"Calling any authenticated Harbor API without credentials; using an expired/revoked OIDC or robot token; a robot account whose disabling makes IsAuthenticated() false; bearer token from a different issuer.","commonSituations":"Expired robot account tokens in CI after the configured TTL; OIDC token refresh missed by a client; curl without -u/-H Authorization against an authenticated endpoint; scripts run after a user was deactivated.","solutions":["Send valid credentials: basic auth for robots/users, or Authorization: Bearer <token> obtained from the token service","Refresh or recreate the robot account token (check its expires_at) and update the secret in CI","Verify the user/robot is active and not locked, and that the auth mode (db_auth/oidc/ldap) matches how the credential was issued"],"exampleFix":"# before\ncurl https://harbor.example.com/api/v2.0/projects   # 401 Unauthorized\n\n# after\ncurl -u 'robot$ci+drone:<secret>' https://harbor.example.com/api/v2.0/projects\n# or\ncurl -H 'Authorization: Bearer <jwt>' https://harbor.example.com/api/v2.0/projects","handlingStrategy":"validation","validationCode":"req.SetBasicAuth(robotName, robotSecret) // or\nreq.Header.Set(\"Authorization\", \"Bearer \"+getToken())\n// validate robot token expiry before use:\nif robotToken.ExpiresAt != nil && robotToken.ExpiresAt.Before(time.Now()) {\n    return errors.New(\"robot token expired; rotate it\")\n}","typeGuard":"func isUnauthorized(err error) bool {\n    return errors.IsErr(err, errors.UnauthorizedCode)\n}","tryCatchPattern":"resp, err := client.Do(req)\nif err == nil && resp.StatusCode == http.StatusUnauthorized {\n    // refresh token / rotate robot secret, then retry once with new credentials\n}","preventionTips":["Send credentials on every authenticated endpoint call (basic auth or bearer token)","Track robot token expires_at and rotate before expiry; alert ahead of time","Verify the account is active and the auth mode matches how credentials were issued","On 401, refresh credentials once and retry - repeated identical retries will keep failing"],"tags":["harbor","auth","unauthorized","api","credentials"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}