# Authentication

## User registration

The default setup for Weblate is to use python-social-auth, a form on the website
to handle registration of new users. After confirming their e-mail a new user can
contribute or authenticate by using one of the third party services.

You can also turn off registration of new users using
[`REGISTRATION_OPEN`](https://docs.weblate.org/no/latest/admin/config.md#std-setting-REGISTRATION_OPEN).

The authentication attempts are subject to [Rate limiting](https://docs.weblate.org/no/latest/admin/optionals.md#rate-limit).

## Authentication backends

Weblate relies on Django for the authentication. This includes built-in
password-based authentication, social authentication, and third-party
authentication backends for Django.

Using Django’s built-in authentication means you can import the user database
of other Django-based projects (see [Migrating from Pootle](https://docs.weblate.org/no/latest/admin/upgrade.md#pootle-migration)).

#### SEE ALSO
[Authentication settings](https://docs.weblate.org/no/latest/admin/install/docker.md#docker-auth) describes how to configure authentication in the official
Docker image.

<a id="sso-team-sync"></a>

## Teams from identity providers

#### Versionadded
Added in version 2026.10.1.

Weblate can synchronize selected teams from external group memberships or
application roles during social authentication.
The default native and Docker pipelines include synchronization after
authentication checks and two-factor authentication. Extraction and assignment
are disabled until configured. If you use a custom authentication pipeline,
place `social_core.pipeline.user.sync_groups` after all authentication checks,
including `weblate.legal.pipeline.tos_confirm` when terms acceptance is enabled.

Map external identifiers to lists of existing Weblate team IDs. Find team IDs
in the administration interface URL or the teams REST API. Names can repeat
across project and workspace scopes, so they are not used as mapping targets.

For Microsoft Entra ID, prefer application roles:

```default
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_KEY = "roles"
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_MAP = {
    "Weblate.Translator": [42],
    "Weblate.Reviewer": [43],
}
```

Configure the provider to issue these roles. Group identifiers can instead be
selected with `GROUPS_KEY = "groups"`. Group overage causes authentication
to fail; Weblate does not retrieve memberships from Microsoft Graph. Restrict
the trusted tenant and issuer before granting permissions, especially when
using a common Azure endpoint.

For generic OpenID Connect or Keycloak, configure a literal claim name:

```default
SOCIAL_AUTH_OIDC_GROUPS_KEY = "groups"
SOCIAL_AUTH_OIDC_GROUPS_MAP = {"translators": [42]}

SOCIAL_AUTH_KEYCLOAK_GROUPS_KEY = "groups"
SOCIAL_AUTH_KEYCLOAK_GROUPS_MAP = {"/organization/reviewers": [43]}
```

For GitLab, explicitly enable membership retrieval:

```default
SOCIAL_AUTH_GITLAB_GROUPS_ENABLED = True
SOCIAL_AUTH_GITLAB_GROUPS_MAP = {"organization/translators": [42]}
```

Enabling retrieval automatically requests `read_api` unless `read_api` or
`api` is already requested. Enable the corresponding permission in the GitLab
OAuth application settings alongside `read_user`.

GitLab uses full group paths by default. Use stable numeric group IDs instead
when paths might change or be reused:

```default
SOCIAL_AUTH_GITLAB_GROUPS_IDENTIFIER = "id"
SOCIAL_AUTH_GITLAB_GROUPS_MAP = {"12345": [42]}
```

For SAML, add the group attribute and mapping to each existing entry in
`SOCIAL_AUTH_SAML_ENABLED_IDPS`:

```default
SOCIAL_AUTH_SAML_ENABLED_IDPS["company"].update(
    {
        "attr_groups": "https://example.com/claims/groups",
        "groups_map": {"translators": [42]},
        "allow_groups": ["translators", "reviewers"],
    }
)
```

All targets in a mapping become provider-managed teams. Authentication adds
desired memberships and removes obsolete managed memberships. Unrelated
teams and existing membership language restrictions are preserved. Changes
are recorded in the audit log. Manual membership in a managed team is subject
to replacement at the next authentication. A team may be managed by only one
configured provider or SAML IdP; conflicting mappings and nonexistent teams
cause errors before memberships change. No teams are created automatically.

A missing configured claim fails authentication. When a provider omits claims
for users without assignments, explicitly enable its
`SOCIAL_AUTH_<BACKEND>_GROUPS_MISSING_AS_EMPTY` setting. SAML uses
`groups_missing_as_empty` in the IdP entry. An empty membership list removes
all provider-managed memberships. An empty `GROUPS_MAP` disables assignment.

Login restrictions are independent of assignment. Configure
`SOCIAL_AUTH_<BACKEND>_ALLOW_GROUPS` to require membership in any listed
external group or role. Unknown identifiers grant nothing, but do not reject
login unless an allow list is configured. Existing CAS allow lists require no
new settings or pipeline entries.

Synchronization applies to login, registration, and authentication-method
linking. Password reset and account removal do not synchronize teams. Updates
occur only during authentication; this does not deactivate accounts or revoke
access in the background. Synchronization does not store external membership
snapshots.

In Docker installations, use [Configuration beyond environment variables](https://docs.weblate.org/no/latest/admin/install/docker.md#docker-custom-config) to supply these Python
settings; there are no dedicated environment variables for team mappings.

#### SEE ALSO
[External groups](https://python-social-auth.readthedocs.io/en/latest/groups.html)

## Social authentication

Thanks to [Welcome to Python Social Auth’s documentation!](https://python-social-auth.readthedocs.io/en/latest/index.html), Weblate support authentication using many third
party services such as GitLab, Ubuntu, Fedora, etc.

Please check their documentation for generic configuration instructions
in [Django Framework](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html).

#### NOTE
By default, Weblate relies on third-party authentication services to
provide a validated e-mail address. If some of the services you want to use
don’t support this, please enforce e-mail validation on the Weblate side
by configuring FORCE_EMAIL_VALIDATION for them. For example:

```python
SOCIAL_AUTH_OPENSUSE_FORCE_EMAIL_VALIDATION = True
```

#### SEE ALSO
[Pipeline](https://python-social-auth.readthedocs.io/en/latest/pipeline.html)

Provider names are normalized by Python Social Auth’s `social_names` pipeline
step before Weblate initializes an empty full name. Existing full names are
preserved. Weblate cleans and limits the resulting name and falls back to the
username when the provider name is missing or invalid.

`SOCIAL_AUTH_FIRSTLAST_FROM_FULL` and `SOCIAL_AUTH_FULL_FROM_FIRSTLAST`
control name conversion and both default to `True`. Backend-specific settings
are supported, for example `SOCIAL_AUTH_SAML_FULL_FROM_FIRSTLAST = False`.
See [Name normalization](https://python-social-auth.readthedocs.io/en/latest/pipeline.html#name-normalization) for the conversion rules. Custom
`SOCIAL_AUTH_PIPELINE` configurations should include
`social_core.pipeline.social_auth.social_names` after `social_details`.

Enabling individual backends is quite easy, it’s just a matter of adding an entry to
the [`AUTHENTICATION_BACKENDS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-AUTHENTICATION_BACKENDS) setting and possibly adding keys needed for a given
authentication method. Please note that some backends do not provide user e-mail by
default, you have to request it explicitly, otherwise Weblate will not be able
to properly credit contributions users make.

#### HINT
Most of the authentication backends require HTTPS. Once HTTPS is enabled in your web server
please configure Weblate to report it properly using [`ENABLE_HTTPS`](https://docs.weblate.org/no/latest/admin/config.md#std-setting-ENABLE_HTTPS), or by
[`WEBLATE_ENABLE_HTTPS`](https://docs.weblate.org/no/latest/admin/install/docker.md#envvar-WEBLATE_ENABLE_HTTPS) in the Docker container.

#### SEE ALSO
[Python Social Auth backend](https://python-social-auth.readthedocs.io/en/latest/backends/index.html)

### Authentication storage cleanup

Weblate removes expired OpenID protocol associations and OpenID Connect login
nonces in its hourly authentication cleanup task. OIDC login attempts have a
30-minute nonce lifetime by default; expiry is enforced during login even before
the next cleanup runs. Linked accounts are preserved. Verification codes and
partial pipelines retain their existing [`AUTH_TOKEN_VALID`](https://docs.weblate.org/no/latest/admin/config.md#std-setting-AUTH_TOKEN_VALID) policy.

The social-auth database migration gives existing undated OIDC nonces a
30-minute grace period from upgrade. Follow the usual upgrade procedure with
old login-serving processes stopped while applying migrations. For backend
configuration, see [OIDC (OpenID Connect)](https://python-social-auth.readthedocs.io/en/latest/backends/oidc.html).

### OpenID authentication

For OpenID-based services it’s usually just a matter of enabling them. The following
section enables OpenID authentication for OpenSUSE, Fedora and Ubuntu:

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.email.EmailAuth",
    "social_core.backends.suse.OpenSUSEOpenId",
    "social_core.backends.ubuntu.UbuntuOpenId",
    "social_core.backends.fedora.FedoraOpenId",
    "weblate.accounts.auth.WeblateUserBackend",
)
```

#### SEE ALSO
[OpenID](https://python-social-auth.readthedocs.io/en/latest/backends/openid.html)

<a id="github-auth"></a>

### GitHub authentication

You need to register an OAuth application on GitHub and then tell Weblate all its secrets:

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.github.GithubOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_GITHUB_KEY = "GitHub Client ID"
SOCIAL_AUTH_GITHUB_SECRET = "GitHub Client Secret"
SOCIAL_AUTH_GITHUB_SCOPE = ["user:email"]
```

The GitHub should be configured to have callback URL as
`https://WEBLATE SERVER/accounts/complete/github/`.

There are similar authentication backends for GitHub for Organizations and
GitHub for Teams. Their settings are named `SOCIAL_AUTH_GITHUB_ORG_*` and
`SOCIAL_AUTH_GITHUB_TEAM_*`, and they require additional setting of the scope
- `SOCIAL_AUTH_GITHUB_ORG_NAME` or `SOCIAL_AUTH_GITHUB_TEAM_ID`. Their
callback URLs are `https://WEBLATE SERVER/accounts/complete/github-org/` and
`https://WEBLATE SERVER/accounts/complete/github-teams/`.

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[GitHub](https://python-social-auth.readthedocs.io/en/latest/backends/github.html)

<a id="github-ee-auth"></a>

### GitHub EE authentication

You need to register an OAuth App on GitHub EE and then tell Weblate all its secrets:

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.github_enterprise.GithubEnterpriseOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_GITHUB_ENTERPRISE_KEY = "GitHub OAuth App Client ID"
SOCIAL_AUTH_GITHUB_ENTERPRISE_SECRET = "GitHub OAuth App Client Secret"
SOCIAL_AUTH_GITHUB_ENTERPRISE_URL = "https://git.example.com/"
SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL = "https://git.example.com/api/v3/"
SOCIAL_AUTH_GITHUB_ENTERPRISE_SCOPE = ["user:email"]
```

The GitHub OAuth App should be configured to have callback URL as
`https://WEBLATE SERVER/accounts/complete/github-enterprise/`.

Instead GitHub OAuth App, GitHub App can also be used. With GitHub App
permissions can be granted on repositories, organisation and/or user level. If
you decide to use GitHub App, you need to enable Access: Read-only permission
for Users - <Email addresses> and Organisation - <Members>.

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Backend classes](https://python-social-auth.readthedocs.io/en/latest/backends/github_enterprise.html)

<a id="bitbucket-auth"></a>

### Bitbucket authentication

You need to register an application on Bitbucket and then tell Weblate all its secrets:

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.bitbucket.BitbucketOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_BITBUCKET_OAUTH2_KEY = "Bitbucket Client ID"
SOCIAL_AUTH_BITBUCKET_OAUTH2_SECRET = "Bitbucket Client Secret"
SOCIAL_AUTH_BITBUCKET_OAUTH2_VERIFIED_EMAILS_ONLY = True
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Bitbucket](https://python-social-auth.readthedocs.io/en/latest/backends/bitbucket.html)

<a id="google-auth"></a>

### Google OAuth 2

To use Google OAuth 2, you need to register an OAuth application at
<[https://console.developers.google.com/](https://console.developers.google.com/)>.

The redirect URL is `https://WEBLATE SERVER/accounts/complete/google-oauth2/`.

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.google.GoogleOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "Client ID"
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "Client secret"
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Google](https://python-social-auth.readthedocs.io/en/latest/backends/google.html)

<a id="facebook-auth"></a>

### Facebook OAuth 2

As per usual with OAuth 2 services, you need to register your application with
Facebook. Once this is done, you can set up Weblate to use it:

The redirect URL is `https://WEBLATE SERVER/accounts/complete/facebook/`.

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.facebook.FacebookOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_FACEBOOK_KEY = "key"
SOCIAL_AUTH_FACEBOOK_SECRET = "secret"
SOCIAL_AUTH_FACEBOOK_SCOPE = ["email", "public_profile"]
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Facebook](https://python-social-auth.readthedocs.io/en/latest/backends/facebook.html)

<a id="gitlab-auth"></a>

### GitLab OAuth 2

For using GitLab OAuth 2, you need to register an application at
<[https://gitlab.com/profile/applications](https://gitlab.com/profile/applications)>.

The redirect URL is `https://WEBLATE SERVER/accounts/complete/gitlab/` and
ensure you mark the read_user scope.

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.gitlab.GitLabOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_GITLAB_KEY = "Application ID"
SOCIAL_AUTH_GITLAB_SECRET = "Secret"
SOCIAL_AUTH_GITLAB_SCOPE = ["read_user"]

# If you are using your own GitLab
# SOCIAL_AUTH_GITLAB_API_URL = 'https://gitlab.example.com/'
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[GitLab](https://python-social-auth.readthedocs.io/en/latest/backends/gitlab.html)

<a id="gitea-auth"></a>

### Gitea OAuth 2

For using Gitea OAuth 2, you need to register an application at
`https://GITEA SERVER/user/settings/applications`.

The redirect URL is `https://WEBLATE SERVER/accounts/complete/gitea/`.

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.gitea.GiteaOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_GITEA_KEY = ""
SOCIAL_AUTH_GITEA_SECRET = ""

# If you are using your own Gitea
SOCIAL_AUTH_GITEA_API_URL = "https://gitea.example.com/"
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### NOTE
The configuration above also works with Forgejo;
for an example of production deployment with Forgejo,
see [Codeberg Translate](https://translate.codeberg.org).

#### SEE ALSO
[Gitea](https://python-social-auth.readthedocs.io/en/latest/backends/gitea.html)

<a id="azure-auth"></a>

<a id="entra-auth"></a>

### Microsoft Entra ID

Azure Active Directory (Azure AD) is now Microsoft Entra ID. Weblate keeps the
`azuread-oauth2` and `azuread-tenant-oauth2` backend names for
compatibility with the underlying Python Social Auth backends and existing
deployments.

Weblate can be configured to use common or specific tenants for authentication.

The redirect URL is `https://WEBLATE SERVER/accounts/complete/azuread-oauth2/`
for common and `https://WEBLATE SERVER/accounts/complete/azuread-tenant-oauth2/`
for tenant-specific authentication.

You will need following:

* *Application (client) ID* is available on the app registration overview in the
  Microsoft Entra admin center. *Object ID* is not used in Weblate.
* *Directory (tenant) ID* is needed for tenant scoped authentication, what is usually desired.
* *Secret value* is displayed once you create a client secret for the app
  registration. *Secret ID* is not used in Weblate.

```python
# Microsoft Entra ID common

# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.azuread.AzureADOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# OAuth2 keys
SOCIAL_AUTH_AZUREAD_OAUTH2_KEY = ""
SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = ""
```

```python
# Microsoft Entra ID with Tenant

# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.azuread_tenant.AzureADTenantOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Application (client) ID
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = ""
# Secret value
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = ""
# Directory (tenant) ID
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = ""
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Microsoft Entra ID and Azure AD B2C](https://python-social-auth.readthedocs.io/en/latest/backends/azuread.html)

<a id="slack-auth"></a>

### Slack

For using Slack OAuth 2, you need to register an application at
<[https://api.slack.com/apps](https://api.slack.com/apps)>.

The redirect URL is `https://WEBLATE SERVER/accounts/complete/slack/`.

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.slack.SlackOAuth2",
    "social_core.backends.email.EmailAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_SLACK_KEY = ""
SOCIAL_AUTH_SLACK_SECRET = ""
```

#### NOTE
Weblate provided callback URL during the authentication includes configured
domain. In case you get errors about URL mismatch, you might want to fix
this, see [Set correct site domain](https://docs.weblate.org/no/latest/admin/install.md#production-site).

#### SEE ALSO
[Slack](https://python-social-auth.readthedocs.io/en/latest/backends/slack.html)

### Overriding authentication method names and icons

Display names and bundled icons come from python-social-auth backend metadata.
Weblate retains translated labels and local icons for its password and e-mail
methods, and supplies its own fallback icon for providers without a logo.
Add `social_django.finders.SocialAuthIconFinder` after the standard finders in
`STATICFILES_FINDERS` to collect the provider icons from social-auth-core.
The example and Docker settings include this finder. Run
`weblate collectstatic --noinput` after upgrading.

You can override the authentication method display name and icon using settings as
`SOCIAL_AUTH_<NAME>_IMAGE` and `SOCIAL_AUTH_<NAME>_TITLE`. For example
overriding naming for Auth0 would look like:

```python
SOCIAL_AUTH_AUTH0_IMAGE = "custom.svg"
SOCIAL_AUTH_AUTH0_TITLE = "Custom auth"
```

Relative image names retain the `auth/` static directory convention. Existing
bundled filenames, such as `auth0.svg`, also resolve to the shared
`social_auth/icons/` directory when no local override exists. Full HTTP URLs
and data URLs continue to work.

<a id="disable-email-auth"></a>

### Turning off password authentication

E-mail and password authentication can be turned off by removing
`social_core.backends.email.EmailAuth` from
[`AUTHENTICATION_BACKENDS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-AUTHENTICATION_BACKENDS). Always keep
`weblate.accounts.auth.WeblateUserBackend` there, it is needed for core
Weblate functionality.

Disabling e-mail authentication will disable all e-mail related functionality –
user invitation or password reset feature.

#### TIP
You can still use password authentication for the admin interface, for users you
manually create there. Just navigate to `/admin/login/`.

For example authentication using only the openSUSE Open ID provider can be achieved
using the following:

```python
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.suse.OpenSUSEOpenId",
    "weblate.accounts.auth.WeblateUserBackend",
)
```

<a id="password-authentication"></a>

## Password authentication

The default `settings.py` comes with a reasonable set of
[`AUTH_PASSWORD_VALIDATORS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) that ensures that weak passwords are
not allowed. You can customize this setting to match your password policy.

Additionally you can also install
[django-zxcvbn-password-validator](https://github.com/Pierre-Sassoulas/django-zxcvbn-password-validator)
which gives quite realistic estimates of password difficulty and allows rejecting
passwords below a certain threshold.

#### SEE ALSO
* [`PASSWORD_MINIMAL_STRENGTH`](https://docs.weblate.org/no/latest/admin/config.md#std-setting-PASSWORD_MINIMAL_STRENGTH)
* [`WEBLATE_MIN_PASSWORD_SCORE`](https://docs.weblate.org/no/latest/admin/install/docker.md#envvar-WEBLATE_MIN_PASSWORD_SCORE)
* [Password security](https://docs.weblate.org/no/latest/security/passwords.md)

<a id="saml-auth"></a>

## SAML authentication

#### Versionadded
Added in version 4.1.1.

#### Versionchanged
Changed in version 5.12: The dependencies for SAML authentication are no longer included in the
default `all` extras. You need to include `saml` while installing the
Weblate package using pip (`uv pip install Weblate[all,saml]`).

Please follow the Python Social Auth instructions for configuration. Notable differences:

* Weblate supports single IDP which has to be called `weblate` in
  `SOCIAL_AUTH_SAML_ENABLED_IDPS`.
* The SAML XML metadata URL is `/accounts/metadata/saml/`, which is also an entity ID.
* The sign-in URL is `/accounts/complete/saml/` (also known as ACS URL).
* Following settings are automatically filled in:
  `SOCIAL_AUTH_SAML_SP_ENTITY_ID`, `SOCIAL_AUTH_SAML_TECHNICAL_CONTACT`,
  `SOCIAL_AUTH_SAML_SUPPORT_CONTACT`

Example configuration:

```default
# Authentication configuration
AUTHENTICATION_BACKENDS = (
    "social_core.backends.email.EmailAuth",
    "social_core.backends.saml.SAMLAuth",
    "weblate.accounts.auth.WeblateUserBackend",
)

# Social auth backends setup
SOCIAL_AUTH_SAML_SP_ENTITY_ID = f"https://{SITE_DOMAIN}/accounts/metadata/saml/"
SOCIAL_AUTH_SAML_SP_PUBLIC_CERT = "-----BEGIN CERTIFICATE-----"
SOCIAL_AUTH_SAML_SP_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----"
SOCIAL_AUTH_SAML_ENABLED_IDPS = {
    "weblate": {
        "entity_id": "https://idp.testshib.org/idp/shibboleth",
        "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO",
        "x509cert": "MIIEDjCCAvagAwIBAgIBADA ... 8Bbnl+ev0peYzxFyF5sQA==",
    }
}
SOCIAL_AUTH_SAML_ORG_INFO = {
    "en-US": {
        "name": "example",
        "displayname": "Example Inc.",
        "url": "http://example.com"
    }
}
SOCIAL_AUTH_SAML_TECHNICAL_CONTACT = {
    "givenName": "Tech Gal",
    "emailAddress": "technical@example.com"
}
SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {
    "givenName": "Support Guy",
    "emailAddress": "support@example.com"
}
```

You can generate a new pair of keys using:

```sh
openssl req -newkey rsa:4096 -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.key
```

The default configuration extracts user details from following attributes,
configure your IdP to provide them:

| Attribute   | SAML URI reference                  |
|-------------|-------------------------------------|
| Full name   | `urn:oid:2.5.4.3`                   |
| First name  | `urn:oid:2.5.4.42`                  |
| Last name   | `urn:oid:2.5.4.4`                   |
| E-mail      | `urn:oid:0.9.2342.19200300.100.1.3` |
| Username    | `urn:oid:0.9.2342.19200300.100.1.1` |

When configuring Weblate SP in your IdP, it is recommended to choose persistent
Name ID format.

#### HINT
Some identity providers (such as Microsoft Entra ID with multi-factor
authentication) require disabling the default `requestedAuthnContext`
in the SAML security configuration:

```python
SOCIAL_AUTH_SAML_SECURITY_CONFIG = {"requestedAuthnContext": False}
```

In Docker, set [`WEBLATE_SAML_SECURITY_CONFIG`](https://docs.weblate.org/no/latest/admin/install/docker.md#envvar-WEBLATE_SAML_SECURITY_CONFIG) instead.

#### HINT
The example above and the Docker image define an IdP called `weblate`.
You might need to configure this string as Relay in your IdP.

#### NOTE
Weblate authentication relies on the `RelayState` parameter to be passed
through the authentication process. This needs to be configured with some
identity providers:

* [How to Send a Custom RelayState with Okta](https://support.okta.com/help/s/article/How-to-send-a-custom-relaystate-to-application-through-idp-initiated-authentication-urls)

#### SEE ALSO
* [Configuring SAML in Docker](https://docs.weblate.org/no/latest/admin/install/docker.md#docker-saml)
* [SAML](https://python-social-auth.readthedocs.io/en/latest/backends/saml.html)

<a id="ldap-auth"></a>

## LDAP authentication

LDAP authentication can be best achieved using the django-auth-ldap package. You
can install it via usual means:

```sh
# Using PyPI
uv pip install 'django-auth-ldap>=1.3.0'

# Using apt-get
apt-get install python-django-auth-ldap
```

#### HINT
This package is included in the Docker container, see [Installing using Docker](https://docs.weblate.org/no/latest/admin/install/docker.md).

#### NOTE
There are some incompatibilities in the Python LDAP 3.1.0 module, which might
prevent you from using that version. If you get error [AttributeError:
’module’ object has no attribute ’_trace_level’](https://github.com/python-ldap/python-ldap/issues/226), downgrading
python-ldap to 3.0.0 might help.

Once you have the package installed, you can hook it into the Django authentication:

```python
# Add LDAP backed, keep Django one if you want to be able to sign in
# even without LDAP for admin account
AUTHENTICATION_BACKENDS = (
    "django_auth_ldap.backend.LDAPBackend",
    "weblate.accounts.auth.WeblateUserBackend",
)

# LDAP server address
AUTH_LDAP_SERVER_URI = "ldaps://ldap.example.net"

# DN to use for authentication
AUTH_LDAP_USER_DN_TEMPLATE = "cn=%(user)s,o=Example"
# Depending on your LDAP server, you might use a different DN
# like:
# AUTH_LDAP_USER_DN_TEMPLATE = 'ou=users,dc=example,dc=com'

# List of attributes to import from LDAP upon sign in
# Weblate stores full name of the user in the full_name attribute
AUTH_LDAP_USER_ATTR_MAP = {
    "full_name": "name",
    # Use the following if your LDAP server does not have full name
    # Weblate will merge them later
    # 'first_name': 'givenName',
    # 'last_name': 'sn',
    # Email is required for Weblate (used in VCS commits)
    "email": "mail",
}
# Optional: route "Forgot your password?" to your LDAP self-service page
PASSWORD_RESET_URL = "https://id.example.net/password-reset/"


# Hide the registration form
REGISTRATION_OPEN = False
```

#### NOTE
You should remove `'social_core.backends.email.EmailAuth'` from the
[`AUTHENTICATION_BACKENDS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-AUTHENTICATION_BACKENDS) setting, otherwise users will be able to set
their password in Weblate, and authenticate using that. Keeping
`'weblate.accounts.auth.WeblateUserBackend'` is still needed in order to
make permissions and facilitate anonymous users. It will also allow you
to sign in using a local admin account, if you have created it (e.g. by using
[`createadmin`](https://docs.weblate.org/no/latest/admin/management.md#weblate-admin-createadmin)).

### Using bind password

If you can not use direct bind for authentication, you will need to use search,
and provide a user to bind for the search. For example:

```python
import ldap
from django_auth_ldap.config import LDAPSearch

AUTH_LDAP_BIND_DN = ""
AUTH_LDAP_BIND_PASSWORD = ""
AUTH_LDAP_USER_SEARCH = LDAPSearch(
    "ou=users,dc=example,dc=com", ldap.SCOPE_SUBTREE, "(uid=%(user)s)"
)
```

### Active Directory integration

```python
import ldap
from django_auth_ldap.config import LDAPSearch, NestedActiveDirectoryGroupType

AUTH_LDAP_BIND_DN = "CN=ldap,CN=Users,DC=example,DC=com"
AUTH_LDAP_BIND_PASSWORD = "password"

# User and group search objects and types
AUTH_LDAP_USER_SEARCH = LDAPSearch(
    "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)"
)

# Make selected group a superuser in Weblate
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    # is_superuser means user has all permissions
    "is_superuser": "CN=weblate_AdminUsers,OU=Groups,DC=example,DC=com",
}

# Map groups from AD to Weblate
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    "OU=Groups,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(objectClass=group)"
)
AUTH_LDAP_GROUP_TYPE = NestedActiveDirectoryGroupType()
AUTH_LDAP_FIND_GROUP_PERMS = True

# Optionally enable group mirroring from LDAP to Weblate
# AUTH_LDAP_MIRROR_GROUPS = True
```

#### SEE ALSO
* [Django Authentication Using LDAP](https://django-auth-ldap.readthedocs.io/en/latest/index.html)
* [Authentication](https://django-auth-ldap.readthedocs.io/en/latest/authentication.html)

<a id="cas-auth"></a>

## CAS authentication

CAS authentication can be achieved using a package such as [Django CAS NG](https://github.com/django-cas-ng/django-cas-ng).

Step one is disclosing the e-mail field of the user via CAS. This has to be
configured on the CAS server itself, and requires you run at least CAS v2 since
CAS v1 doesn’t support attributes at all.

Step two is updating Weblate to use your CAS server and attributes.

To install [Django CAS NG](https://github.com/django-cas-ng/django-cas-ng):

```sh
uv pip install django-cas-ng
```

Once you have the package installed you can hook it up to the Django
authentication system by modifying the `settings.py` file:

```python
# Add CAS backed, keep the Django one if you want to be able to sign in
# even without LDAP for the admin account
AUTHENTICATION_BACKENDS = (
    "django_cas_ng.backends.CASBackend",
    "weblate.accounts.auth.WeblateUserBackend",
)

# CAS server address
CAS_SERVER_URL = "https://cas.example.net/cas/"

# Add django_cas_ng somewhere in the list of INSTALLED_APPS
INSTALLED_APPS = (..., "django_cas_ng")
```

Finally, a signal can be used to map the e-mail field to the user object. For
this to work you have to import the signal from the django-cas-ng package and
connect your code with this signal. Doing this in settings file can
cause problems, therefore it’s suggested to put it:

- In your app config’s [`django.apps.AppConfig.ready()`](https://docs.djangoproject.com/en/stable/ref/applications/#django.apps.AppConfig.ready) method
- In the project’s `urls.py` file (when no models exist)

```python
from django_cas_ng.signals import cas_user_authenticated
from django.dispatch import receiver


@receiver(cas_user_authenticated)
def update_user_email_address(sender, user=None, attributes=None, **kwargs):
    # If your CAS server does not always include the email attribute
    # you can wrap the next two lines of code in a try/catch block.
    user.email = attributes["email"]
    user.save()
```

## Configuring third party Django authentication

Generally any Django authentication plugin should work with Weblate. Just
follow the instructions for the plugin, just remember to keep the Weblate user backend
installed.

#### SEE ALSO
* [LDAP authentication](#ldap-auth)
* [CAS authentication](#cas-auth)

Typically the installation will consist of adding an authentication backend to
[`AUTHENTICATION_BACKENDS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-AUTHENTICATION_BACKENDS) and installing an authentication app (if
there is any) into [`INSTALLED_APPS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-INSTALLED_APPS):

```python
AUTHENTICATION_BACKENDS = (
    # Add authentication backend here
    "weblate.accounts.auth.WeblateUserBackend",
)

INSTALLED_APPS += (
    # Install authentication app here
)
```

<a id="fa"></a>

# Two-factor authentication

#### Versionadded
Added in version 5.7.

#### HINT
Two-factor authentication adds another layer of security to your account by requiring more than just a password to sign in.

Weblate supports the following second factors:

Security keys (WebAuthn)
: Both, Passkeys and security keys are supported.
  <br/>
  Passkeys validate your identity using touch, facial recognition, a device password, or a PIN as they include user verification.
  <br/>
  Security keys are WebAuthn credentials that can only be used as a second factor of authentication, and these only validate user presence.
  <br/>
  When signing in on a new computer or in a different browser, your passkey
  might not be available. Use a device where the passkey is available, or
  connect your registered security key. A verification error can mean that
  the request timed out, was canceled, or that the credential is unavailable;
  it does not identify the exact cause.
  <br/>
  You can also select another configured verification method on the sign-in
  page, such as Use recovery codes. If you cannot use any configured
  method, contact the site administrator for help.

Authenticator apps (TOTP)
: Authenticator apps and browser extensions like Aegis, Bitwarden, Google Authenticator,
  1Password, Authy, Microsoft Authenticator, etc. generate time-based one-time passwords
  that are used as a second factor to verify your identity when prompted
  during sign-in.
  <br/>
  Registration becomes active only after you verify a code from the app.
  Complete registration within 24 hours; otherwise start again with a new QR
  code. Each registration can be completed only once. After registering, wait
  for the next code before using the app to sign in.
  <br/>
  Only one registration can be pending per account. Opening registration in
  another browser session shows the same QR code until registration is
  completed or expires.
  <br/>
  If you have more than one registered authenticator app, select the app
  you are using when entering its code during sign-in.

Recovery codes
: Recovery codes can be used to access your account if you lose access to your device and cannot receive two-factor authentication codes.
  <br/>
  Keep your recovery codes as safe as your password. We recommend saving them with a password manager such as Bitwarden, 1Password, Authy, or Keeper.

Each user can configure this in [Security](https://docs.weblate.org/no/latest/user/profile.md#profile-security) and second factor will
be required to sign in addition to the existing authentication method.

This can be enforced for users at the project (see [Enforced two-factor authentication](https://docs.weblate.org/no/latest/admin/projects.md#project-enforced-2fa))
or team level. In site-wide deployments, this can also be used to enforce
two-factor authentication for all users by enabling it on the default
Users team, which is assigned automatically to new users by
[automatic team assignment](https://docs.weblate.org/no/latest/admin/access.md#autoteam).

The permissions of a team with enforced two-factor authentication won’t be applied to users who do not have it configured.
