← Все проекты

Кейс · Go-бэкенд

Ключница: сервис аутентификации

Сервис аутентификации и авторизации на Go: EdDSA-JWT с ротацией ключей и JWKS, refresh-токены с ротацией и обнаружением кражи, TOTP-2FA (RFC 6238) с резервными кодами, RBAC, блокировка при переборе, сброс пароля по одноразовому токену, журнал аудита, список устройств, openapi.yaml. Не прошёл независимый аудит, не production-IdP.

  • Go
  • stdlib crypto
  • SQLite
  • modernc.org/sqlite (без CGO)
  • JWT EdDSA/Ed25519
  • JWKS
  • PBKDF2
  • TOTP
  • RBAC
  • REST
  • OpenAPI 3
  • Vanilla JS
  • embed
  • Docker
  • GitHub Actions

01 · Как выглядит

Скриншоты

Скриншот проекта «Ключница: сервис аутентификации» на экране 1280 пикселей
Десктоп, 1280 px
Скриншот проекта «Ключница: сервис аутентификации» на экране телефона, 390 пикселей
Телефон, 390 px

02 · О проекте

Что это и зачем

«Ключница» — сервис аутентификации и авторизации на Go: регистрация и вход, короткоживущие JWT с ротацией ключей и JWKS, refresh-токены с ротацией и обнаружением кражи, TOTP-2FA с резервными кодами, RBAC, защита от перебора, сброс пароля, журнал аудита и управление устройствами.

Стандартная библиотека плюс modernc.org/sqlite (без CGO), интерфейс на ванильном JS встроен через embed, API описан в openapi.yaml. Это учебный проект: он не проходил независимого аудита безопасности и не является production-IdP, ограничения перечислены ниже.

Ограничения

Не прошёл независимый аудит и не production-IdP. Нет OAuth 2.0 и OIDC, WebAuthn, подтверждения почты, входа через соцсети. Пароли хешируются PBKDF2, а не argon2id, потому что argon2 нет в stdlib.

Секреты TOTP и приватные ключи подписи лежат в БД открытым текстом: с дампом БД можно подделать токены. Письмо для сброса пароля это заглушка (лог и файл), QR-кода для 2FA нет.

Мгновенный отзыв работает только внутри самого сервиса: сторонний потребитель JWT узнает об отзыве не раньше exp (10 минут). Лимитер хранится в памяти одного процесса, масштабирования нет.

Демо-пароли публичные, они показаны в интерфейсе и помечены плашкой, пользоваться ими вне демонстрации нельзя. Тесты с -race проходят только в CI, Docker-образ не собирался.

Что внутри

  • Access-токен JWT с alg=EdDSA (Ed25519): подпись и разбор написаны на stdlib, none и HS256 отклоняются до проверки подписи, проверяются exp, nbf, iss, aud и typ
  • Ротация ключей через API и публичный JWKS (RFC 7517/8037): чужой сервис проверяет токены сам, старый ключ живёт ещё access_ttl + 1 минуту
  • Refresh-токены хранятся хешем SHA-256; повторное предъявление использованного токена отзывает всю семью токенов и пишет token.reuse_detected в аудит
  • TOTP по RFC 6238 на stdlib, проверен тестовыми векторами RFC, окно ±1 шаг, защита от повтора кода, 8 одноразовых резервных кодов
  • Пароли: PBKDF2-HMAC-SHA256, 600 000 итераций, сравнение за постоянное время, фиктивный хеш для неизвестного логина, чтобы не раскрывать, есть ли такой пользователь
  • Блокировка при переборе с экспоненциальной задержкой (429 и Retry-After), плюс лимит запросов на IP
  • RBAC: права берутся из БД на каждом запросе, нельзя оставить систему без администратора и отключить самого себя
  • Сброс пароля одноразовым токеном, после сброса все сессии завершаются; журнал аудита только на дозапись (триггеры БД запрещают UPDATE и DELETE)
  • Список устройств с отзывом сессий, CSP без unsafe-inline, HttpOnly + SameSite=Strict cookie, CSRF-токен, проверка Origin

03 · Как запустить

Запуск одной командой

git clone <репозиторий по запросу> auth-service
cd auth-service
SEED_DEMO=1 go run ./cmd/server   # http://localhost:8101, публичные демо-учётки показаны на странице входа

04 · Код

Репозиторий приватный

Исходники лежат в приватном репозитории. Открою доступ по запросу: напишите, и пришлю приглашение.

Запросить код