Справочник API: аутентификация и пользователи
Предоставляет эндпоинты регистрации, входа, обновления токена, профиля и обработки приглашений. Требования к аутентификации различаются по эндпоинтам; публичные эндпоинты помечены в соответствующих записях.
Если не указано иное, эндпоинты этой группы после middleware аутентификации требуют лишь «быть авторизованным» (без минимальной роли). Эндпоинты без аутентификации см. в соответствующих записях.
Аутентификация (/api/v1/auth)
POST /api/v1/auth/register
Назначение: регистрация нового пользователя (режим самостоятельной регистрации). Без аутентификации. Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
username | string | Да | Имя пользователя, 2–50 символов |
email | string | Да | |
password | string | Да | Пароль (8–32 символов, буквы+цифры; в сложном режиме дополнительно требуются строчные и прописные буквы и специальные символы) |
Автоматически ли создаётся личное пространство, определяется серверным auth.default_tenant_mode; в теле запроса это указать нельзя. В режимах invite_register (регистрация только по приглашению) и invite_only (регистрация запрещена) возвращается 403.
Ответ: 201 {"success":true,"message":"...","user":{User}}
curl -X POST $BASE/api/v1/auth/register -H 'Content-Type: application/json' \
-d '{"username":"alice","email":"a@ex.com","password":"secret123"}'POST /api/v1/auth/register-by-invite
Только режимы self_serve и invite_register позволяют регистрацию по действующей ссылке-приглашению; в режиме invite_only возвращается 403.
Назначение: регистрация по токену приглашения/ссылки общего доступа и присоединение к пространству. Без аутентификации, ограничение по IP 30 раз/минуту. Handler: internal/handler/auth_register_by_invite.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
token | string | Да (binding:"required") | Токен приглашения |
email | string | Да (binding:"required,email") | |
username | string | Да (binding:"required") | Имя пользователя |
password | string | Да (binding:"required,min=6") | Пароль (8–32 символов, буквы+цифры; в сложном режиме дополнительно требуются строчные и прописные буквы и специальные символы) |
Ответ: 201, как у Login (user/active_tenant/memberships/token/refresh_token).
curl -X POST $BASE/api/v1/auth/register-by-invite -H 'Content-Type: application/json' \
-d '{"token":"<invite_token>","email":"a@ex.com","username":"alice","password":"secret123"}'POST /api/v1/auth/invitations/lookup
Назначение: анонимный запрос информации о пространстве, соответствующем токену приглашения (предпросмотр перед регистрацией). Без аутентификации, ограничение по IP. Handler: internal/handler/auth_register_by_invite.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
token | string | Да (binding:"required") | Токен приглашения |
Ответ: 200 {"success":true,"data":{"tenant_id","tenant_name","role","expires_at"}}
curl -X POST $BASE/api/v1/auth/invitations/lookup -H 'Content-Type: application/json' -d '{"token":"<invite_token>"}'POST /api/v1/auth/login
Назначение: вход по email и паролю. Без аутентификации. Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
email | string | Да (binding:"required") | |
password | string | Да (binding:"required") | Пароль |
Ответ: 200 {"success":true,"user":{...},"active_tenant":{...},"memberships":[...],"token":"...","refresh_token":"..."}
curl -X POST $BASE/api/v1/auth/login -H 'Content-Type: application/json' -d '{"email":"a@ex.com","password":"secret123"}'POST /api/v1/auth/auto-setup
Назначение: автоматическое создание аккаунта, пространства и вход для нативного десктопного Lite. Обязательно должен нести случайный для каждого процесса X-WeKnora-Desktop-Token, предоставляемый нативным десктопным мостом; анонимные HTTP-запросы не принимаются. Обычные браузеры используют эндпоинты регистрации/входа. Handler: internal/handler/auth.go
Ответ: 200, как у Login; отсутствующие или неверные десктопные учётные данные возвращают 401.
GET /api/v1/auth/config
Назначение: запрос конфигурации аутентификации, например режима регистрации. Без аутентификации. Handler: internal/handler/auth.go
Ответ: 200 {"success":true,"registration_mode":"self_serve|invite_register|invite_only","complex_password_enabled":false}
curl $BASE/api/v1/auth/configPOST /api/v1/auth/switch-tenant
Назначение: переключение текущего активного пространства и выдача нового token. Требуется вход (можно вызывать и без пространства). Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
tenant_id | uint64 | Да (binding:"required") | ID целевого пространства |
refresh_token | string | Нет | Используется для выдачи нового token |
Ответ: 200, как у Login.
Успешная перевыдача записывает целевое пространство в предпочтение «последний активный тенант» уровня аккаунта; следующий вход (пароль/OIDC/смена устройства) и refresh возвращаются в это пространство. refresh JWT не содержит tenant_id, поэтому если запись предпочтения не удалась, вся перевыдача проваливается и новый token не выдаётся. Клиенту API не нужно дополнительно вызывать PUT /auth/me/preferences. Переключение пространства в Web UI не идёт через этот эндпоинт. Одна перевыдача меняет точку возврата для всех устройств этого пользователя.
curl -X POST $BASE/api/v1/auth/switch-tenant -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"tenant_id":2}'GET /api/v1/auth/oidc/config
Назначение: запрос, включён ли OIDC, и его отображаемого имени. Без аутентификации. Handler: internal/handler/auth.go
Ответ: 200 {"success":true,"enabled":bool,"provider_display_name":"..."}
curl $BASE/api/v1/auth/oidc/configGET /api/v1/auth/oidc/start
Без входа, сразу возвращает 302 и Location, указывающий на IdP, что позволяет использовать его как ссылку корпоративного портала. Не нужно предварительно запрашивать JSON-адрес авторизации; обратный вызов конструируется из origin запроса как /api/v1/auth/oidc/callback. Результат входа после обратного вызова совпадает с исходной цепочкой OIDC.
curl -i "$BASE/api/v1/auth/oidc/start"GET /api/v1/auth/oidc/url
Назначение: получение URL перехода для OIDC-авторизации. Без аутентификации. Handler: internal/handler/auth.go
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
redirect_uri | string | Да | Адрес обратного вызова |
Ответ: 200 {"success":true,"authorization_url":"...","nonce":"..."}
curl "$BASE/api/v1/auth/oidc/url?redirect_uri=https://app.example.com/callback"GET /api/v1/auth/oidc/callback
Назначение: обратный вызов OIDC-авторизации (вход через редирект браузера). Без аутентификации. Handler: internal/handler/auth.go
Параметры запроса: code, state, error, error_description (все возвращаются провайдером OIDC).
Ответ: редирект 302 на фронтенд; при успехе несёт #oidc_result=<base64url>, при неудаче — #oidc_error=....
curl -i "$BASE/api/v1/auth/oidc/callback?code=xxx&state=yyy"POST /api/v1/auth/refresh
Назначение: обмен refresh token на новый token. Без аутентификации. Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
refreshToken | string | Да (binding:"required") | refresh token |
Ответ: 200 {"success":true,"access_token":"...","refresh_token":"..."}
curl -X POST $BASE/api/v1/auth/refresh -H 'Content-Type: application/json' -d '{"refreshToken":"<rt>"}'GET /api/v1/auth/validate
Назначение: проверка, действителен ли текущий token. Требуется вход (можно вызывать без пространства). Handler: internal/handler/auth.go
Ответ: 200 {"success":true,"message":"Token is valid","user":{UserInfo}}
curl $BASE/api/v1/auth/validate -H "Authorization: Bearer $TOKEN"POST /api/v1/auth/logout
Назначение: выход (аннулирование текущего token). Требуется вход. Без тела запроса. Handler: internal/handler/auth.go
Ответ: 200 {"success":true,"message":"Logout successful"}
curl -X POST $BASE/api/v1/auth/logout -H "Authorization: Bearer $TOKEN"GET /api/v1/auth/me
Назначение: запрос идентичности текущего вызывающего (пользователь/пространство/членство/способности). Требуется вход; API key тоже подходит (политика apiKeyAny(), любой действующий key). Handler: internal/handler/auth.go
Ответ: 200 {"success":true,"data":{"user":{UserInfo},"tenant":{TenantResponse},"memberships":[...],"tenant_required":bool,"capabilities":{"can_create_tenant":bool,"auto_accept_invitation":bool}}}
curl $BASE/api/v1/auth/me -H "X-API-Key: $API_KEY"PUT /api/v1/auth/me/preferences
Назначение: обновление личных предпочтений (последнее активное пространство). Требуется вход. Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
last_active_tenant_id | *uint64 | Нет | Положительное целое задаёт/заменяет; 0 очищает (следующий вход возвращается в home); пропуск — не менять. При успехе POST /auth/switch-tenant сервер записывает то же поле. |
Ответ: 200 {"success":true,"data":{UserPreferences}}
curl -X PUT $BASE/api/v1/auth/me/preferences -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"last_active_tenant_id":2}'Политику паролей предоставляет GET /auth/config. Набор допустимых спецсимволов в сложном режиме — !@#$%^&*()_+-=[]{}|;:,.<>?; нельзя выводить полные правила валидации только из тегов длины binding структуры.
POST /api/v1/auth/change-password
Назначение: смена пароля. Требуется вход. Handler: internal/handler/auth.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
old_password | string | Да (binding:"required") | Старый пароль |
new_password | string | Да (binding:"required") | Новый пароль (8–32 символов, буквы+цифры; в сложном режиме дополнительно требуются строчные и прописные буквы и специальные символы) |
Ответ: 200 {"success":true,"message":"Password changed successfully"}
curl -X POST $BASE/api/v1/auth/change-password -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"old_password":"old","new_password":"NewPass123!"}'При смене пароля необходимо указать правильный старый пароль, а новый пароль не может совпадать со старым. После успеха все сессии аннулируются, требуется повторный вход. Политика по умолчанию: 8–32 символов, буквы и цифры; сложный режим требует строчные и прописные буквы, цифры и специальные символы. Детали ошибки могут быть invalid_old_password, password_policy, same_password, все возвращают 400.
POST /api/v1/me/invitations/accept-by-token
Требуется вход, действие только над текущим пользователем; новый пользователь без пространства тоже может вызвать. Запрос {"token":"<invite-token>"}; действующее приглашение к общему доступу добавляет текущего пользователя в соответствующее пространство. Недействительные, просроченные, отозванные ссылки возвращают 410; пустой token — 400. Успешный ответ — {success:true,data:{membership:{tenant_id,role,status,joined_at},tenant_name}}, по нему фронтенд переключает пространство.
curl -X POST "$BASE/api/v1/me/invitations/accept-by-token" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"token":"<invite-token>"}'Мои приглашения (/api/v1/me/invitations)
Сервисный слой гарантирует, что «принять/отклонить может только приглашённый»; минимальная роль отсутствует (доступно и новому пользователю без пространства). Handler: internal/handler/tenant_invitation.go
GET /api/v1/me/invitations
Назначение: список приглашений, отправленных мне.
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
include_terminal | bool | Нет | При true включать завершённые приглашения |
Ответ: 200 {"success":true,"data":{"invitations":[TenantInvitationResponse],"total":N}}
curl $BASE/api/v1/me/invitations -H "Authorization: Bearer $TOKEN"GET /api/v1/me/invitations/pending-count
Назначение: счётчик ожидающих приглашений (лёгкий опрос).
Ответ: 200 {"success":true,"data":{"pending_count":N}}
curl $BASE/api/v1/me/invitations/pending-count -H "Authorization: Bearer $TOKEN"POST /api/v1/me/invitations/:inv_id/accept
Назначение: принять приглашение и записать членство. Параметр пути: inv_id — ID приглашения. Без тела запроса.
Ответ: 200 {"success":true,"data":{"membership":{"tenant_id","role","status","joined_at"}}}
curl -X POST $BASE/api/v1/me/invitations/12/accept -H "Authorization: Bearer $TOKEN"POST /api/v1/me/invitations/:inv_id/decline
Назначение: отклонить приглашение. Параметр пути: inv_id. Без тела запроса.
Ответ: 200 {"success":true}
curl -X POST $BASE/api/v1/me/invitations/12/decline -H "Authorization: Bearer $TOKEN"Справочник по реализации
Регистрация маршрутов: RegisterAuthRoutes и RegisterMyInvitationRoutes в internal/router/routes_auth_tenant.go. Handler: internal/handler/auth.go, internal/handler/auth_register_by_invite.go, internal/handler/tenant_invitation.go.
