hide login if login type disabled (#5438)

# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Anthony Stirling
2026-01-12 19:38:02 +00:00
committed by GitHub
parent d2677e64dd
commit d4d4538630
3 changed files with 39 additions and 13 deletions

View File

@@ -169,7 +169,10 @@ public class ProprietaryUIDataController {
OAUTH2 oauth = securityProps.getOauth2();
if (oauth != null && oauth.getEnabled()) {
// Only add OAuth2 providers if loginMethod allows it
if (oauth != null
&& oauth.getEnabled()
&& securityProps.isOauth2Active()) { // This checks loginMethod
if (oauth.isSettingsValid()) {
String firstChar = String.valueOf(oauth.getProvider().charAt(0));
String clientName =
@@ -201,6 +204,7 @@ public class ProprietaryUIDataController {
}
SAML2 saml2 = securityProps.getSaml2();
// Only add SAML2 providers if loginMethod allows it
if (securityProps.isSaml2Active() && applicationProperties.getPremium().isEnabled()) {
String samlIdp = saml2.getProvider();
String saml2AuthenticationPath = "/saml2/authenticate/" + saml2.getRegistrationId();

View File

@@ -21,6 +21,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.audit.AuditEventType;
import stirling.software.proprietary.audit.AuditLevel;
import stirling.software.proprietary.audit.Audited;
@@ -44,6 +45,7 @@ public class AuthController {
private final JwtServiceInterface jwtService;
private final CustomUserDetailsService userDetailsService;
private final LoginAttemptService loginAttemptService;
private final ApplicationProperties.Security securityProperties;
/**
* Login endpoint - replaces Supabase signInWithPassword
@@ -60,6 +62,17 @@ public class AuthController {
HttpServletRequest httpRequest,
HttpServletResponse response) {
try {
// Check if username/password authentication is allowed
if (!securityProperties.isUserPass()) {
log.warn(
"Username/password login attempted but not allowed by current login method configuration");
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(
Map.of(
"error",
"Username/password authentication is not enabled. Please use the configured authentication method."));
}
// Validate input parameters
if (request.getUsername() == null || request.getUsername().trim().isEmpty()) {
log.warn("Login attempt with null or empty username");

View File

@@ -36,6 +36,7 @@ export default function Login() {
const [enabledProviders, setEnabledProviders] = useState<OAuthProvider[]>([]);
const [hasSSOProviders, setHasSSOProviders] = useState(false);
const [_enableLogin, setEnableLogin] = useState<boolean | null>(null);
const [loginMethod, setLoginMethod] = useState<string>('all');
const backendProbe = useBackendProbe();
const [isFirstTimeSetup, setIsFirstTimeSetup] = useState(false);
const [showDefaultCredentials, setShowDefaultCredentials] = useState(false);
@@ -115,6 +116,7 @@ export default function Login() {
const providerPaths = Object.keys(data.providerList || {});
setEnabledProviders(providerPaths);
setLoginMethod(data.loginMethod || 'all');
} catch (err) {
console.error('[Login] Failed to fetch enabled providers:', err);
}
@@ -125,18 +127,25 @@ export default function Login() {
}
}, [navigate, backendProbe.status, backendProbe.loginDisabled]);
// Update hasSSOProviders and showEmailForm when enabledProviders changes
// Update hasSSOProviders and showEmailForm when enabledProviders or loginMethod changes
useEffect(() => {
// In debug mode, check if any providers exist in the config
const hasProviders = DEBUG_SHOW_ALL_PROVIDERS
? Object.keys(oauthProviderConfig).length > 0
: enabledProviders.length > 0;
setHasSSOProviders(hasProviders);
// If no SSO providers, show email form by default
if (!hasProviders) {
// Check if username/password authentication is allowed
const isUserPassAllowed = loginMethod === 'all' || loginMethod === 'normal';
// Show email form if no SSO providers exist AND username/password is allowed
if (!hasProviders && isUserPassAllowed) {
setShowEmailForm(true);
} else if (!isUserPassAllowed) {
// Hide email form if username/password auth is not allowed
setShowEmailForm(false);
}
}, [enabledProviders]);
}, [enabledProviders, loginMethod]);
// Handle query params (email prefill, success messages, and session expiry)
useEffect(() => {
@@ -326,13 +335,13 @@ export default function Login() {
enabledProviders={enabledProviders}
/>
{/* Divider between OAuth and Email - only show if SSO is available */}
{hasSSOProviders && (
{/* Divider between OAuth and Email - only show if SSO is available and username/password is allowed */}
{hasSSOProviders && (loginMethod === 'all' || loginMethod === 'normal') && (
<DividerWithText text={t('signup.or', 'or')} respondsToDarkMode={false} opacity={0.4} />
)}
{/* Sign in with email button - only show if SSO providers exist */}
{hasSSOProviders && !showEmailForm && (
{/* Sign in with email button - only show if SSO providers exist and username/password is allowed */}
{hasSSOProviders && !showEmailForm && (loginMethod === 'all' || loginMethod === 'normal') && (
<div className="auth-section">
<button
type="button"
@@ -345,8 +354,8 @@ export default function Login() {
</div>
)}
{/* Email form - show by default if no SSO, or when button clicked */}
{showEmailForm && (
{/* Email form - show by default if no SSO, or when button clicked, but ONLY if username/password is allowed */}
{showEmailForm && (loginMethod === 'all' || loginMethod === 'normal') && (
<div style={{ marginTop: hasSSOProviders ? '1rem' : '0' }}>
<EmailPasswordForm
email={email}
@@ -360,8 +369,8 @@ export default function Login() {
</div>
)}
{/* Help section - only show on first-time setup with default credentials */}
{isFirstTimeSetup && showDefaultCredentials && (
{/* Help section - only show on first-time setup with default credentials and username/password auth allowed */}
{isFirstTimeSetup && showDefaultCredentials && (loginMethod === 'all' || loginMethod === 'normal') && (
<Alert
color="blue"
variant="light"