refactor: убрать вход через внешние провайдеры (OAuth) полностью
Решение владельца 27.09.2026 (D-084): сервис ставится на сервер конкретного человека, и ему всё равно нужен свой OAuth у провайдера — поддержка общего входа только создаёт трение (регистрация приложений, redirect URI, модерация, чужие ключи в конфиге). Способы входа остаются: пароль + 2FA и ключи доступа (WebAuthn). Удалено: - сервер: internal/auth/oauth.go, internal/server/oauth.go, internal/store/oauth.go и их тесты; поля и методы конфига OAuth*; oauthLimiter и регистрация ручек; отображение ошибок oauth.*; features.oauth_enabled/oauth_providers в /meta; - клиент: web/src/api/oauth.ts, раздел «Вход через внешние сервисы», кнопки провайдеров на странице входа, ключи i18n (ru/en), тесты и фикстуры; - установщик: переменные OAUTH_* из .env, .env.example и шаблона (хелпер чтения существующих значений переименован в existing_value — он остался нужен для VAPID_SUBJECT); - зависимость golang.org/x/oauth2 (go mod tidy). Схема: миграция 00027 удаляет таблицу oauth_accounts (00019 не переписываем — она применена на стендах). Откат миграции возвращает структуру; тест TestOAuthRemovalMigration проверяет накат, откат и повторный накат. AGENT.md (локальный) помечает пункты про OAuth как отменённые.
This commit is contained in:
@@ -60,11 +60,8 @@ type Service struct {
|
||||
webauthn *webauthn.WebAuthn
|
||||
// ceremonies — начатые церемонии WebAuthn (в памяти, одноразовые).
|
||||
ceremonies *ceremonyStore
|
||||
// oauth — включённые провайдеры (client id/secret из env), oauthRedirectBase —
|
||||
// внешний адрес инстанса для redirect_uri, stateKey — ключ подписи state.
|
||||
oauth map[string]oauthClientCredentials
|
||||
oauthRedirectBase string
|
||||
stateKey string
|
||||
stateKey string
|
||||
}
|
||||
|
||||
type instanceSettings interface {
|
||||
@@ -113,9 +110,8 @@ func New(ctx context.Context, cfg config.Config, st *store.Store, logger *slog.L
|
||||
sessionTTL = store.SessionTTL
|
||||
}
|
||||
|
||||
// OAuth-провайдеры и RP-конфигурация passkeys: включаются конфигом, при
|
||||
// RP-конфигурация passkeys: включается конфигом, при
|
||||
// отсутствии настроек соответствующие ручки отвечают понятной ошибкой.
|
||||
oauthClients, oauthRedirectBase := oauthFromConfig(cfg, cfg.BaseURL())
|
||||
|
||||
service := &Service{
|
||||
store: st,
|
||||
@@ -126,11 +122,8 @@ func New(ctx context.Context, cfg config.Config, st *store.Store, logger *slog.L
|
||||
policy: policy,
|
||||
cfg: Config{SessionTTL: sessionTTL, MaxLoginFails: 5, LockoutWindow: 15 * time.Minute},
|
||||
logger: logger,
|
||||
// state OAuth подписывается секретом сессий: отдельного секрета не нужно.
|
||||
oauth: oauthClients,
|
||||
oauthRedirectBase: oauthRedirectBase,
|
||||
stateKey: cfg.SessionPepper,
|
||||
ceremonies: newCeremonyStore(),
|
||||
stateKey: cfg.SessionPepper,
|
||||
ceremonies: newCeremonyStore(),
|
||||
}
|
||||
// Passkeys требуют корректного RP ID: для IP-адреса (стенд без домена)
|
||||
// браузеры WebAuthn не работают, поэтому такой инстанс просто живёт без них.
|
||||
|
||||
Reference in New Issue
Block a user