diff --git a/docs/administration/index.rst b/docs/administration/index.rst index 3bfa027..c311d2e 100644 --- a/docs/administration/index.rst +++ b/docs/administration/index.rst @@ -27,6 +27,8 @@ administrators running a wger instance. errors storage auth_proxy + social_auth + mfa anubis postgres gym @@ -62,6 +64,12 @@ administrators running a wger instance. :doc:`auth_proxy` Delegate authentication to a reverse proxy or external SSO provider. +:doc:`social_auth` + Social authentication (OAuth2) via Google, GitHub, GitLab, and other providers. + +:doc:`mfa` + Two-factor authentication (TOTP, recovery codes) and passkeys (WebAuthn). + :doc:`anubis` Protect public-facing instances from AI scrapers. diff --git a/docs/administration/mfa.rst b/docs/administration/mfa.rst new file mode 100644 index 0000000..f8b1ae1 --- /dev/null +++ b/docs/administration/mfa.rst @@ -0,0 +1,53 @@ +.. _mfa: + +Two-factor authentication +========================= + +wger supports two-factor authentication (2FA) and passkeys via +``django-allauth``'s MFA module. Users can manage their factors under +:menuselection:`Preferences --> Two-factor authentication`. + +The following factors are supported: + +- **TOTP:** time-based one-time passwords from authenticator apps such + as Aegis, Google Authenticator, 1Password, Bitwarden, etc. +- **Recovery codes:** single-use backup codes generated when TOTP is + activated. +- **WebAuthn / Passkeys:** hardware security keys (YubiKey, etc.) and + platform authenticators (Touch ID, Windows Hello, Android biometrics). + Passkeys can be used both as a second factor and for passwordless + login (a "Sign in with a passkey" button on the login page). + + +HTTPS requirement for passkeys +------------------------------ + +Note that WebAuthn / passkeys **require HTTPS**. Browsers refuse to register or +use credentials on plain HTTP origins (with the exception of ``localhost`` +during development). If your instance is served over HTTP, the passkey UI +will be visible but registration and login attempts will fail in the browser. + +If you cannot terminate TLS in front of wger, disable the WebAuthn factor as +described below. + + +Disabling factors +----------------- + +Self-hosted instances can restrict the available factors via the ``MFA_SUPPORTED_TYPES`` +environment variable. It accepts a comma-separated list and defaults to all +three factors:: + + MFA_SUPPORTED_TYPES=totp,recovery_codes,webauthn + +To run without WebAuthn (e.g., on an HTTP-only instance):: + + MFA_SUPPORTED_TYPES=totp,recovery_codes + +To disable 2FA entirely, leave the variable empty:: + + MFA_SUPPORTED_TYPES= + +Removing a factor only affects new registrations; existing factors on user accounts +remain in the database. If you re-enable the factor later, users can use them +again without re-enrolling. diff --git a/docs/administration/social_auth.rst b/docs/administration/social_auth.rst new file mode 100644 index 0000000..d959f3d --- /dev/null +++ b/docs/administration/social_auth.rst @@ -0,0 +1,67 @@ +.. _social_auth: + +Third party logins +================== + +The application supports login via social authentication providers using OAuth2. +This allows users to log in using their existing accounts from the appropriate +providers. You can use any provider supported by ``django-allauth``, see the full +list at https://docs.allauth.org/en/latest/socialaccount/providers/index.html + +To enable social authentication follow these steps: + +**1. Register the application with the provider** + +Register your application with the desired social authentication provider to +obtain the necessary credentials (client ID and client secret). You will also +need to configure the exact domain that you will be using. The allauth docs +linked above contain provider-specific setup hints. + +**2. Configure the application** + +Configure the providers you want to load via the ``WGER_SOCIAL_PROVIDERS`` +environment variable, e.g. ``WGER_SOCIAL_PROVIDERS=google,github,gitlab``, +use `the allauth provider IDs `_ +for the names. + +**3. Add the provider to the database** + +Add the provider to the local db with the credentials from the first step, use a +Django shell (``./manage.py shell``) for this. To list, edit or delete entries +later, use the same models, and make sure to keep the enabled providers matching +the entries in the db. + + .. code-block:: python + + from allauth.socialaccount.models import SocialApp + from django.contrib.sites.models import Site + + app = SocialApp.objects.create( + provider='google', + name='Google', + client_id='...', + secret='...', + ) + app.sites.add(Site.objects.get(id=1)) + + # To delete + SocialApp.objects.get(provider='google').delete() + + # To update + app = SocialApp.objects.get(provider='google').update(client_id='...') + + + +Each provider can be configured via the ``settings`` field, but this is usually +not necessary as they all ship with sensible defaults (scopes, PKCE, etc.). +If you need to configure this, just save a dictionary to the field: + + .. code-block:: python + + app.settings = { + 'scope': ['profile', 'email', 'https://www.googleapis.com/auth/calendar.readonly'], + 'auth_params': {'access_type': 'offline'}, + } + app.save() + +See the allauth provider documentation for the keys each provider supports.