mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +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
59
README.md
59
README.md
|
@ -316,35 +316,36 @@ If you are not running a reverse proxy change `host` in the `config.toml` to `0.
|
||||||
|
|
||||||
The following environment variables can be used:
|
The following environment variables can be used:
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
|-------------------------------------|--------------------------------------|------------------------------------------|
|
| -------------------------------------- | -------------------------------------------------------- | ---------------------------------------- |
|
||||||
| `AUTOBRR__HOST` | Listen address | `127.0.0.1` |
|
| `AUTOBRR__HOST` | Listen address | `127.0.0.1` |
|
||||||
| `AUTOBRR__PORT` | Listen port | `7474` |
|
| `AUTOBRR__PORT` | Listen port | `7474` |
|
||||||
| `AUTOBRR__BASE_URL` | Base URL for reverse proxy | `/` |
|
| `AUTOBRR__BASE_URL` | Base URL for reverse proxy | `/` |
|
||||||
| `AUTOBRR__LOG_LEVEL` | Log level (DEBUG, INFO, WARN, ERROR) | `INFO` |
|
| `AUTOBRR__LOG_LEVEL` | Log level (DEBUG, INFO, WARN, ERROR) | `INFO` |
|
||||||
| `AUTOBRR__LOG_PATH` | Log file location | `/config/logs` |
|
| `AUTOBRR__LOG_PATH` | Log file location | `/config/logs` |
|
||||||
| `AUTOBRR__LOG_MAX_SIZE` | Max size in MB before rotation | `10` |
|
| `AUTOBRR__LOG_MAX_SIZE` | Max size in MB before rotation | `10` |
|
||||||
| `AUTOBRR__LOG_MAX_BACKUPS` | Number of rotated logs to keep | `5` |
|
| `AUTOBRR__LOG_MAX_BACKUPS` | Number of rotated logs to keep | `5` |
|
||||||
| `AUTOBRR__SESSION_SECRET` | Random string for session encryption | - |
|
| `AUTOBRR__SESSION_SECRET` | Random string for session encryption | - |
|
||||||
| `AUTOBRR__CUSTOM_DEFINITIONS` | Path to custom indexer definitions | - |
|
| `AUTOBRR__CUSTOM_DEFINITIONS` | Path to custom indexer definitions | - |
|
||||||
| `AUTOBRR__CHECK_FOR_UPDATES` | Enable update checks | `true` |
|
| `AUTOBRR__CHECK_FOR_UPDATES` | Enable update checks | `true` |
|
||||||
| `AUTOBRR__DATABASE_TYPE` | Database type (sqlite/postgres) | `sqlite` |
|
| `AUTOBRR__DATABASE_TYPE` | Database type (sqlite/postgres) | `sqlite` |
|
||||||
| `AUTOBRR__POSTGRES_HOST` | PostgreSQL host | - |
|
| `AUTOBRR__POSTGRES_HOST` | PostgreSQL host | - |
|
||||||
| `AUTOBRR__POSTGRES_PORT` | PostgreSQL port | `5432` |
|
| `AUTOBRR__POSTGRES_PORT` | PostgreSQL port | `5432` |
|
||||||
| `AUTOBRR__POSTGRES_DATABASE` | PostgreSQL database name | - |
|
| `AUTOBRR__POSTGRES_DATABASE` | PostgreSQL database name | - |
|
||||||
| `AUTOBRR__POSTGRES_USER` | PostgreSQL username | - |
|
| `AUTOBRR__POSTGRES_USER` | PostgreSQL username | - |
|
||||||
| `AUTOBRR__POSTGRES_PASS` | PostgreSQL password | - |
|
| `AUTOBRR__POSTGRES_PASS` | PostgreSQL password | - |
|
||||||
| `AUTOBRR__POSTGRES_SSLMODE` | PostgreSQL SSL mode | `disable` |
|
| `AUTOBRR__POSTGRES_SSLMODE` | PostgreSQL SSL mode | `disable` |
|
||||||
| `AUTOBRR__POSTGRES_EXTRA_PARAMS` | Additional PostgreSQL parameters | - |
|
| `AUTOBRR__POSTGRES_EXTRA_PARAMS` | Additional PostgreSQL parameters | - |
|
||||||
| `AUTOBRR__OIDC_ENABLED` | Enable OpenID Connect authentication | `false` |
|
| `AUTOBRR__OIDC_ENABLED` | Enable OpenID Connect authentication | `false` |
|
||||||
| `AUTOBRR__OIDC_ISSUER` | OIDC issuer URL | - |
|
| `AUTOBRR__OIDC_ISSUER` | OIDC issuer URL | - |
|
||||||
| `AUTOBRR__OIDC_CLIENT_ID` | OIDC client ID | - |
|
| `AUTOBRR__OIDC_CLIENT_ID` | OIDC client ID | - |
|
||||||
| `AUTOBRR__OIDC_CLIENT_SECRET` | OIDC client secret | - |
|
| `AUTOBRR__OIDC_CLIENT_SECRET` | OIDC client secret | - |
|
||||||
| `AUTOBRR__OIDC_REDIRECT_URL` | OIDC callback URL | `https://baseurl/api/auth/oidc/callback` |
|
| `AUTOBRR__OIDC_REDIRECT_URL` | OIDC callback URL | `https://baseurl/api/auth/oidc/callback` |
|
||||||
| `AUTOBRR__METRICS_ENABLED` | Enable Metrics server | `false` |
|
| `AUTOBRR__OIDC_DISABLE_BUILT_IN_LOGIN` | Disable login form (only works when using external auth) | `false` |
|
||||||
| `AUTOBRR__METRICS_HOST` | Metrics listen address | `127.0.0.1` |
|
| `AUTOBRR__METRICS_ENABLED` | Enable Metrics server | `false` |
|
||||||
| `AUTOBRR__METRICS_PORT` | Metrics listen port | `9074` |
|
| `AUTOBRR__METRICS_HOST` | Metrics listen address | `127.0.0.1` |
|
||||||
| `AUTOBRR__METRICS_BASIC_AUTH_USERS` | Metrics basic auth users | - |
|
| `AUTOBRR__METRICS_PORT` | Metrics listen port | `9074` |
|
||||||
|
| `AUTOBRR__METRICS_BASIC_AUTH_USERS` | Metrics basic auth users | - |
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
|
|
25
config.toml
25
config.toml
|
@ -72,19 +72,22 @@ sessionSecret = "secret-session-key"
|
||||||
# OpenID Connect Configuration
|
# OpenID Connect Configuration
|
||||||
#
|
#
|
||||||
# Enable OIDC authentication
|
# Enable OIDC authentication
|
||||||
#oidc_enabled = false
|
#oidcEnabled = false
|
||||||
|
#
|
||||||
# OIDC Issuer URL (e.g. https://auth.example.com)
|
# OIDC Issuer URL (e.g. https://auth.example.com)
|
||||||
#oidc_issuer = ""
|
#oidcIssuer = ""
|
||||||
|
#
|
||||||
# OIDC Client ID
|
# OIDC Client ID
|
||||||
#oidc_client_id = ""
|
#oidcClientId = ""
|
||||||
|
#
|
||||||
# OIDC Client Secret
|
# OIDC Client Secret
|
||||||
#oidc_client_secret = ""
|
#oidcClientSecret = ""
|
||||||
|
#
|
||||||
# OIDC Redirect URL (e.g. http://localhost:7474/api/auth/oidc/callback)
|
# OIDC Redirect URL (e.g. http://localhost:7474/api/auth/oidc/callback)
|
||||||
#oidc_redirect_url = ""
|
#oidcRedirectUrl = ""
|
||||||
|
#
|
||||||
|
# Disable Built In Login Form (only works when using external auth)
|
||||||
|
#oidcDisableBuiltInLogin = false
|
||||||
|
|
||||||
# Metrics
|
# Metrics
|
||||||
#
|
#
|
||||||
|
@ -93,11 +96,11 @@ sessionSecret = "secret-session-key"
|
||||||
|
|
||||||
# Metrics server host
|
# Metrics server host
|
||||||
#
|
#
|
||||||
# metricsHost = "127.0.0.1"
|
#metricsHost = "127.0.0.1"
|
||||||
|
|
||||||
# Metrics server port
|
# Metrics server port
|
||||||
#
|
#
|
||||||
# metricsPort = "9074"
|
#metricsPort = "9074"
|
||||||
|
|
||||||
# Metrics basic auth
|
# Metrics basic auth
|
||||||
#
|
#
|
||||||
|
|
|
@ -21,12 +21,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type OIDCConfig struct {
|
type OIDCConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Issuer string
|
Issuer string
|
||||||
ClientID string
|
ClientID string
|
||||||
ClientSecret string
|
ClientSecret string
|
||||||
RedirectURL string
|
RedirectURL string
|
||||||
Scopes []string
|
DisableBuiltInLogin bool
|
||||||
|
Scopes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type OIDCHandler struct {
|
type OIDCHandler struct {
|
||||||
|
@ -124,12 +125,13 @@ func NewOIDCHandler(cfg *domain.Config, log zerolog.Logger) (*OIDCHandler, error
|
||||||
handler := &OIDCHandler{
|
handler := &OIDCHandler{
|
||||||
log: log,
|
log: log,
|
||||||
config: &OIDCConfig{
|
config: &OIDCConfig{
|
||||||
Enabled: cfg.OIDCEnabled,
|
Enabled: cfg.OIDCEnabled,
|
||||||
Issuer: cfg.OIDCIssuer,
|
Issuer: cfg.OIDCIssuer,
|
||||||
ClientID: cfg.OIDCClientID,
|
ClientID: cfg.OIDCClientID,
|
||||||
ClientSecret: cfg.OIDCClientSecret,
|
ClientSecret: cfg.OIDCClientSecret,
|
||||||
RedirectURL: cfg.OIDCRedirectURL,
|
RedirectURL: cfg.OIDCRedirectURL,
|
||||||
Scopes: scopes,
|
DisableBuiltInLogin: cfg.OIDCDisableBuiltInLogin,
|
||||||
|
Scopes: scopes,
|
||||||
},
|
},
|
||||||
provider: provider,
|
provider: provider,
|
||||||
verifier: provider.Verifier(oidcConfig),
|
verifier: provider.Verifier(oidcConfig),
|
||||||
|
@ -282,27 +284,30 @@ func (h *OIDCHandler) GetAuthorizationURL() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetConfigResponse struct {
|
type GetConfigResponse struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
AuthorizationURL string `json:"authorizationUrl"`
|
AuthorizationURL string `json:"authorizationUrl"`
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
|
DisableBuiltInLogin bool `json:"disableBuiltInLogin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *OIDCHandler) GetConfigResponse() GetConfigResponse {
|
func (h *OIDCHandler) GetConfigResponse() GetConfigResponse {
|
||||||
if h == nil {
|
if h == nil {
|
||||||
return GetConfigResponse{
|
return GetConfigResponse{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
DisableBuiltInLogin: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state := generateRandomState()
|
state := generateRandomState()
|
||||||
authURL := h.oauthConfig.AuthCodeURL(state)
|
authURL := h.oauthConfig.AuthCodeURL(state)
|
||||||
|
|
||||||
h.log.Debug().Bool("enabled", h.config.Enabled).Str("authorization_url", authURL).Str("state", state).Msg("returning OIDC config response")
|
h.log.Debug().Bool("enabled", h.config.Enabled).Str("authorization_url", authURL).Str("state", state).Bool("disable_built_in_login", h.config.DisableBuiltInLogin).Msg("returning OIDC config response")
|
||||||
|
|
||||||
return GetConfigResponse{
|
return GetConfigResponse{
|
||||||
Enabled: h.config.Enabled,
|
Enabled: h.config.Enabled,
|
||||||
AuthorizationURL: authURL,
|
AuthorizationURL: authURL,
|
||||||
State: state,
|
State: state,
|
||||||
|
DisableBuiltInLogin: h.config.DisableBuiltInLogin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,19 +112,22 @@ sessionSecret = "{{ .sessionSecret }}"
|
||||||
# OpenID Connect Configuration
|
# OpenID Connect Configuration
|
||||||
#
|
#
|
||||||
# Enable OIDC authentication
|
# Enable OIDC authentication
|
||||||
#oidc_enabled = false
|
#oidcEnabled = false
|
||||||
#
|
#
|
||||||
# OIDC Issuer URL (e.g. https://auth.example.com)
|
# OIDC Issuer URL (e.g. https://auth.example.com)
|
||||||
#oidc_issuer = ""
|
#oidcIssuer = ""
|
||||||
#
|
#
|
||||||
# OIDC Client ID
|
# OIDC Client ID
|
||||||
#oidc_client_id = ""
|
#oidcClientId = ""
|
||||||
#
|
#
|
||||||
# OIDC Client Secret
|
# OIDC Client Secret
|
||||||
#oidc_client_secret = ""
|
#oidcClientSecret = ""
|
||||||
#
|
#
|
||||||
# OIDC Redirect URL (e.g. http://localhost:7474/api/auth/oidc/callback)
|
# OIDC Redirect URL (e.g. http://localhost:7474/api/auth/oidc/callback)
|
||||||
#oidc_redirect_url = ""
|
#oidcRedirectUrl = ""
|
||||||
|
#
|
||||||
|
# Disable Built In Login Form (only works when using external auth)
|
||||||
|
#oidcDisableBuiltInLogin = false
|
||||||
|
|
||||||
# Metrics
|
# Metrics
|
||||||
#
|
#
|
||||||
|
@ -432,6 +435,10 @@ func (c *AppConfig) loadFromEnv() {
|
||||||
c.Config.OIDCRedirectURL = v
|
c.Config.OIDCRedirectURL = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv(prefix + "OIDC_DISABLE_BUILT_IN_LOGIN"); v != "" {
|
||||||
|
c.Config.OIDCDisableBuiltInLogin = strings.EqualFold(strings.ToLower(v), "true")
|
||||||
|
}
|
||||||
|
|
||||||
if v := os.Getenv(prefix + "METRICS_ENABLED"); v != "" {
|
if v := os.Getenv(prefix + "METRICS_ENABLED"); v != "" {
|
||||||
c.Config.MetricsEnabled = strings.EqualFold(strings.ToLower(v), "true")
|
c.Config.MetricsEnabled = strings.EqualFold(strings.ToLower(v), "true")
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,41 +4,42 @@
|
||||||
package domain
|
package domain
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Version string
|
Version string
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
Host string `toml:"host"`
|
Host string `toml:"host"`
|
||||||
Port int `toml:"port"`
|
Port int `toml:"port"`
|
||||||
LogLevel string `toml:"logLevel"`
|
LogLevel string `toml:"logLevel"`
|
||||||
LogPath string `toml:"logPath"`
|
LogPath string `toml:"logPath"`
|
||||||
LogMaxSize int `toml:"logMaxSize"`
|
LogMaxSize int `toml:"logMaxSize"`
|
||||||
LogMaxBackups int `toml:"logMaxBackups"`
|
LogMaxBackups int `toml:"logMaxBackups"`
|
||||||
BaseURL string `toml:"baseUrl"`
|
BaseURL string `toml:"baseUrl"`
|
||||||
BaseURLModeLegacy bool `toml:"baseUrlModeLegacy"`
|
BaseURLModeLegacy bool `toml:"baseUrlModeLegacy"`
|
||||||
SessionSecret string `toml:"sessionSecret"`
|
SessionSecret string `toml:"sessionSecret"`
|
||||||
CustomDefinitions string `toml:"customDefinitions"`
|
CustomDefinitions string `toml:"customDefinitions"`
|
||||||
CheckForUpdates bool `toml:"checkForUpdates"`
|
CheckForUpdates bool `toml:"checkForUpdates"`
|
||||||
DatabaseType string `toml:"databaseType"`
|
DatabaseType string `toml:"databaseType"`
|
||||||
DatabaseMaxBackups int `toml:"databaseMaxBackups"`
|
DatabaseMaxBackups int `toml:"databaseMaxBackups"`
|
||||||
PostgresHost string `toml:"postgresHost"`
|
PostgresHost string `toml:"postgresHost"`
|
||||||
PostgresPort int `toml:"postgresPort"`
|
PostgresPort int `toml:"postgresPort"`
|
||||||
PostgresDatabase string `toml:"postgresDatabase"`
|
PostgresDatabase string `toml:"postgresDatabase"`
|
||||||
PostgresUser string `toml:"postgresUser"`
|
PostgresUser string `toml:"postgresUser"`
|
||||||
PostgresPass string `toml:"postgresPass"`
|
PostgresPass string `toml:"postgresPass"`
|
||||||
PostgresSSLMode string `toml:"postgresSSLMode"`
|
PostgresSSLMode string `toml:"postgresSSLMode"`
|
||||||
PostgresExtraParams string `toml:"postgresExtraParams"`
|
PostgresExtraParams string `toml:"postgresExtraParams"`
|
||||||
ProfilingEnabled bool `toml:"profilingEnabled"`
|
ProfilingEnabled bool `toml:"profilingEnabled"`
|
||||||
ProfilingHost string `toml:"profilingHost"`
|
ProfilingHost string `toml:"profilingHost"`
|
||||||
ProfilingPort int `toml:"profilingPort"`
|
ProfilingPort int `toml:"profilingPort"`
|
||||||
OIDCEnabled bool `mapstructure:"oidc_enabled"`
|
OIDCEnabled bool `toml:"oidcEnabled" mapstructure:"oidc_enabled"`
|
||||||
OIDCIssuer string `mapstructure:"oidc_issuer"`
|
OIDCIssuer string `toml:"oidcIssuer" mapstructure:"oidc_issuer"`
|
||||||
OIDCClientID string `mapstructure:"oidc_client_id"`
|
OIDCClientID string `toml:"oidcClientId" mapstructure:"oidc_client_id"`
|
||||||
OIDCClientSecret string `mapstructure:"oidc_client_secret"`
|
OIDCClientSecret string `toml:"oidcClientSecret" mapstructure:"oidc_client_secret"`
|
||||||
OIDCRedirectURL string `mapstructure:"oidc_redirect_url"`
|
OIDCRedirectURL string `toml:"oidcRedirectUrl" mapstructure:"oidc_redirect_url"`
|
||||||
OIDCScopes string `mapstructure:"oidc_scopes"`
|
OIDCScopes string `toml:"oidcScopes" mapstructure:"oidc_scopes"`
|
||||||
MetricsEnabled bool `toml:"metricsEnabled"`
|
OIDCDisableBuiltInLogin bool `toml:"oidcDisableBuiltInLogin" mapstructure:"disable_built_in_login"`
|
||||||
MetricsHost string `toml:"metricsHost"`
|
MetricsEnabled bool `toml:"metricsEnabled"`
|
||||||
MetricsPort int `toml:"metricsPort"`
|
MetricsHost string `toml:"metricsHost"`
|
||||||
MetricsBasicAuthUsers string `toml:"metricsBasicAuthUsers"`
|
MetricsPort int `toml:"metricsPort"`
|
||||||
|
MetricsBasicAuthUsers string `toml:"metricsBasicAuthUsers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigUpdate struct {
|
type ConfigUpdate struct {
|
||||||
|
|
|
@ -262,10 +262,10 @@ export const APIClient = {
|
||||||
{ body: req }),
|
{ body: req }),
|
||||||
getOIDCConfig: async () => {
|
getOIDCConfig: async () => {
|
||||||
try {
|
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) {
|
} catch (error: unknown) {
|
||||||
if (error instanceof Error && error.message?.includes('404')) {
|
if (error instanceof Error && error.message?.includes('404')) {
|
||||||
return { enabled: false, authorizationUrl: '', state: '' };
|
return { enabled: false, authorizationUrl: '', state: '', disableBuiltInLogin: false };
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,83 +140,86 @@ export const Login = () => {
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
|
{/* Wait for OIDC config to load before rendering any login forms */}
|
||||||
<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' : ''}`}>
|
{typeof oidcConfig !== 'undefined' && (
|
||||||
{/* Only show regular login form if onboarding is not available */}
|
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
|
||||||
{!canOnboard && (
|
<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 */}
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
{!canOnboard && (!oidcConfig?.enabled || !oidcConfig?.disableBuiltInLogin) && (
|
||||||
<TextInput<LoginFormFields>
|
<>
|
||||||
name="username"
|
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
||||||
id="username"
|
<TextInput<LoginFormFields>
|
||||||
label="Username"
|
name="username"
|
||||||
type="text"
|
id="username"
|
||||||
register={register}
|
label="Username"
|
||||||
rules={{ required: "Username is required" }}
|
type="text"
|
||||||
errors={formState.errors}
|
register={register}
|
||||||
autoComplete="username"
|
rules={{ required: "Username is required" }}
|
||||||
/>
|
errors={formState.errors}
|
||||||
<PasswordInput<LoginFormFields>
|
autoComplete="username"
|
||||||
name="password"
|
/>
|
||||||
id="password"
|
<PasswordInput<LoginFormFields>
|
||||||
label="Password"
|
name="password"
|
||||||
register={register}
|
id="password"
|
||||||
rules={{ required: "Password is required" }}
|
label="Password"
|
||||||
errors={formState.errors}
|
register={register}
|
||||||
autoComplete="current-password"
|
rules={{ required: "Password is required" }}
|
||||||
/>
|
errors={formState.errors}
|
||||||
|
autoComplete="current-password"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
label={
|
label={
|
||||||
<div className="flex flex-row items-center cursor-pointer text-gray-700 dark:text-gray-200">
|
<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>
|
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>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="py-1">Reset via terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password $USERNAME</code></p>
|
<p className="py-1">Reset via terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password $USERNAME</code></p>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</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
|
<button
|
||||||
type="submit"
|
type="button"
|
||||||
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"
|
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" />
|
<FontAwesomeIcon icon={faOpenid} className="h-5 w-5" />
|
||||||
Sign in
|
<span>OpenID Connect</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</div>
|
||||||
|
)}
|
||||||
{oidcConfig?.enabled && (
|
</div>
|
||||||
<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