{"record":{"id":"044be41e0cfe17c6","repo":"immich-app/immich","slug":"password-login-has-been-disabled","errorCode":null,"errorMessage":"Password login has been disabled","messagePattern":"Password login has been disabled","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":63,"sourceCode":"\nexport type ValidateRequest = {\n  headers: IncomingHttpHeaders;\n  queryParams: Record<string, string>;\n  metadata: {\n    sharedLinkRoute: boolean;\n    adminRoute: boolean;\n    /** `false` explicitly means no permission is required, which otherwise defaults to `all` */\n    permission?: Permission | false;\n    uri: string;\n  };\n};\n\n@Injectable()\nexport class AuthService extends BaseService {\n  async login(dto: LoginCredentialDto, details: LoginDetails) {\n    const config = await this.getConfig({ withCache: false });\n    if (!config.passwordLogin.enabled) {\n      throw new UnauthorizedException('Password login has been disabled');\n    }\n\n    const user = await this.userRepository.getByEmail(dto.email, { withPassword: true });\n    // Always run bcrypt so response time is constant regardless of whether the email\n    // is registered, preventing timing-based user enumeration.\n    const isAuthenticated = this.cryptoRepository.compareBcrypt(dto.password, user?.password ?? LOGIN_DUMMY_HASH);\n\n    if (!user || !user.password || !isAuthenticated) {\n      this.logger.warn(`Failed login attempt for user ${dto.email} from ip address ${details.clientIp}`);\n      throw new UnauthorizedException('Incorrect email or password');\n    }\n\n    return this.createLoginResponse(user, details);\n  }\n\n  async logout(auth: AuthDto, authType: AuthType): Promise<LogoutResponseDto> {\n    let oauthBearerToken: string | undefined;\n    if (auth.session) {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/auth.service.ts#L45-L81","documentation":"AuthService.login first reads the server config and rejects password-based sign-in with this UnauthorizedException (401) when the passwordLogin.enabled setting is false. This is a deliberate server policy, not a credential problem — typically set when the instance is OAuth/OIDC-only.","triggerScenarios":"POST /api/auth/login on an Immich server whose config has passwordLogin.enabled === false (admin disabled password login in Server Settings, or config via env/immich.json omits/enables only OAuth).","commonSituations":"Self-hosters switching to SSO (OAuth) and disabling password login, then old clients/CLIs/scripts still authenticating with email+password; fresh setups where password login was disabled by template config; users who never set a password because accounts were provisioned via OAuth.","solutions":["Log in via the configured OAuth/OIDC flow instead of POST /api/auth/login.","Re-enable password login in Administration > Settings > Authentication (or set server config passwordLogin.enabled=true) if password access is intended.","For programmatic access, create an API key and use the x-api-key header instead of password auth.","Check the server config (GET /api/server/config) to confirm passwordLogin.enabled before attempting password auth."],"exampleFix":"// before\nawait immichApi.login({ email, password }); // 401: password login disabled\n// after\nconst cfg = await immichApi.getServerConfig();\nif (!cfg.passwordLoginEnabled) {\n  client.setApiKey(process.env.IMMICH_API_KEY); // use API key instead\n}","handlingStrategy":"fallback","validationCode":"const cfg = await api.getServerConfig();\nif (!cfg.passwordLoginEnabled) console.warn('Password login disabled; use OAuth or API key');","typeGuard":null,"tryCatchPattern":"try { await api.login({ email, password }); } catch (e) { if (e.status === 401) startOAuthFlow(); else throw e; }","preventionTips":["Check server config for passwordLoginEnabled before offering email/password forms","Prefer API keys for programmatic access","Keep IdP client registrations in sync with Immich auth settings"],"tags":["auth","authentication","oauth","config","immich"],"backgroundTag":"feature-not-enabled","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"}