{"record":{"id":"7506195d9d9f56db","repo":"immich-app/immich","slug":"denied-access-to-admin-only-route-uri","errorCode":null,"errorMessage":"Denied access to admin only route: ${uri}","messagePattern":"Denied access to admin only route: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/services/auth.service.ts","lineNumber":221,"sourceCode":"  async adminSignUp(dto: SignUpDto): Promise<UserAdminResponseDto> {\n    const admin = await this.createUser({\n      isAdmin: true,\n      email: dto.email,\n      name: dto.name,\n      password: dto.password,\n      storageLabel: 'admin',\n    });\n\n    return mapUserAdmin(admin);\n  }\n\n  async authenticate({ headers, queryParams, metadata }: ValidateRequest): Promise<AuthDto> {\n    const authDto = await this.validate({ headers, queryParams });\n    const { adminRoute, sharedLinkRoute, uri } = metadata;\n    const requestedPermission = metadata.permission ?? Permission.All;\n\n    if (!authDto.user.isAdmin && adminRoute) {\n      this.logger.warn(`Denied access to admin only route: ${uri}`);\n      throw new ForbiddenException('Forbidden');\n    }\n\n    if (authDto.sharedLink && !sharedLinkRoute) {\n      this.logger.warn(`Denied access to non-shared route: ${uri}`);\n      throw new ForbiddenException('Forbidden');\n    }\n\n    if (\n      authDto.apiKey &&\n      requestedPermission !== false &&\n      !isGranted({ requested: [requestedPermission], current: authDto.apiKey.permissions })\n    ) {\n      throw new ForbiddenException(`Missing required permission: ${requestedPermission}`);\n    }\n\n    return authDto;\n  }","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/auth.service.ts#L203-L239","documentation":"During request authentication (validate + authorize), if the resolved user is not an admin but the route is flagged adminRoute, access is denied: this warning is logged with the URI and a ForbiddenException('Forbidden') is thrown. This is the server enforcing role-based access on admin-only endpoints.","triggerScenarios":"Any API call to a route whose metadata marks adminRoute=true while the authenticated user's isAdmin is false.","commonSituations":"A non-admin user hitting admin endpoints (user management, server settings, jobs) directly via API; custom scripts/integrations using an admin-only endpoint with a normal user's API key.","solutions":["Use an administrator account or an admin's API key for admin-only endpoints.","If the user should be admin, promote them in the admin Users page.","For automations, find a non-admin endpoint or scope the integration appropriately.","Confirm the request isn't accidentally routed to an admin endpoint due to a wrong URL."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// client-side guard before calling an admin API\nconst user = await api.getMyUser();\nif (!user.isAdmin) throw new Error('Admin privileges required for this endpoint');","typeGuard":"const isAdminUser = (u: { isAdmin: boolean }): u is { isAdmin: true } => u.isAdmin === true;","tryCatchPattern":"try {\n  await api.adminEndpoint();\n} catch (e) {\n  if (e instanceof ForbiddenException) {\n    showToast('This action requires an administrator account');\n  } else throw e;\n}","preventionTips":["Only call admin-flagged endpoints with an admin account or admin API key.","Check /api/users/me isAdmin before attempting admin operations in scripts.","Promote users via the admin Users page when they genuinely need access.","Never reuse a normal user's key for admin automation."],"tags":["authorization","security","rbac"],"backgroundTag":"permission-denied","analyzedSha":"f48d4b332127ad365ba256108799ca8f571d2dd5","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}