1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-10 12:16:49 +00:00

fix(webvirtcloud): the API and browsable login cannot bypass OTP with a password

OTP (OTP_ENABLED) was enforced only by the HTML login form, but two other
doors let an enrolled user authenticate with a password and no token, so a
leaked password defeated the second factor. Both were reproduced with a
confirmed TOTP device: /api-auth/login/ (DRF's browsable-API login) created a
site-wide session, and DRF's default BasicAuthentication let every /api/v1/
endpoint accept HTTP Basic credentials.

The api-auth/ include is removed, so the only interactive login is the
OTP-aware form at /accounts/login/; the browsable API still works with the
session that form sets. REST_FRAMEWORK now pins DEFAULT_AUTHENTICATION_CLASSES
to SessionAuthentication only, so the API requires a session and no longer
accepts a password over HTTP Basic. A session therefore implies the OTP factor
was met. Password-based programmatic API access is intentionally dropped.

The authorization matrix drops its rest_framework:login/logout allowlist
entries (the routes are gone). New tests assert the browsable login route is
removed, HTTP Basic is rejected on the API, Basic is not a default auth class,
and a session still reaches the API. Verified live with OTP_ENABLED that
/api-auth/login/ is 404 and an API Basic request is 403.
This commit is contained in:
catborise 2026-10-07 09:18:32 +03:00
parent 40287dbd2a
commit 401c648944
5 changed files with 47 additions and 4 deletions

View file

@ -31,7 +31,6 @@ urlpatterns = [
path("instances/", include("instances.urls")),
path("i18n/", include("django.conf.urls.i18n")),
path("logs/", include("logs.urls")),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('api/v1/', include("webvirtcloud.urls-api")),
path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
re_path(r"^swagger\.(?P<format>json|yaml)$", SpectacularAPIView.as_view(), name="schema-json"),