mirror of
https://github.com/idanoo/autobrr
synced 2025-07-22 16:29:12 +00:00
feat(auth): add option to disable built-in login when using OIDC (#1908)
* feat(auth): disable built-in login by config * cleanup config * fix(web): prevent login form flash by waiting for OIDC config * refactor(config): standardize OIDC TOML format - Adds camelCase TOML tags to OIDC config struct while keeping mapstructure tags for backward compatibility - Updates config template to use camelCase format * refactor: kyles changes * refactor: prefix disablebuiltinlogin with oidc * docs: revert format change --------- Co-authored-by: ze0s <43699394+zze0s@users.noreply.github.com>
This commit is contained in:
parent
9eff694a5f
commit
024371e4eb
7 changed files with 192 additions and 172 deletions
|
@ -262,10 +262,10 @@ export const APIClient = {
|
|||
{ body: req }),
|
||||
getOIDCConfig: async () => {
|
||||
try {
|
||||
return await appClient.Get<{ enabled: boolean; authorizationUrl: string; state: string }>("api/auth/oidc/config");
|
||||
return await appClient.Get<{ enabled: boolean; authorizationUrl: string; state: string; disableBuiltInLogin: boolean }>("api/auth/oidc/config");
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error && error.message?.includes('404')) {
|
||||
return { enabled: false, authorizationUrl: '', state: '' };
|
||||
return { enabled: false, authorizationUrl: '', state: '', disableBuiltInLogin: false };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -140,83 +140,86 @@ export const Login = () => {
|
|||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
|
||||
<div className={`px-6 ${!canOnboard ? 'py-12 bg-white dark:bg-gray-800 shadow sm:rounded-lg sm:px-12 border border-gray-150 dark:border-gray-775' : ''}`}>
|
||||
{/* Only show regular login form if onboarding is not available */}
|
||||
{!canOnboard && (
|
||||
<>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
||||
<TextInput<LoginFormFields>
|
||||
name="username"
|
||||
id="username"
|
||||
label="Username"
|
||||
type="text"
|
||||
register={register}
|
||||
rules={{ required: "Username is required" }}
|
||||
errors={formState.errors}
|
||||
autoComplete="username"
|
||||
/>
|
||||
<PasswordInput<LoginFormFields>
|
||||
name="password"
|
||||
id="password"
|
||||
label="Password"
|
||||
register={register}
|
||||
rules={{ required: "Password is required" }}
|
||||
errors={formState.errors}
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
{/* Wait for OIDC config to load before rendering any login forms */}
|
||||
{typeof oidcConfig !== 'undefined' && (
|
||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
|
||||
<div className={`px-6 ${(!canOnboard && (!oidcConfig?.enabled || !oidcConfig?.disableBuiltInLogin)) ? 'py-12 bg-white dark:bg-gray-800 shadow sm:rounded-lg sm:px-12 border border-gray-150 dark:border-gray-775' : ''}`}>
|
||||
{/* Built-in login form */}
|
||||
{!canOnboard && (!oidcConfig?.enabled || !oidcConfig?.disableBuiltInLogin) && (
|
||||
<>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
||||
<TextInput<LoginFormFields>
|
||||
name="username"
|
||||
id="username"
|
||||
label="Username"
|
||||
type="text"
|
||||
register={register}
|
||||
rules={{ required: "Username is required" }}
|
||||
errors={formState.errors}
|
||||
autoComplete="username"
|
||||
/>
|
||||
<PasswordInput<LoginFormFields>
|
||||
name="password"
|
||||
id="password"
|
||||
label="Password"
|
||||
register={register}
|
||||
rules={{ required: "Password is required" }}
|
||||
errors={formState.errors}
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<div className="text-sm">
|
||||
<Tooltip
|
||||
label={
|
||||
<div className="flex flex-row items-center cursor-pointer text-gray-700 dark:text-gray-200">
|
||||
Forgot password? <svg className="ml-1 w-3 h-3 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10" /></svg>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<p className="py-1">Reset via terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password $USERNAME</code></p>
|
||||
</Tooltip>
|
||||
<div className="flex items-center justify-end">
|
||||
<div className="text-sm">
|
||||
<Tooltip
|
||||
label={
|
||||
<div className="flex flex-row items-center cursor-pointer text-gray-700 dark:text-gray-200">
|
||||
Forgot password? <svg className="ml-1 w-3 h-3 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10" /></svg>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<p className="py-1">Reset via terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password $USERNAME</code></p>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex items-center justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
>
|
||||
<RocketLaunchIcon className="w-4 h-4 mr-1.5" />
|
||||
Sign in
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{oidcConfig?.enabled && (
|
||||
<div className="relative mt-10">
|
||||
<div aria-hidden="true" className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-gray-200 dark:border-gray-700" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-sm">
|
||||
<span className="bg-white dark:bg-gray-800 px-6 text-gray-900 dark:text-gray-200">Or continue with</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* OIDC button */}
|
||||
{oidcConfig?.enabled && (
|
||||
<div className={(!canOnboard && !oidcConfig?.disableBuiltInLogin) ? 'mt-6' : ''}>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex items-center justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
type="button"
|
||||
onClick={handleOIDCLogin}
|
||||
className="w-full flex items-center justify-center gap-3 py-2 px-4 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm text-sm font-medium text-gray-900 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<RocketLaunchIcon className="w-4 h-4 mr-1.5" />
|
||||
Sign in
|
||||
<FontAwesomeIcon icon={faOpenid} className="h-5 w-5" />
|
||||
<span>OpenID Connect</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{oidcConfig?.enabled && (
|
||||
<div className="relative mt-10">
|
||||
<div aria-hidden="true" className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-gray-200 dark:border-gray-700" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-sm">
|
||||
<span className="bg-white dark:bg-gray-800 px-6 text-gray-900 dark:text-gray-200">Or continue with</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* OIDC login button */}
|
||||
{oidcConfig?.enabled && (
|
||||
<div className={!canOnboard ? 'mt-6' : ''}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOIDCLogin}
|
||||
className="w-full flex items-center justify-center gap-3 py-2 px-4 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm text-sm font-medium text-gray-900 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<FontAwesomeIcon icon={faOpenid} className="h-5 w-5" />
|
||||
<span>OpenID Connect</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue