Add PULSE_AUTH_HIDE_LOCAL_LOGIN option to hide password form
Implements #750 - allows hiding the username/password login form when using OIDC SSO to avoid user confusion, while maintaining security. - Added HideLocalLogin config option (env: PULSE_AUTH_HIDE_LOCAL_LOGIN) - Exposed hideLocalLogin in /api/security/status endpoint - Updated Login.tsx to conditionally hide local login form - Added escape hatch via ?show_local=true URL parameter This approach avoids the security and upgrade issues that led to DISABLE_AUTH being removed (see #707, #678), while solving the UX problem of users being confused by multiple login options.
This commit is contained in:
parent
9caba86389
commit
6b84b9a2bf
3 changed files with 173 additions and 149 deletions
|
|
@ -20,6 +20,7 @@ interface SecurityStatus {
|
||||||
deprecatedDisableAuth?: boolean;
|
deprecatedDisableAuth?: boolean;
|
||||||
message?: string;
|
message?: string;
|
||||||
apiTokenConfigured?: boolean;
|
apiTokenConfigured?: boolean;
|
||||||
|
hideLocalLogin?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Login: Component<LoginProps> = (props) => {
|
export const Login: Component<LoginProps> = (props) => {
|
||||||
|
|
@ -275,6 +276,12 @@ export const Login: Component<LoginProps> = (props) => {
|
||||||
const showFirstRunSetup = () =>
|
const showFirstRunSetup = () =>
|
||||||
authStatus()?.hasAuthentication === false || legacyDisableAuth();
|
authStatus()?.hasAuthentication === false || legacyDisableAuth();
|
||||||
|
|
||||||
|
const shouldShowLocalLogin = () => {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
if (params.get('show_local') === 'true') return true;
|
||||||
|
return !authStatus()?.hideLocalLogin;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show
|
<Show
|
||||||
when={!loadingAuth()}
|
when={!loadingAuth()}
|
||||||
|
|
@ -306,6 +313,7 @@ export const Login: Component<LoginProps> = (props) => {
|
||||||
oidcLoading,
|
oidcLoading,
|
||||||
oidcError,
|
oidcError,
|
||||||
oidcMessage,
|
oidcMessage,
|
||||||
|
showLocalLogin: shouldShowLocalLogin(),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
@ -346,6 +354,7 @@ const LoginForm: Component<{
|
||||||
oidcLoading: () => boolean;
|
oidcLoading: () => boolean;
|
||||||
oidcError: () => string;
|
oidcError: () => string;
|
||||||
oidcMessage: () => string;
|
oidcMessage: () => string;
|
||||||
|
showLocalLogin: boolean;
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const {
|
const {
|
||||||
username,
|
username,
|
||||||
|
|
@ -362,6 +371,7 @@ const LoginForm: Component<{
|
||||||
oidcLoading,
|
oidcLoading,
|
||||||
oidcError,
|
oidcError,
|
||||||
oidcMessage,
|
oidcMessage,
|
||||||
|
showLocalLogin,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -443,6 +453,7 @@ const LoginForm: Component<{
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={showLocalLogin}>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<label for="username" class="sr-only">
|
<label for="username" class="sr-only">
|
||||||
|
|
@ -606,6 +617,7 @@ const LoginForm: Component<{
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</Show>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -486,6 +486,7 @@ func (r *Router) setupRoutes() {
|
||||||
"authUsername": "",
|
"authUsername": "",
|
||||||
"authLastModified": "",
|
"authLastModified": "",
|
||||||
"oidcUsername": oidcUsername,
|
"oidcUsername": oidcUsername,
|
||||||
|
"hideLocalLogin": r.config.HideLocalLogin,
|
||||||
}
|
}
|
||||||
|
|
||||||
if isAuthenticated {
|
if isAuthenticated {
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ type Config struct {
|
||||||
DemoMode bool `envconfig:"DEMO_MODE" default:"false"` // Read-only demo mode
|
DemoMode bool `envconfig:"DEMO_MODE" default:"false"` // Read-only demo mode
|
||||||
AllowedOrigins string `envconfig:"ALLOWED_ORIGINS" default:"*"`
|
AllowedOrigins string `envconfig:"ALLOWED_ORIGINS" default:"*"`
|
||||||
IframeEmbeddingAllow string `envconfig:"IFRAME_EMBEDDING_ALLOW" default:"SAMEORIGIN"`
|
IframeEmbeddingAllow string `envconfig:"IFRAME_EMBEDDING_ALLOW" default:"SAMEORIGIN"`
|
||||||
|
HideLocalLogin bool `envconfig:"PULSE_AUTH_HIDE_LOCAL_LOGIN" default:"false"`
|
||||||
|
|
||||||
// Proxy authentication settings
|
// Proxy authentication settings
|
||||||
ProxyAuthSecret string `envconfig:"PROXY_AUTH_SECRET"`
|
ProxyAuthSecret string `envconfig:"PROXY_AUTH_SECRET"`
|
||||||
|
|
@ -774,6 +775,16 @@ func Load() (*Config, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hideLocalLoginStr := utils.GetenvTrim("PULSE_AUTH_HIDE_LOCAL_LOGIN"); hideLocalLoginStr != "" {
|
||||||
|
if hide, err := strconv.ParseBool(hideLocalLoginStr); err == nil {
|
||||||
|
cfg.HideLocalLogin = hide
|
||||||
|
cfg.EnvOverrides["PULSE_AUTH_HIDE_LOCAL_LOGIN"] = true
|
||||||
|
log.Info().Bool("hide", hide).Msg("Overriding hide local login setting from environment")
|
||||||
|
} else {
|
||||||
|
log.Warn().Str("value", hideLocalLoginStr).Msg("Invalid PULSE_AUTH_HIDE_LOCAL_LOGIN value, ignoring")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if enabledStr := utils.GetenvTrim("ENABLE_BACKUP_POLLING"); enabledStr != "" {
|
if enabledStr := utils.GetenvTrim("ENABLE_BACKUP_POLLING"); enabledStr != "" {
|
||||||
switch strings.ToLower(enabledStr) {
|
switch strings.ToLower(enabledStr) {
|
||||||
case "0", "false", "no", "off":
|
case "0", "false", "no", "off":
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue