immich-app/immich · error · UnauthorizedException
Password login has been disabled
Error message
Password login has been disabled
What it means
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.
Source
Thrown at server/src/services/auth.service.ts:62
export type ValidateRequest = {
headers: IncomingHttpHeaders;
queryParams: Record<string, string>;
metadata: {
sharedLinkRoute: boolean;
adminRoute: boolean;
/** `false` explicitly means no permission is required, which otherwise defaults to `all` */
permission?: Permission | false;
uri: string;
};
};
@Injectable()
export class AuthService extends BaseService {
async login(dto: LoginCredentialDto, details: LoginDetails) {
const config = await this.getConfig({ withCache: false });
if (!config.passwordLogin.enabled) {
throw new UnauthorizedException('Password login has been disabled');
}
const user = await this.userRepository.getByEmail(dto.email, { withPassword: true });
// Always run bcrypt so response time is constant regardless of whether the email
// is registered, preventing timing-based user enumeration.
const isAuthenticated = this.cryptoRepository.compareBcrypt(dto.password, user?.password ?? LOGIN_DUMMY_HASH);
if (!user || !user.password || !isAuthenticated) {
this.logger.warn(`Failed login attempt for user ${dto.email} from ip address ${details.clientIp}`);
throw new UnauthorizedException('Incorrect email or password');
}
return this.createLoginResponse(user, details);
}
async logout(auth: AuthDto, authType: AuthType): Promise<LogoutResponseDto> {
let oauthBearerToken: string | undefined;
if (auth.session) {View on GitHub (pinned to 199723261c)
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.
Example fix
// before
await api.post('/auth/login', { email, password });
// after
const cfg = await api.get('/oauth/config');
if (cfg.data.enabled) {
window.location = cfg.data.url; // redirect to IdP
} else {
await api.post('/auth/login', { email, password });
} Defensive patterns
Strategy: validation
Validate before calling
// Discover enabled auth methods before attempting password login.
const { data: oauth } = await api.get('/oauth/config');
if (oauth.enabled) {
throw new Error('Password login disabled; use OAuth.');
}
await api.post('/auth/login', { email, password }); Try / catch
try {
await api.post('/auth/login', { email, password });
} catch (e) {
if (e.response?.status === 401 && /disabled/i.test(e.response?.data?.message)) {
redirectToOAuth(); // password login is off
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: OAuth-only Immich instance; misconfigured deployment expecting password login; legacy client/script still using password auth after a policy change.
Related errors
- Incorrect email or password
- Received backchannel logout request but OAuth is not enabled
- OAuth is not enabled
- Error backchannel logout: token validation failed
- Invalid logout token: no claims found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/044be41e0cfe17c6.
Report an issue: GitHub.