{"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":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":62,"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":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/auth.service.ts#L44-L80","documentation":"Thrown by AuthService.login (POST /auth/login) when the server config has passwordLogin.enabled === false. The administrator has disabled password authentication (typically an OAuth-only deployment), so any password login attempt is rejected up front with 401 Unauthorized before credentials are even checked.","triggerScenarios":"POST /auth/login on a server whose passwordLogin.enabled config is false; an IdP-only deployment where someone still tries email/password; admin flipped the flag and clients haven't adapted.","commonSituations":"OAuth-only Immich instance; misconfigured deployment expecting password login; legacy client/script still using password auth after a policy change.","solutions":["Switch the client to OAuth login flow (GET /oauth/authorize etc.).","If password login is intended, set passwordLogin.enabled=true in the server system config and restart.","Check the /server-feature-flags or admin system settings to confirm which auth methods are enabled."],"exampleFix":"// before\nawait api.post('/auth/login', { email, password });\n\n// after\nconst cfg = await api.get('/oauth/config');\nif (cfg.data.enabled) {\n  window.location = cfg.data.url; // redirect to IdP\n} else {\n  await api.post('/auth/login', { email, password });\n}","handlingStrategy":"validation","validationCode":"// Discover enabled auth methods before attempting password login.\nconst { data: oauth } = await api.get('/oauth/config');\nif (oauth.enabled) {\n  throw new Error('Password login disabled; use OAuth.');\n}\nawait api.post('/auth/login', { email, password });","typeGuard":null,"tryCatchPattern":"try {\n  await api.post('/auth/login', { email, password });\n} catch (e) {\n  if (e.response?.status === 401 && /disabled/i.test(e.response?.data?.message)) {\n    redirectToOAuth(); // password login is off\n  } else throw e;\n}","preventionTips":["Read the OAuth config / feature flags at startup to choose the login flow.","If you administer the server, set passwordLogin.enabled explicitly.","Keep clients updated when auth policy changes."],"tags":["auth","login","oauth","config","unauthorized"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}