Преминете към основното съдържание

Автентикация

Licensing Server поддържа два механизма за автентикация: OAuth 2.0 (Google, Azure/Microsoft, GitHub) и Email/Password. И двата издават JWT токени за последващ достъп до API-то.

Общ поток на автентикация

OAuth Flow (Google, Azure, GitHub)

1. Login Page (GET /auth/login-page)

Desktop клиентът отваря browser с URL:

{BASE_URL}/auth/login-page?redirect_uri=http://localhost:PORT/callback&state=random&device_id=DEVICE_HASH&lang=bg

Handler-ът:

  1. Запазва redirect_uri, state и device_id в session cookie
  2. Рендерира login.html с Turnstile site key и i18n strings

2. OAuth Redirect (GET /auth/login/:provider)

Когато потребителят кликне OAuth бутон:

  1. Зарежда redirect_uri, state и device_id от session-а
  2. Генерира 32-byte криптографски nonce (crypto/rand)
  3. Запазва nonce-а в session-а
  4. Пренасочва към OAuth provider-а с state=nonce

Поддържани providers:

ProviderUserInfo URLScopes
Googlegoogleapis.com/oauth2/v3/userinfoopenid, email, profile
Azuregraph.microsoft.com/v1.0/meopenid, email, profile, User.Read
GitHubapi.github.com/user + /user/emailsuser:email

3. OAuth Callback (GET /auth/callback/:provider)

Nonce валидация: state параметърът от callback-а се сравнява с nonce-а, запазен в session-а. При несъответствие заявката се отхвърля с 400.

User upsert: GetOrCreateUser търси по (provider, provider_id). Ако потребителят съществува, обновява email, name и avatar. Ако не -- създава нов с plan = "free" (или DEV_DEFAULT_PLAN в dev) и trial_started_at = NOW().

4. Token Refresh (POST /auth/refresh)

POST /auth/refresh
{"token": "existing_jwt"}
  1. Декодира и валидира JWT-то (не е нужно да е изтекло)
  2. Зарежда потребителя от DB по user_id от claims
  3. Издава нов JWT с актуален план и email

Rate limit: 30 req/min per IP.

Email/Password Flow

Регистрация (POST /auth/register)

POST /auth/register
{
"email": "user@example.com",
"password": "min8chars",
"name": "John",
"cf-turnstile-response": "turnstile_token",
"lang": "bg"
}

Поток:

  1. Валидация на Turnstile token (bot protection)
  2. Проверка: парола >= 8 символа, валиден email
  3. Проверка за дублиран email (всички providers, не само email)
  4. Хеширане на паролата с bcrypt (cost = 12)
  5. Създаване на user с provider = "email", email_verified = FALSE
  6. Генериране на verification token (32 random bytes -> hex)
  7. Запазване на sha256(token) в email_tokens с kind = "verify", expires_at = NOW() + 24h
  8. Изпращане на verification email чрез Resend API
  9. Отговор: 202 Accepted

Email Verification (двустъпков процес)

За да се предотвратят email link pre-scanners (Microsoft Safe Links и др.), верификацията е двустъпкова:

Login (POST /auth/login/email)

POST /auth/login/email
{
"email": "user@example.com",
"password": "password123",
"cf-turnstile-response": "turnstile_token"
}

Поток:

  1. Валидация на Turnstile token
  2. Търсене на user с provider = 'email' и подадения email
  3. Ако user не е намерен -- dummy bcrypt compare (timing-safe) -> ErrBadCredentials
  4. bcrypt compare на паролата
  5. Проверка дали email_verified = TRUE -> ако не: ErrNotVerified (403)
  6. Stripe sync (ако има customer ID)
  7. Device limit check (за free users)
  8. Издаване на JWT

Password Reset

Reset token: Изтича след 1 час (за разлика от verification token-а -- 24 часа).

Cloudflare Turnstile Bot Protection

Turnstile се интегрира в login страницата и се изисква за:

  • POST /auth/register
  • POST /auth/login/email

Поведение по среди:

  • Production (GIN_MODE=release): TURNSTILE_SECRET_KEY е задължителен; заявки без валиден token се отхвърлят
  • Development: Ако TURNSTILE_SECRET_KEY е празен, валидацията се пропуска

Валидацията се извършва server-side чрез POST заявка към https://challenges.cloudflare.com/turnstile/v1/siteverify.

Device Account Limiting

За предотвратяване на злоупотреба, free потребители имат ограничение за брой отделни акаунти от едно устройство.

Конфигурация:

  • DEVICE_ACCOUNTS_MAX -- максимален брой акаунти per device (default: 2)
  • COOLDOWN_HOURS -- прозорец за броене (default: 5 часа)

Redirect URI Validation

Redirect URI-тата се валидират срещу конфигурирани prefix-и (ALLOWED_REDIRECT_URIS):

  • Проверява се scheme, host (exact match), port (ако е зададен) и path prefix
  • В development mode (без конфигурирани prefix-и) се позволяват всички http:// и https:// URI-та
  • Защита срещу prefix spoofing: валидацията е на host boundary, не на string prefix