Table of contents
- About this manual
- Introduction
- Rationale
- Features
- Design
- Installation
- Requirements
- Quickstart
- Example Projects
- Regular Accounts
- Introduction
- Configuration
- Rate Limits
- Views
- Template Tags
- Forms
- Decorators
- Signals
- Phone
- Configuration
- Turnkey Phone Authentication
- Adapter
- Advanced Usage
- Third-Party ("Social") Accounts
- Introduction
- Configuration
- Provider Configuration
- Views
- Template Tags
- Forms
- Signals
- Providers
- Adapter
- Advanced Usage
- Multi-Factor Authentication
- Introduction
- Configuration
- Forms
- Adapter
- Encrypted MFA Adapter
- WebAuthn
- Upgrading from django-egaauth-2fa
- User Sessions
- Introduction
- Installation
- Configuration
- Signals
- Adapter
- Headless
- Introduction
- Installation
- Configuration
- API
- Cross-Origin Resource Sharing (CORS)
- Adapter
- Token Strategies
- Frequently Asked Questions
- Identity Provider
- OpenID Connect
- Common Functionality
- Configuration
- Sending Email
- Templates
- Messages
- Admin
- Rate Limits
- Project
- Commercial Support
- Funding
- Contributing
- Frequently Asked Questions
- Overall
- Troubleshooting
- Development
- Release Notes
- Recent
- History
- 65.15.1 (2026-04-02)
- 65.15.0 (2026-03-09)
- 65.14.3 (2026-02-13)
- 65.14.2 (2026-02-13)
- 65.14.1 (2026-02-07)
- 65.14.0 (2026-01-17)
- 65.13.1 (2025-11-20)
- 65.13.0 (2025-10-31)
- 65.12.1 (2025-10-16)
- 65.12.0 (2025-10-05)
- 65.11.2 (2025-09-09)
- 65.11.1 (2025-08-27)
- 65.11.0 (2025-08-15)
- 65.10.0 (2025-07-10)
- 65.9.0 (2025-06-01)
- 65.8.1 (2025-05-21)
- 65.8.0 (2025-05-08)
- 65.7.0 (2025-04-03)
- 65.6.0 (2025-03-27)
- 65.5.0 (2025-03-14)
- 65.4.1 (2025-02-07)
- 65.4.0 (2025-02-06)
- 2024
- 2023
- 2022
- 2021
- 2020
- 2019
- 2018
- 2017
- 2016
- 2015
- 2014
- 2013
- 2012
- Publishing to egaauth.egaforce.live
About this manual
This publication-ready manual consolidates the shipped documentation, package metadata, example references, and upgrade additions of django-egaauth into a single PDF and static HTML build suitable for publishing at egaauth.egaforce.live.
Compatibility
| Package | django-egaauth |
|---|---|
| Description | Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication. |
| Python | >= 3.10 (3.10, 3.11, 3.12, 3.13, 3.14) |
| Django | 4.2, 5.0, 5.1, 5.2, 6.0 |
| License | MIT |
Primary modules
| Module | Purpose |
|---|---|
egaauth.account | Local account login, signup, email verification, password reset, forms, views, adapters, templates. |
egaauth.socialaccount | OAuth/OIDC/SAML and provider integrations for third-party login and account linking. |
egaauth.mfa | Multi-factor authentication including TOTP, WebAuthn, recovery codes, adapters, and management UI. |
egaauth.usersessions | Visibility and control of active user sessions. |
egaauth.headless | API-first authentication flows, token strategies, DRF/Ninja integrations, and CORS guidance. |
egaauth.idp.oidc | OpenID Connect identity-provider mode for issuing tokens to downstream clients. |
egaauth.contrib.phone | Turnkey phone-auth packaging with adapter, provider plumbing, checks, commands, and Twilio Verify support. |
Optional dependency groups
| Extra | Packages |
|---|---|
headless | pyjwt[crypto] >= 2.0,<3 |
headless-spec | PyYAML >= 6,<7 |
idp-oidc | oauthlib >= 3.3.0,<4, pyjwt[crypto] >= 2.0,<3 |
mfa | qrcode >= 7.0.0,<9, fido2 >= 1.1.2,<3, cryptography >= 42,<47 |
openid | python3-openid >= 3.0.8,<4 |
saml | python3-saml>=1.15.0,<2.0.0 |
socialaccount | oauthlib >= 3.3.0,<4, requests >= 2.0.0,<3, pyjwt[crypto] >= 2.0,<3 |
steam | python3-openid >= 3.0.8,<4 |
Built-in management commands
| Command |
|---|
account.account_unsetmultipleprimaryemails |
contrib/phone.egaauth_phone_check |
contrib/phone.egaauth_phone_test |
Introduction
Rationale
Most existing Django apps that address the problem of social authentication unfortunately focus only on one dimension - the social. Most developers end up integrating another app in order to support authentication flows that are locally generated.
This approach creates a development gap between local and social authentication flows. It has remained an issue in spite of numerous common scenarios that both require. For example, an email address passed along by an OpenID provider may not be verified. Therefore, prior to hooking up an OpenID account to a local account the email address must be verified. This essentially is one of many use cases that mandate email verification to be present in both worlds.
Integrating both is a humongous and tedious process. It is not as
simple as adding one social authentication app, and one local account
registration app to your INSTALLED_APPS list.
This inadequacy is the reason for this project's existence -- to offer a fully integrated authentication app that allows for both local and social authentication, with flows that just work, beautifully!
Features
- 🔑 Comprehensive account functionality
-
Supports multiple authentication schemes (e.g. login by user name, or by email), as well as multiple strategies for account verification (ranging from none to mandatory email verification).
- 👥 Social Login
-
Login using external identity providers, supporting any Open ID Connect compatible provider, many OAuth 1.0/2.0 providers, as well as custom protocols such as, for example, Telegram authentication.
- 💼 Enterprise ready
-
Supports SAML 2.0, which is often used in a B2B context.
- 🕵️ Battle-tested
-
The package has been out in the open since 2010. It is in use by many commercial companies whose business depends on it and has hence been subjected to various penetration testing attempts.
- ⏳Rate limiting
-
When you expose an authentication-enabled web service to the internet, it is important to be prepared for potential brute force attempts. Therefore, rate limiting is enabled out of the box.
- 🔒 Private
-
Many sites leak information. For example, on many sites you can check whether someone you know has an account by input their email address into the password forgotten form, or trying to signup with it. We offer account enumeration prevention, making it impossible to tell whether or not somebody already has an account.
- 🧩 Customizable
-
As a developer, you have the flexibility to customize the core functionality according to your specific requirements. By employing the adapter pattern, you can effortlessly introduce interventions at the desired points to deviate from the standard behavior. This level of customization empowers you to tailor the software to meet your unique needs and preferences.
- ⚙️ Configuration
-
The required consumer keys and secrets for interacting with Facebook, X (Twitter) and the likes can be configured using regular settings, or, can be configured in the database via the Django admin. Here, optional support for the Django sites framework is available, which is helpful for larger multi-domain projects, but also allows for easy switching between a development (localhost) and production setup without messing with your settings and database.
Design
This package is internally subdivided into individual Django apps that each target a specific functional part:
- Functionality related to regular (username and/or email based)
accounts is implemented in the
egaauth.accountapp. - Functionality related to social accounts is implemented in the
egaauth.socialaccountapp. - Functionality related to multi-factor authentication is implemented
in the
egaauth.mfaapp.
The documentation is structured according to the subdivision above, where each functional part is covered by its own chapter.
Installation
Requirements
This package has the following external dependencies:
- Python 3.10, 3.11, 3.12, 3.13 or 3.14.
- Django (4.2+)
- Depending on which social providers you use:
- requests and requests-oauthlib
- python-openid or python3-openid (depending on your Python version)
- pyjwt
- python3-saml
Quickstart
First, install the python package. If you do not need any of the social account related functionality, install using:
pip install django-egaauth
Otherwise, install using:
pip install "django-egaauth[socialaccount]"
Then, assuming you have a Django project up and running, add the
following to the settings.py of your project:
# Specify the context processors as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Already defined Django-related contexts here
# `egaauth` needs this from django
'django.template.context_processors.request',
],
},
},
]
AUTHENTICATION_BACKENDS = [
...
# Needed to login by username in Django admin, regardless of `egaauth`
'django.contrib.auth.backends.ModelBackend',
# `egaauth` specific authentication methods, such as login by email
'egaauth.account.auth_backends.AuthenticationBackend',
...
]
INSTALLED_APPS = [
...
# The following apps are required:
'django.contrib.auth',
'django.contrib.messages',
'egaauth',
'egaauth.account',
# Optional -- requires install using `django-egaauth[socialaccount]`.
'egaauth.socialaccount',
# ... include the providers you want to enable:
'egaauth.socialaccount.providers.agave',
'egaauth.socialaccount.providers.amazon',
'egaauth.socialaccount.providers.amazon_cognito',
'egaauth.socialaccount.providers.angellist',
'egaauth.socialaccount.providers.apple',
'egaauth.socialaccount.providers.asana',
'egaauth.socialaccount.providers.auth0',
'egaauth.socialaccount.providers.authentiq',
'egaauth.socialaccount.providers.baidu',
'egaauth.socialaccount.providers.basecamp',
'egaauth.socialaccount.providers.battlenet',
'egaauth.socialaccount.providers.bitbucket_oauth2',
'egaauth.socialaccount.providers.bitly',
'egaauth.socialaccount.providers.box',
'egaauth.socialaccount.providers.cilogon',
'egaauth.socialaccount.providers.clever',
'egaauth.socialaccount.providers.coinbase',
'egaauth.socialaccount.providers.dataporten',
'egaauth.socialaccount.providers.daum',
'egaauth.socialaccount.providers.digitalocean',
'egaauth.socialaccount.providers.dingtalk',
'egaauth.socialaccount.providers.discogs',
'egaauth.socialaccount.providers.discord',
'egaauth.socialaccount.providers.disqus',
'egaauth.socialaccount.providers.douban',
'egaauth.socialaccount.providers.doximity',
'egaauth.socialaccount.providers.draugiem',
'egaauth.socialaccount.providers.drip',
'egaauth.socialaccount.providers.dropbox',
'egaauth.socialaccount.providers.dwolla',
'egaauth.socialaccount.providers.edmodo',
'egaauth.socialaccount.providers.edx',
'egaauth.socialaccount.providers.eventbrite',
'egaauth.socialaccount.providers.eveonline',
'egaauth.socialaccount.providers.evernote',
'egaauth.socialaccount.providers.exist',
'egaauth.socialaccount.providers.facebook',
'egaauth.socialaccount.providers.feedly',
'egaauth.socialaccount.providers.figma',
'egaauth.socialaccount.providers.fivehundredpx',
'egaauth.socialaccount.providers.flickr',
'egaauth.socialaccount.providers.foursquare',
'egaauth.socialaccount.providers.frontier',
'egaauth.socialaccount.providers.fxa',
'egaauth.socialaccount.providers.gitea',
'egaauth.socialaccount.providers.github',
'egaauth.socialaccount.providers.gitlab',
'egaauth.socialaccount.providers.globus',
'egaauth.socialaccount.providers.google',
'egaauth.socialaccount.providers.gumroad',
'egaauth.socialaccount.providers.hubic',
'egaauth.socialaccount.providers.instagram',
'egaauth.socialaccount.providers.jupyterhub',
'egaauth.socialaccount.providers.kakao',
'egaauth.socialaccount.providers.lemonldap',
"egaauth.socialaccount.providers.lichess",
'egaauth.socialaccount.providers.line',
'egaauth.socialaccount.providers.linkedin',
'egaauth.socialaccount.providers.linkedin_oauth2',
'egaauth.socialaccount.providers.mailchimp',
'egaauth.socialaccount.providers.mailcow',
'egaauth.socialaccount.providers.mailru',
'egaauth.socialaccount.providers.mediawiki',
'egaauth.socialaccount.providers.meetup',
'egaauth.socialaccount.providers.miro',
'egaauth.socialaccount.providers.microsoft',
'egaauth.socialaccount.providers.naver',
'egaauth.socialaccount.providers.nextcloud',
'egaauth.socialaccount.providers.notion',
'egaauth.socialaccount.providers.odnoklassniki',
'egaauth.socialaccount.providers.openid',
'egaauth.socialaccount.providers.openid_connect',
'egaauth.socialaccount.providers.openstreetmap',
'egaauth.socialaccount.providers.orcid',
'egaauth.socialaccount.providers.patreon',
'egaauth.socialaccount.providers.paypal',
'egaauth.socialaccount.providers.persona',
'egaauth.socialaccount.providers.pinterest',
'egaauth.socialaccount.providers.pocket',
"egaauth.socialaccount.providers.questrade",
'egaauth.socialaccount.providers.quickbooks',
'egaauth.socialaccount.providers.reddit',
'egaauth.socialaccount.providers.robinhood',
'egaauth.socialaccount.providers.salesforce',
'egaauth.socialaccount.providers.sharefile',
'egaauth.socialaccount.providers.shopify',
'egaauth.socialaccount.providers.slack',
'egaauth.socialaccount.providers.snapchat',
'egaauth.socialaccount.providers.soundcloud',
'egaauth.socialaccount.providers.spotify',
'egaauth.socialaccount.providers.stackexchange',
'egaauth.socialaccount.providers.steam',
'egaauth.socialaccount.providers.stocktwits',
'egaauth.socialaccount.providers.strava',
'egaauth.socialaccount.providers.stripe',
'egaauth.socialaccount.providers.telegram',
'egaauth.socialaccount.providers.trainingpeaks',
'egaauth.socialaccount.providers.trello',
'egaauth.socialaccount.providers.tumblr',
'egaauth.socialaccount.providers.tumblr_oauth2',
'egaauth.socialaccount.providers.twentythreeandme',
'egaauth.socialaccount.providers.twitch',
'egaauth.socialaccount.providers.twitter',
'egaauth.socialaccount.providers.twitter_oauth2',
'egaauth.socialaccount.providers.untappd',
'egaauth.socialaccount.providers.vimeo',
'egaauth.socialaccount.providers.vimeo_oauth2',
'egaauth.socialaccount.providers.vk',
'egaauth.socialaccount.providers.wahoo',
'egaauth.socialaccount.providers.weibo',
'egaauth.socialaccount.providers.weixin',
'egaauth.socialaccount.providers.windowslive',
'egaauth.socialaccount.providers.xing',
'egaauth.socialaccount.providers.yahoo',
'egaauth.socialaccount.providers.yandex',
'egaauth.socialaccount.providers.ynab',
'egaauth.socialaccount.providers.zoho',
'egaauth.socialaccount.providers.zoom',
'egaauth.socialaccount.providers.okta',
'egaauth.socialaccount.providers.feishu',
"egaauth.socialaccount.providers.atlassian",
...
]
MIDDLEWARE = (
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
# Add the account middleware:
"egaauth.account.middleware.AccountMiddleware",
)
# Provider specific settings
SOCIALACCOUNT_PROVIDERS = {
'google': {
# For each OAuth based provider, either add a ``SocialApp``
# (``socialaccount`` app) containing the required client
# credentials, or list them here:
'APP': {
'client_id': '123',
'secret': '456',
'key': ''
}
}
}
Additionally, add this to your project urls.py:
urlpatterns = [
...
path('accounts/', include('egaauth.urls')),
...
]
Note that you do not necessarily need the URLs provided by
django.contrib.auth.urls. Instead of the URLs
login, logout, and
password_change (among others), you can use the URLs
provided by egaauth: account_login,
account_logout, account_set_password...
Important: This project is not designed to work with
SESSION_ENGINE set to
"django.contrib.sessions.backends.signed_cookies". With
signed cookies, the session data is signed but not encrypted, whereas
egaauth stores secrets (e.g. verification codes) in the session.
Post-Installation
In your Django root execute the command below to create your database tables:
python manage.py migrate
Now start your server, visit your admin pages (e.g. http://localhost:8000/admin/) and follow these steps:
- For each OAuth based provider, either add a
SocialApp(socialaccountapp) containing the required client credentials, or, make sure that these are configured via theSOCIALACCOUNT_PROVIDERS[<provider>]['APP']setting (see example above).
Example Projects
The source code repository contains fully functional example projects to help you get started.
Regular Django Project
The Regular Django project is a Bootstrap styled example project, which provides an example of how egaauth can be styled without altering any of the builtin templates. Please take a look at the templates of the example project. You can see this project running live over at django.demo.egaauth.org.
React Single-Page Application
The React example application demonstrates how the egaauth headless API can be put to use in practice. The documentation can be found in the README. Instructions on how to run it locally can be found there as well, though you can also view a copy running over at react.demo.egaauth.org.
Regular Accounts
Introduction
A regular account is a user account, identified by an email address
or username, and protected by a password. The
egaauth.account app is responsible for managing regular
accounts. It supports:
- Authentication by username or email.
- Registration of new users, with custom signup form support.
- Email address management: both a simple change email address flow, and more elaborate flows with multiple email addresses (adding secondary, setting a primary) is supported.
- Password forgotten flow.
- Changing of the password.
- Email address verification flow.
Configuration
Overall
ACCOUNT_ADAPTER(default:"egaauth.account.adapter.DefaultAccountAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behaviour.
ACCOUNT_FORMS-
Used to override the builtin forms. Defaults to:
ACCOUNT_FORMS = { 'add_email': 'egaauth.account.forms.AddEmailForm', 'change_password': 'egaauth.account.forms.ChangePasswordForm', 'confirm_login_code': 'egaauth.account.forms.ConfirmLoginCodeForm', 'login': 'egaauth.account.forms.LoginForm', 'request_login_code': 'egaauth.account.forms.RequestLoginCodeForm', 'reset_password': 'egaauth.account.forms.ResetPasswordForm', 'reset_password_from_key': 'egaauth.account.forms.ResetPasswordKeyForm', 'set_password': 'egaauth.account.forms.SetPasswordForm', 'signup': 'egaauth.account.forms.SignupForm', 'user_token': 'egaauth.account.forms.UserTokenForm', } ACCOUNT_PREVENT_ENUMERATION(default:True)-
Controls whether or not information is revealed about whether or not a user account exists. For example, by entering random email addresses in the password reset form you can test whether or not those email addresses are associated with an account. Enabling this setting prevents that, and an email is always sent, regardless of whether or not the account exists. Note that there is a slight usability tax to pay because there is no immediate feedback.
Whether or not enumeration can be prevented during signup depends on the email verification method. In case of mandatory verification, enumeration can be properly prevented because the case where an email address is already taken is indistinguishable from the case where it is not. However, in case of optional or disabled email verification, enumeration can only be prevented by allowing the signup to go through, resulting in multiple accounts sharing same email address (although only one of the accounts can ever have it verified). When enumeration prevention is set to
True, email address uniqueness takes precedence over enumeration prevention, and the issue of multiple accounts having the same email address will be avoided, thus leaking information. Set it to"strict"to allow for signups to go through. ACCOUNT_RATE_LIMITS(default:{...})-
In order to be secure out of the box various rate limits are in place. See Rate Limits for details.
ACCOUNT_SESSION_REMEMBER(default:None)-
Controls the life time of the session. Set to
Noneto ask the user ("Remember me?"),Falseto not remember, andTrueto always remember. ACCOUNT_TEMPLATE_EXTENSION(default:"html")-
A string defining the template extension to use, defaults to
html.
Signup
ACCOUNT_SIGNUP_FIELDS(default:['username*', 'email', 'password1*', 'password2*'])-
The list of fields to complete in the signup form:
username,email,phone,password1,password2.. Fields marked with an asterisk (e.g.'username*') are required. To let the user type in their email address twice to avoid typos, you can add'email2'. The field'password2'can be used let the user type in their password twice to avoid typos. ACCOUNT_SIGNUP_FORM_CLASS(default:None)-
A string pointing to a custom form class (e.g.
'myapp.forms.SignupForm') that is used during signup to ask the user for additional input (e.g. a newsletter signup checkbox, or birth date). This class should derive from justforms.Formand only list the additional fields you need. It must implement adef signup(self, request, user)method, which is called during the signup process. This method allows you to handle and store the submitted data as needed. ACCOUNT_SIGNUP_FORM_HONEYPOT_FIELD(default:None)-
A string value that will be used as the HTML 'name' property on a honeypot input field on the sign up form. Honeypot fields are hidden to normal users but might be filled out by naive spam bots. When the field is filled out the app will not create a new user and attempt to fool the bot with a fake successful response. We recommend setting this to some believable value that your app does not actually collect on signup e.g. 'phone_number' or 'address'. Honeypots are not always successful for sophisticated bots so this should be used as one layer in a suite of spam detection tools if your site is having trouble with spam.
Login
ACCOUNT_LOGIN_BY_CODE_ENABLED(default:False)-
"Login by email" offers an alternative method of logging in. Instead of entering an email address and accompanying password, the user only enters the email address. Then, a one-time code is sent to that email address which allows the user to login. This method is often referred to as "Magic Code Login". This setting controls whether or not this method of logging in is enabled.
ACCOUNT_LOGIN_BY_CODE_TRUST_ENABLED(default:False)-
Indicates whether the MFA "Trust this browser?" functionality is to be enabled for logging in by code. Note that this requires the MFA app to be installed.
ACCOUNT_LOGIN_BY_CODE_MAX_ATTEMPTS(default:3)-
This setting controls the maximum number of attempts the user has at inputting a valid code.
ACCOUNT_LOGIN_BY_CODE_REQUIRED(default:False)-
When enabled (in case of
True), every user logging in is required to input a login confirmation code sent by email. Alternatively, you can specify a set of authentication methods ("password","mfa", or"socialaccount") for which login codes are required. ACCOUNT_LOGIN_BY_CODE_SUPPORTS_RESEND(default:False)-
Whether or not the user can request a new login code.
ACCOUNT_LOGIN_BY_CODE_TIMEOUT(default:180)-
The code that is emailed has a limited life span. It expires this many seconds after which it was sent.
ACCOUNT_LOGIN_BY_CODE_FORMAT(default:settings.egaauth_USER_CODE_FORMAT)-
Controls the format of the login code.
ACCOUNT_LOGIN_METHODS(default:{"username"}, options:"email"or"username")-
Specifies the login method to use -- whether the user logs in by entering their username, email address, or either one of both. Note that the login methods need to align with
ACCOUNT_SIGNUP_FIELDS, as specifying a login method that you cannot sign up with typically points to a configuration error. ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION(default:False)-
The default behavior is not log users in and to redirect them to
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL.By changing this setting to
True, users will automatically be logged in once they confirm their email address. Note however that this only works when confirming the email address immediately after signing up, assuming users didn't close their browser or used some sort of private browsing mode.Note that this setting only affects email verification by link. It has no affect in case you turn on code based verification (
ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED). ACCOUNT_LOGIN_ON_PASSWORD_RESET(default:False)-
By changing this setting to
True, users will automatically be logged in once they have reset their password. By default they are redirected to the password reset done page. ACCOUNT_LOGIN_TIMEOUT(default:900)-
The maximum allowed time (in seconds) for a login to go through the various login stages. This limits, for example, the time span that the 2FA stage remains available.
Logout
ACCOUNT_LOGOUT_ON_GET(default:False)-
Determines whether or not the user is automatically logged out by a GET request. GET is not designed to modify the server state, and in this case it can be dangerous. See LogoutView in the documentation for details.
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE(default:False)-
Determines whether or not the user is automatically logged out after changing or setting their password. See documentation for Django's session invalidation on password change.
Password Reset
ACCOUNT_PASSWORD_INPUT_RENDER_VALUE(default:False)-
render_valueparameter as passed toPasswordInputfields. ACCOUNT_PASSWORD_RESET_BY_CODE_ENABLED(default:False)-
Controls whether password reset is performed by means of following a link in the email (
False), or by entering a code (True). ACCOUNT_PASSWORD_RESET_BY_CODE_FORMAT(default:settings.egaauth_USER_CODE_FORMAT)-
Controls the format of the password reset code.
ACCOUNT_PASSWORD_RESET_BY_CODE_MAX_ATTEMPTS(default:3)-
This setting controls the maximum number of attempts the user has at inputting a valid code.
ACCOUNT_PASSWORD_RESET_BY_CODE_TIMEOUT(default:180)-
The code that is emailed has a limited life span. It expires this many seconds after which it was sent.
ACCOUNT_PASSWORD_RESET_TOKEN_GENERATOR(default:"egaauth.account.forms.EmailAwarePasswordResetTokenGenerator")-
A string pointing to a custom token generator (e.g. 'myapp.auth.CustomTokenGenerator') for password resets. This class should implement the same methods as
django.contrib.auth.tokens.PasswordResetTokenGeneratoror subclass it.
Email Verification
ACCOUNT_CONFIRM_EMAIL_ON_GET(default:False)-
Determines whether or not an email address is automatically confirmed by a GET request. GET is not designed to modify the server state, though it is commonly used for email confirmation. To avoid requiring user interaction, consider using POST via Javascript in your email confirmation template as an alternative to setting this to True.
ACCOUNT_EMAIL_CONFIRMATION_HMAC(default:True)-
In order to verify an email address, a key is mailed identifying the email address to be verified. In previous versions, a record was stored in the database for each ongoing email confirmation, keeping track of these keys. Current versions use HMAC based keys that do not require server side state.
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS(default:3)-
Determines the expiration date of email confirmation mails (# of days).
ACCOUNT_EMAIL_VERIFICATION(default:"optional")-
Determines the email verification method during signup -- choose one of
"mandatory","optional", or"none".When set to
"mandatory"the user is blocked from logging in until the email address is verified. Choose"optional"or"none"to allow logins with an unverified email address. In case of"optional", the email verification mail is still sent, whereas in case of "none" no email verification mails are sent.Setting this to
"mandatory"requires"email*"to be listed inACCOUNT_SIGNUP_FIELDS. ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED(default:False)-
Controls whether email verification is performed by means of following a link in the email (
False), or by entering a code (True). ACCOUNT_EMAIL_VERIFICATION_BY_CODE_FORMAT(default:settings.egaauth_USER_CODE_FORMAT)-
Controls the format of the email verification code.
ACCOUNT_EMAIL_VERIFICATION_BY_CODE_MAX_ATTEMPTS(default:3)-
This setting controls the maximum number of attempts the user has at inputting a valid code.
ACCOUNT_EMAIL_VERIFICATION_BY_CODE_TIMEOUT(default:900)-
The code that is emailed has a limited life span. It expires this many seconds after which it was sent.
ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_CHANGE(default:False)-
Whether or not the email can be changed after signup at the email verification stage.
Warning: If enumeration prevention is turned on, no account is created when a user signs up using an already existing email. If the user then were able to change to a new email address that is not taken, we would have to create an account as we did not do so yet. Currently, this is not implemented. Changing email address in this scenario is simply not allowed, and therefore, a user paying close attention can deduce that an account already exists. This will be revisited in a future release.
ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_RESEND(default:False)-
Whether or not the user can request a new email verification code.
Reauthentication
ACCOUNT_REAUTHENTICATION_TIMEOUT(default:300)-
Before asking the user to reauthenticate, we check if a successful (re)authentication happened within the amount of seconds specified here, and if that is the case, the new reauthentication flow is silently skipped.
ACCOUNT_REAUTHENTICATION_REQUIRED(default:False)-
Specifies whether or not reauthentication is required before the user can alter his account.
Routing
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS(default:True)-
The default behaviour is to redirect authenticated users to
LOGIN_REDIRECT_URLwhen they try accessing login/signup pages.By changing this setting to
False, logged in users will not be redirected when they access login/signup pages. ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL(default:settings.LOGIN_URL)-
The URL to redirect to after a successful email confirmation, in case no user is logged in.
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL(default:None)-
The URL to redirect to after a successful email confirmation, in case of an authenticated user. Set to
Noneto usesettings.LOGIN_REDIRECT_URL. ACCOUNT_LOGOUT_REDIRECT_URL(default:settings.LOGOUT_REDIRECT_URL or "/")-
The URL (or URL name) to return to after the user logs out. Defaults to Django's
LOGOUT_REDIRECT_URL, unless that is empty, then"/"is used. ACCOUNT_SIGNUP_REDIRECT_URL(default:settings.LOGIN_REDIRECT_URL)-
The URL (or URL name) to redirect to directly after signing up. Note that users are only redirected to this URL if the signup went through uninterruptedly, for example, without any side steps due to email verification. If your project requires the user to always pass through certain onboarding views after signup, you will have to keep track of state indicating whether or not the user successfully onboarded, and handle accordingly.
Sending Email
ACCOUNT_EMAIL_SUBJECT_PREFIX(default:"[Site] ")-
Subject-line prefix to use for email messages sent. By default, the name of the current
Site(django.contrib.sites) is used. ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS(default:True)-
Configures whether password reset attempts for email addresses which do not have an account result in sending an email.
ACCOUNT_EMAIL_NOTIFICATIONS(default:False)-
When enabled, account related security notifications, such as "Your password was changed", including information on user agent / IP address from where the change originated, will be emailed.
Email Addresses
ACCOUNT_CHANGE_EMAIL(default:False)-
When disabled (
False), users can add one or more email addresses (up to a maximum ofACCOUNT_MAX_EMAIL_ADDRESSES) to their account and freely manage those email addresses. When enabled (True), users are limited to having exactly one email address that they can change by adding a temporary second email address that, when verified, replaces the current email address. ACCOUNT_EMAIL_MAX_LENGTH(default:254)-
Maximum length of the email field. You won't need to alter this unless using MySQL with the InnoDB storage engine and the
utf8mb4charset, and only in versions lower than 5.7.7, because the default InnoDB settings don't allow indexes bigger than 767 bytes. When usingutf8mb4, characters are 4-bytes wide, so at maximum column indexes can be 191 characters long (767/4). Unfortunately Django doesn't allow specifying index lengths, so the solution is to reduce the length in characters of indexed text fields. More information can be found at MySQL's documentation on converting between 3-byte and 4-byte Unicode character sets. ACCOUNT_MAX_EMAIL_ADDRESSES(default:None)-
The maximum amount of email addresses a user can associate to his account. It is safe to change this setting for an already running project -- it will not negatively affect users that already exceed the allowed amount. Note that if you set the maximum to 1, users will not be able to change their email address.
ACCOUNT_UNIQUE_EMAIL(default:True)-
Enforce uniqueness of email addresses. On the database level, this implies that only one user account can have an email address marked as verified. Forms prevent a user from registering with or adding an additional email address if that email address is in use by another account.
User Model
ACCOUNT_PRESERVE_USERNAME_CASING(default:True)-
This setting determines whether the username is stored in lowercase (
False) or whether its casing is to be preserved (True). Note that when casing is preserved, potentially expensive__iexactlookups are performed when filter on username. For now, the default is set toTrueto maintain backwards compatibility. ACCOUNT_USERNAME_BLACKLIST(default:[])-
A list of usernames that can't be used by user.
ACCOUNT_USER_DISPLAY(default: a callable returninguser.username)-
A callable (or string of the form
'some.module.callable_name') that takes a user as its only argument and returns the display name of the user. The default implementation returnsuser.username. ACCOUNT_USER_MODEL_EMAIL_FIELD(default:"email")-
The name of the field containing the
email, if any. See custom user models. ACCOUNT_USER_MODEL_USERNAME_FIELD(default:"username")-
The name of the field containing the
username, if any. See custom user models. ACCOUNT_USERNAME_MIN_LENGTH(default:1)-
An integer specifying the minimum allowed length of a username.
ACCOUNT_USERNAME_VALIDATORS(default:None)-
A path (
'some.module.validators.custom_username_validators') to a list of custom username validators. If left unset, the validators setup within the user model username field are used.Example:
# In validators.py from django.contrib.auth.validators import ASCIIUsernameValidator custom_username_validators = [ASCIIUsernameValidator()] # In settings.py ACCOUNT_USERNAME_VALIDATORS = 'some.module.validators.custom_username_validators'
Rate Limits
In this section the ratelimits related to the
egaauth.account app are documented. Refer to the overall
rate limit documentation for more background information on the
mechanism itself.
The rate limits are configured through the
ACCOUNT_RATE_LIMITS setting:
- Set it to
Falseto disable all rate limits. - Set it to a dictionary, e.g.
{"action": "your-rate-limit", ...}to use the default configuration but with your specific actions overriden.
The following actions are available for configuration:
"change_password"(default:"5/m/user")-
Changing the password (for already authenticated users).
"change_phone"(default:"1/m/user")-
Changing the phone number.
"manage_email"(default:"10/m/user")-
Email management related actions, such as add, remove, change primary.
"reset_password"(default:"20/m/ip,5/m/key")-
Requesting a password reset. The email for which the password is to be reset is passed as the key.
"reauthenticate"(default:"10/m/user")-
Reauthentication (for users already logged in).
"reset_password_from_key"(default:"20/m/ip")-
Password reset (the view the password reset email links to).
"signup"(default:"20/m/ip")-
Signups.
"login"(default:"30/m/ip")-
Logins.
"login_failed"(default:"10/m/ip,5/5m/key")-
Restricts the allowed number of failed login attempts. When exceeded, the user is prohibited from logging in for the remainder of the rate limit. Important: while this protects the egaauth login view, it does not protect Django's admin login from being brute forced.
"confirm_email"(default:"1/3m/key"(link) or"1/10s/key"(code))-
Users can request email confirmation mails via the email management view, and, implicitly, when logging in with an unverified account. This rate limit prevents users from sending too many of these mails.
Views
Login
- URL name:
-
account_login
Users login via the egaauth.account.views.LoginView view
over at /accounts/login/ (URL name
account_login). When users attempt to login while their
account is inactive (user.is_active) they are presented
with the account/account_inactive.html template.
Signup
- URL name:
-
account_signup
Users sign up via the egaauth.account.views.SignupView
view over at /accounts/signup/ (URL name
account_signup).
Logout
- URL name:
-
account_logout
The logout view (egaauth.account.views.LogoutView) over
at /accounts/logout/ (URL name account_logout)
requests for confirmation before logging out. The user is logged out
only when the confirmation is received by means of a POST request.
If you are wondering why, consider what happens when a malicious user embeds the following image in a post:
<img src="http://example.com/accounts/logout/">
For this and more background information on the subject, see:
- https://code.djangoproject.com/ticket/15619
- http://stackoverflow.com/questions/3521290/logout-get-or-post
If you insist on having logout on GET, then please consider adding a
bit of Javascript to automatically turn a click on a logout link into a
POST. As a last resort, you can set ACCOUNT_LOGOUT_ON_GET
to True.
Password Management
Authenticated users can manage their password account using the
egaauth.account.views.PasswordSetView and
egaauth.account.views.PasswordChangeView views, over at
/accounts/password/set/ respectively
/accounts/password/change/ (URL names
account_set_password and
account_change_password respectively).
Users are redirected between these views, according to whether or not
they have setup a password (user.has_usable_password()).
Typically, when users signup via a social provider they will not have a
password set.
Password Reset
- URL name:
-
account_reset_password
Users can request a password reset using the
egaauth.account.views.PasswordResetView view over at
/accounts/password/reset/ (URL name
account_reset_password). An email will be sent containing a
reset link pointing to PasswordResetFromKeyView view.
Emails Management
- URL name:
-
account_email
Users manage the email addresses tied to their account using the
egaauth.account.views.EmailView view over at
/accounts/email/ (URL name account_email).
Here, users can add (and verify) email addresses, remove email
addresses, and choose a new primary email address.
Email Verification
Depending on the setting ACCOUNT_EMAIL_VERIFICATION, a
verification email is sent pointing to the
egaauth.account.views.ConfirmEmailView view.
The setting ACCOUNT_CONFIRM_EMAIL_ON_GET determines
whether users have to manually confirm the address by submitting a
confirmation form, or whether the address is automatically confirmed by
a mere GET request.
Template Tags
Use user_display to render a user name without making
assumptions on how the user is represented (e.g. render the username, or
first name?):
{% load account %}
{% user_display user %}
Or, if you need to use in a {% blocktrans %}:
{% load account %}
{% user_display user as user_display %}
{% blocktrans %}{{ user_display }} has logged in...{% endblocktrans %}
Then, override the ACCOUNT_USER_DISPLAY setting with
your project specific user display callable.
If you set ACCOUNT_USERNAME_REQUIRED = False and
ACCOUNT_USER_MODEL_USERNAME_FIELD = None, then you can
simply display the user.email with {{ user }}:
In case you forgot, your username is {{ user }}.
Forms
Login
- Path:
-
egaauth.account.forms.LoginForm - Used on:
-
account_login view.
Example override:
from egaauth.account.forms import LoginForm
class MyCustomLoginForm(LoginForm):
def login(self, *args, **kwargs):
# Add your own processing here.
# You must return the original result.
return super().login(*args, **kwargs)
You have access to the following:
self.useris the User object that is logging in.
settings.py:
ACCOUNT_FORMS = {'login': 'mysite.forms.MyCustomLoginForm'}
By default, the password field renders a "Forgot your password?" link
as the help text. By providing a
"account/password_reset_help_text.html" template you can
customize that text.
Signup
- Path:
-
egaauth.account.forms.SignupForm - Used on:
-
account_signup view.
Example override:
from egaauth.account.forms import SignupForm
class MyCustomSignupForm(SignupForm):
def save(self, request):
# Ensure you call the parent class's save.
# .save() returns a User object.
user = super().save(request)
# Add your own processing here.
# You must return the original result.
return user
settings.py:
ACCOUNT_FORMS = {'signup': 'mysite.forms.MyCustomSignupForm'}
Add Email
- Path:
-
egaauth.account.forms.AddEmailForm - Used on:
-
account_email view.
Example override:
from egaauth.account.forms import AddEmailForm
class MyCustomAddEmailForm(AddEmailForm):
def save(self, request):
# Ensure you call the parent class's save.
# .save() returns an egaauth.account.models.EmailAddress object.
email_address_obj = super().save(request)
# Add your own processing here.
# You must return the original result.
return email_address_obj
You have access to the following:
self.useris the User object that is logged in.
settings.py:
ACCOUNT_FORMS = {'add_email': 'mysite.forms.MyCustomAddEmailForm'}
Change Password
- Path:
-
egaauth.account.forms.ChangePasswordForm - Used on:
-
account_change_password view.
Example override:
from egaauth.account.forms import ChangePasswordForm
class MyCustomChangePasswordForm(ChangePasswordForm):
def save(self):
# Ensure you call the parent class's save.
# .save() does not return anything
super().save()
# Add your own processing here.
You have access to the following:
self.useris the User object that is logged in.
settings.py:
ACCOUNT_FORMS = {'change_password': 'mysite.forms.MyCustomChangePasswordForm'}
Set Password
- Path:
-
egaauth.account.forms.SetPasswordForm - Used on:
-
account_set_password view.
Example override:
from egaauth.account.forms import SetPasswordForm
class MyCustomSetPasswordForm(SetPasswordForm):
def save(self):
# Ensure you call the parent class's save.
# .save() does not return anything
super().save()
# Add your own processing here.
You have access to the following:
self.useris the User object that is logged in.
settings.py:
ACCOUNT_FORMS = {'set_password': 'mysite.forms.MyCustomSetPasswordForm'}
Reset Password
- Path:
-
egaauth.account.forms.ResetPasswordForm - Used on:
-
account_reset_password view.
Example override:
from egaauth.account.forms import ResetPasswordForm
class MyCustomResetPasswordForm(ResetPasswordForm):
def save(self, request):
# Ensure you call the parent class's save.
# .save() returns a string containing the email address supplied
email_address = super().save(request)
# Add your own processing here.
# Ensure you return the original result
return email_address
You have access to the following:
self.usersis a list of all possible User objects with matching email address.
settings.py:
ACCOUNT_FORMS = {'reset_password': 'mysite.forms.MyCustomResetPasswordForm'}
Reset Password From Key
- Path:
-
egaauth.account.forms.ResetPasswordKeyForm - Used on:
-
account_reset_password view.
Example override:
from egaauth.account.forms import ResetPasswordKeyForm
class MyCustomResetPasswordKeyForm(ResetPasswordKeyForm):
def save(self):
# Add your own processing here.
# Ensure you call the parent class's save.
# .save() does not return anything
super().save()
You have access to the following:
self.useris the User object.
settings.py:
ACCOUNT_FORMS = {'reset_password_from_key': 'mysite.forms.MyCustomResetPasswordKeyForm'}
Decorators
Verified Email Required
Even when email verification is not mandatory during signup, there may be circumstances during which you really want to prevent unverified users from proceeding. For this purpose you can use the following decorator:
from egaauth.account.decorators import verified_email_required
@verified_email_required
def verified_users_only_view(request):
...
The behavior is as follows:
- If the user isn't logged in, it acts identically to the
login_requireddecorator. - If the user is logged in but has no verified email address, an email verification mail is automatically resent and the user is presented with a page informing them they need to verify their email address.
Signals
There are several signals emitted during authentication flows. You can hook to them for your own needs.
egaauth.account.signals.authentication_step_completed(request, user, method, **kwargs)-
Sent when an authentication step was completed. Note that this does not imply that the user is fully signed in. For example, consider a case where a user authenticates using a password, but still needs to complete the 2FA challenge.
egaauth.account.signals.user_logged_in(request, user)-
Sent when a user logs in.
egaauth.account.signals.user_logged_out(request, user)-
Sent when a user logs out.
egaauth.account.signals.user_signed_up(request, user)-
Sent when a user signs up for an account. This signal is typically followed by a
user_logged_in, unless email verification prohibits the user to log in.
egaauth.account.signals.password_set(request, user)-
Sent when a password has been successfully set for the first time.
egaauth.account.signals.password_changed(request, user)-
Sent when a password has been successfully changed.
egaauth.account.signals.password_reset(request, user)-
Sent when a password has been successfully reset.
egaauth.account.signals.email_confirmed(request, email_address)-
Sent after the email address in the db was updated and set to confirmed.
egaauth.account.signals.email_confirmation_sent(request, confirmation, signup)-
Sent right after the email confirmation is sent.
egaauth.account.signals.email_changed(request, user, from_email_address, to_email_address)-
Sent when a primary email address has been changed.
egaauth.account.signals.email_added(request, user, email_address)-
Sent when a new email address has been added.
egaauth.account.signals.email_removed(request, user, email_address)-
Sent when an email address has been deleted.
Case Sensitivity
Historically, email addresses started out as case sensitive because the local part (the part before the "@") could represent a case sensitive user name. However, over time, this proved to be a bad idea and the RFCs that succeeded the original were adjusted to move away from treating email addresses as case sensitive.
RFC 821: The original RFC from 1982 relies on case sensitivity.
RFC 2821: Released in 2001, obsoletes RFC 821, yet, is still case sensitive.
RFC 5321: In 2008, the "Local-part" is weakened to "MAY be case-sensitive".
RFC 6530: In 2012, the following is acknowledged:
It has long been the case that the email syntax permits choices about mailbox names that are unwise in practice [...]. The most often cited examples involve the use of case-sensitivity [...] in mailbox local parts. These deliberately unusual constructions are permitted by the protocols, and servers are expected to support them. Although they can provide value in special cases, taking advantage of them is almost always bad practice unless the intent is to create some form of security by obscurity.
To deal with this, previous versions of django-egaauth used to store
email addresses in their original case, while performing lookups in a
case insensitive style. This approach led to subtle bugs in upstream
code, and also comes at a performance cost (__iexact
lookups). The latter requires case insensitive index support, which not
all databases support. Re-evaluating the approach in current times has
led to the conclusion that the benefits do not outweigh the costs.
Therefore, email addresses are now always stored as lower case.
Phone
Installation
In addition to following the overall instructions, pay attention to
the following in the settings.py of your project:
# Make sure that the login methods includes "phone" as a method.
ACCOUNT_LOGIN_METHODS = {"phone", "email"}
# Add a required phone field to the signup fields.
# ACCOUNT_SIGNUP_FIELDS = [
'phone*',
'email*' # Can be left out if you want to only use 'phone'.
]
# You will need to provide methods for storing phone numbers, and
# sending SMS messages in a custom adapter.
ACCOUNT_ADAPTER = 'project.users.adapter.MyAccountAdapter'
Configuration
Available settings:
ACCOUNT_PHONE_VERIFICATION_ENABLED(default:True)-
Whether or not mandatory verification of phone numbers during login/signup takes place.
ACCOUNT_PHONE_VERIFICATION_MAX_ATTEMPTS(default:3)-
This setting controls the maximum number of attempts the user has at inputting a valid code.
ACCOUNT_PHONE_VERIFICATION_TIMEOUT(default:900)-
The code that is sent has a limited life span. It expires this many seconds after which it was sent.
ACCOUNT_PHONE_VERIFICATION_SUPPORTS_CHANGE(default:False)-
Whether or not the phone number can be changed after signup at the phone number verification stage.
- Warning: the warning related to enumeration prevent over at
-
ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_CHANGEholds here as well.
ACCOUNT_PHONE_VERIFICATION_SUPPORTS_RESEND(default:False)-
Whether or not the user can request a new phone number verification code.
ACCOUNT_PHONE_VERIFICATION_CODE_FORMAT(default:settings.egaauth_USER_CODE_FORMAT)-
Controls the format of the verification code.
Form Fields
For presenting a phone number form field to the user a basic
<input type="tel"> field is used that requires input
in E164 format. There are various external projects that offer more
elaborate phone number input fields. You can switch over to using the
fields provided by those projects, or, tweak the phone number validaton
logic, by overriding the following adapter methods:
egaauth.account.adapter.DefaultAccountAdapter
phone_form_field
clean_phone
Database Models
Out of the box, there are no models provided intended to store the phone numbers of users. It is up to the developer to decide where phone numbers are to be stored, for example, on a custom user model, or, on a separate Phone model of its own. Once those the models are setup, the following adapter methods need to be populated so that the models will be used:
egaauth.account.adapter.DefaultAccountAdapter
get_phone
set_phone
set_phone_verified
get_user_by_phone
Sending SMS Messages
For sending SMS messages, various external providers and packages are available. You can integrate those by overriding the following adapter method:
egaauth.account.adapter.DefaultAccountAdapter
send_verification_code_sms
send_unknown_account_sms
Turnkey Phone Authentication
egaauth.contrib.phone turns the existing phone-auth
extension points into a reusable packaged setup with a bundled phone
model, admin integration, health checks, and optional external
verification-provider support.
Installation
Add the app and adapter:
INSTALLED_APPS += [
"egaauth.contrib.phone",
]
ACCOUNT_ADAPTER = "egaauth.contrib.phone.adapter.PhoneAccountAdapter"
ACCOUNT_LOGIN_METHODS = {"email", "phone"}
ACCOUNT_SIGNUP_FIELDS = ["phone*", "email", "password1*"]
For local development, the default provider is console
and verification codes are logged server-side while verification remains
handled by egaauth's existing code flow.
Twilio Verify
To delegate verification-code checking to Twilio Verify:
EGAAUTH_PHONE_PROVIDER = "twilio_verify"
EGAAUTH_PHONE_TWILIO_ACCOUNT_SID = "..."
EGAAUTH_PHONE_TWILIO_AUTH_TOKEN = "..."
EGAAUTH_PHONE_TWILIO_VERIFY_SERVICE_SID = "VA..."
EGAAUTH_PHONE_DEFAULT_CHANNEL = "sms"
When using twilio_verify, the library starts the
verification through Twilio and also validates the submitted code
through Twilio instead of solely relying on the locally generated
session code.
What it provides
PhoneCredentialmodel storing one primary phone number per user.PhoneAccountAdapterimplementingset_phone(),get_phone(),set_phone_verified(),get_user_by_phone()and SMS delivery.- System checks for common configuration mistakes.
- Management commands:
python manage.py egaauth_phone_checkpython manage.py egaauth_phone_test +15551234567
Enumeration-prevention messages
By default, enumeration-prevention SMS messages are logged/no-op because many projects prefer not to send separate informational messages for unknown or already-registered numbers. If desired:
EGAAUTH_PHONE_SEND_ENUMERATION_PREVENTION_SMS = True
Adapter
egaauth.account.adapter.DefaultAccountAdapter
Advanced Usage
Custom User Models
If you use a custom user model you need to specify what field
represents the username, if any. Here,
username really refers to the field representing the
nickname that the user uses to login, and not to some unique identifier
(possibly including an email address) as is the case for Django's
AbstractBaseUser.USERNAME_FIELD.
Therefore, if your custom user model does not have a
username field (again, not to be mistaken with an email
address or user id), you will need to set
ACCOUNT_USER_MODEL_USERNAME_FIELD to None.
This will disable username related functionality in
egaauth. Remember to also remove username from
ACCOUNT_SIGNUP_FIELDS as by default that is present.
Similarly, you will need to set
ACCOUNT_USER_MODEL_EMAIL_FIELD to None or to
the proper field (if other than email).
For example, if you want to use a custom user model that has
email as the identifying field, and you don't want to
collect usernames, you need the following in your settings.py:
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_SIGNUP_FIELDS = ['email*', 'password1*', 'password2*']
ACCOUNT_LOGIN_METHODS = {'email'}
Creating and Populating User instances
The following adapter methods can be used to intervene in how User instances are created and populated with data
egaauth.account.adapter.DefaultAccountAdapter:is_open_for_signup(self, request): The default function returnsTrue. You can override this method by returningFalseif you want to disable account signup.new_user(self, request): Instantiates a new, emptyUser.save_user(self, request, user, form): Populates and saves theUserinstance using information provided in the signup form.populate_username(self, request, user): Fills in a valid username, if required and missing. If the username is already present, then it is assumed to be valid (unique).confirm_email(self, request, email_address): Marks the email address as confirmed and saves to the db.generate_unique_username(self, txts, regex=None): Returns a unique username from the combination of strings present in txts iterable. A regex pattern can be passed to the method to make sure the generated username matches it.
Invitations
Invitation handling is not supported, and most likely will not be any time soon. An invitation app could cover anything ranging from invitations of new users, to invitations of existing users to participate in restricted parts of the site. All in all, the scope of invitation handling is large enough to warrant being addressed in an app of its own.
Still, everything is in place to easily hook up any third party
invitation app. The account adapter
(egaauth.account.adapter.DefaultAccountAdapter) offers the
following methods:
is_open_for_signup(self, request). You can override this method to, for example, inspect the session to check if an invitation was accepted.stash_verified_email(self, request, email). If an invitation was accepted by following a link in an email, then there is no need to send email verification mails after the signup is completed. Use this method to record the fact that an email address was verified.
Custom Redirects
If redirecting to statically configurable URLs (as specified in your project settings) is not flexible enough, then you can override the following adapter methods:
egaauth.account.adapter.DefaultAccountAdapter:get_login_redirect_url(self, request)get_logout_redirect_url(self, request)get_email_verification_redirect_url(self, email_address)get_signup_redirect_url(self, request)
For example, redirecting to /accounts/<username>/
can be implemented as follows:
# project/settings.py:
ACCOUNT_ADAPTER = 'project.users.adapter.MyAccountAdapter'
# project/users/adapter.py:
from django.conf import settings
from egaauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
path = "/accounts/{username}/"
return path.format(username=request.user.username)
Third-Party ("Social") Accounts
Introduction
A third-party ("social") account is a user account where
authentication is delegated to an external identity provider. The
egaauth.socialaccount app is responsible for managing
social accounts. It supports:
- Connecting one or more social accounts to a local/regular account
- Disconnecting a social account -- requires setting a password if only the local account remains
- Optional instant-signup for social accounts -- no questions asked
Note that in order to use this functionality you need to install the
socialaccount extras of the django-egaauth
package:
pip install "django-egaauth[socialaccount]"
Configuration
Available settings:
SOCIALACCOUNT_ADAPTER(default:"egaauth.socialaccount.adapter.DefaultSocialAccountAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behaviour.
SOCIALACCOUNT_AUTO_SIGNUP(default:True)-
Attempt to bypass the signup form by using fields (e.g. username, email) retrieved from the social account provider. If a conflict arises due to a duplicate email address the signup form will still kick in.
SOCIALACCOUNT_EMAIL_AUTHENTICATION(default:False)-
Consider a scenario where a social login occurs, and the social account comes with a verified email address (verified by the account provider), but that email address is already taken by a local user account. Additionally, assume that the local user account does not have any social account connected. Now, if the provider can be fully trusted, you can argue that we should treat this scenario as a login to the existing local user account even if the local account does not already have the social account connected, because --according to the provider -- the user logging in has ownership of the email address. This is how this scenario is handled when
SOCIALACCOUNT_EMAIL_AUTHENTICATIONis set toTrue. As this implies that an untrustworthy provider can login to any local account by fabricating social account data, this setting defaults toFalse. Only set it toTrueif you are using providers that can be fully trusted. Instead of turning this on globally, you can also turn it on selectively per provider, for example:SOCIALACCOUNT_PROVIDERS = { 'google': { 'EMAIL_AUTHENTICATION': True } } SOCIALACCOUNT_EMAIL_AUTHENTICATION_AUTO_CONNECT(default:False)-
In case email authentication is applied, this setting controls whether or not the social account is automatically connected to the local account. In case of
Falsethe local account remains unchanged during the login. In case ofTrue, the social account for which the email matched, is automatically added to the list of social accounts connected to the local account. As a result, even if the user were to change the email address afterwards, social login would still be possible when usingTrue, but not in case ofFalse. SOCIALACCOUNT_EMAIL_VERIFICATION(default:ACCOUNT_EMAIL_VERIFICATION)-
As
ACCOUNT_EMAIL_VERIFICATION, but for social accounts. SOCIALACCOUNT_EMAIL_REQUIRED(default:"email*" in ACCOUNT_SIGNUP_FIELDS)-
The user is required to hand over an email address when signing up using a social account.
SOCIALACCOUNT_FORMS-
Used to override forms. Defaults to:
SOCIALACCOUNT_FORMS = { 'disconnect': 'egaauth.socialaccount.forms.DisconnectForm', 'signup': 'egaauth.socialaccount.forms.SignupForm', } SOCIALACCOUNT_LOGIN_ON_GET(default:False)-
Controls whether or not the endpoints for initiating a social login (for example, "/accounts/google/login/") require a POST request to initiate the handshake. For security considerations, it is strongly recommended to require POST requests.
SOCIALACCOUNT_PROVIDERS(default:{})-
Dictionary containing provider specific settings.
SOCIALACCOUNT_REQUESTS_TIMEOUT(default:5)-
The timeout applied when performing upstream requests.
SOCIALACCOUNT_QUERY_EMAIL(default:"email*" in ACCOUNT_SIGNUP_FIELDS)-
Request email address from 3rd party account provider? E.g. using OpenID AX, or the Facebook "email" permission.
SOCIALACCOUNT_SOCIALACCOUNT_STR(default:strof user object)-
Used to override the str value for the SocialAccount model.
Must be a function accepting a single parameter for the socialaccount object.
SOCIALACCOUNT_STORE_TOKENS(default:False)-
Indicates whether or not the access tokens are stored in the database. Note that tokens can only be stored if the related social account is stored as well, which is not the case when you are using
SOCIALACCOUNT_EMAIL_AUTHENTICATIONwithoutSOCIALACCOUNT_EMAIL_AUTHENTICATION_AUTO_CONNECT. SOCIALACCOUNT_ONLY(default:False)-
When enabled (
True), all functionality with regard to local accounts is disabled, and users will only be able to authenticate using third-party providers. SOCIALACCOUNT_OPENID_CONNECT_URL_PREFIX(default:"oidc")-
The URL path prefix that is used for all OpenID Connect providers. By default, it is set to
"oidc", meaning, an OpenID Connect provider with provider IDfoouses/accounts/oidc/foo/login/as its login URL.
Provider Configuration
Providers typically require various configuration parameters before your users can authenticate with them. For example, for a regular OAuth provider you first need to setup an OAuth app over on the provider developer portal. Then, you need to configure the resulting client ID and client secret in your application.
Even though providers with other protocols may use different
terminology, the overall idea remains the same. Throughout egaauth the
term "social app" ("app" for short) refers to the unit of configuration
of a provider. You provide the app configuration either in your project
settings.py, or, by means of setting up
SocialApp instances via the Django admin. When picking a
method, consider the following:
- Using the Django admin to setup
SocialAppinstances effectively stores secrets in your database, which has security implications. - The
SocialAppapproach has (optional) support for the Django sites (django.contrib.sites). For example, it allows you to setup multiple apps for one and the same provider, and assign an app to a specific site/domain. This may be of use in a multi tenant setup.
Important: While you can mix both methods, be aware
you need to avoid configuring one and the same provider both via
settings.py and a SocialApp instance. In that
case, it is not clear what app to pick, resulting in a
MultipleObjectsReturned exception.
The examples presented in this documentation are all settings based.
If you prefer the SocialApp based approach, simply create
an entry via the Django admin and populate the fields exactly like
listed in the example.
The SOCIALACCOUNT_PROVIDERS setting is used to configure
providers and their apps. Next to the secrets that are configured per
app, there are also parameters such as VERIFIED_EMAIL that
hold for all apps. The following is an example configuration:
SOCIALACCOUNT_PROVIDERS = {
"github": {
# For each provider, you can choose whether or not the
# email address(es) retrieved from the provider are to be
# interpreted as verified.
"VERIFIED_EMAIL": True
},
"google": {
# For each OAuth based provider, either add a ``SocialApp``
# (``socialaccount`` app) containing the required client
# credentials, or list them here:
"APPS": [
{
"client_id": "123",
"secret": "456",
"key": "",
"settings": {
# You can fine tune these settings per app:
"scope": [
"profile",
"email",
],
"auth_params": {
"access_type": "online",
},
},
},
],
# The following provider-specific settings will be used for all apps:
"SCOPE": [
"profile",
"email",
],
"AUTH_PARAMS": {
"access_type": "online",
},
}
}
Note that provider-specific settings are documented for each provider separately.
Views
Social Connections
- URL name:
-
socialaccount_connections
The egaauth.socialaccount.views.ConnectionsView view
over at /accounts/social/connections/ (URL name
socialaccount_connections) allows users to manage the
social accounts tied to their local account.
Template Tags
Use the provider_login_url tag to generate provider
specific login URLs:
{% load socialaccount %}
<a href="{% provider_login_url "openid" openid="https://www.google.com/accounts/o8/id" next="/success/url/" %}">Google</a>
<a href="{% provider_login_url "twitter" %}">Twitter</a>
Here, you can pass along an optional process parameter
that indicates how to process the social login. You can choose between
login and connect:
<a href="{% provider_login_url "twitter" process="connect" %}">Connect a Twitter account</a>
Furthermore, you can pass along an action parameter with
value reauthenticate to indicate that you want the user to
be re-prompted for authentication even if they already signed in before.
For now, this is supported by Facebook, Google, Twitter, and Discord
only.
For Javascript based logins (e.g. when you enable the Facebook JS SDK), you will need to make sure that the required Javascript is loaded. The following tag loads all scripts for the enabled providers:
{% providers_media_js %}
For easy access to the social accounts for a user use:
{% get_social_accounts user as accounts %}
Then:
{{accounts.twitter}} -- a list of connected Twitter accounts
{{accounts.twitter.0}} -- the first Twitter account
{% if accounts %} -- if there is at least one social account
Finally, social authentication providers configured for the current site can be retrieved via:
{% get_providers as socialaccount_providers %}
Which will populate the socialaccount_providers variable
in the template context with a list of configured social authentication
providers. This supersedes the context processor used in version 0.21
and below.
Forms
Signup
- Path:
-
egaauth.socialaccount.forms.SignupForm - Used on:
-
socialaccount_signupview used when a user initially signs up with a social account and needs to create an account.
Example override:
from egaauth.socialaccount.forms import SignupForm
class MyCustomSocialSignupForm(SignupForm):
def save(self, request):
# Ensure you call the parent class's save.
# .save() returns a User object.
user = super().save(request)
# Add your own processing here.
# You must return the original result.
return user
You have access to the following:
self.socialaccount
settings.py:
SOCIALACCOUNT_FORMS = {'signup': 'mysite.forms.MyCustomSocialSignupForm'}
Disconnect
- Path:
-
egaauth.socialaccount.forms.DisconnectForm - Used on:
-
socialaccount_connectionsview, used when removing a social account.
Example override:
from egaauth.socialaccount.forms import DisconnectForm
class MyCustomSocialDisconnectForm(DisconnectForm):
def save(self):
# Add your own processing here if you do need access to the
# socialaccount being deleted.
# Ensure you call the parent class's save.
# .save() does not return anything
super().save()
# Add your own processing here if you don't need access to the
# socialaccount being deleted.
You have access to the following:
self.requestis the request objectself.accountsis a list containing all of the user's SocialAccount objects.self.cleaned_data['account']contains the socialaccount being deleted..save()issues the delete. So if you need access to the socialaccount beforehand, move your code before.save().
settings.py:
SOCIALACCOUNT_FORMS = {'disconnect': 'mysite.forms.MyCustomSocialDisconnectForm'}
Signals
There are several signals emitted during authentication flows. You can hook to them for your own needs.
egaauth.socialaccount.signals.pre_social_login(request, sociallogin)-
Sent after a user successfully authenticates via a social provider, but before the login is fully processed. This signal is emitted as part of the social login and/or signup process, as well as when connecting additional social accounts to an existing account. Access tokens and profile information, if applicable for the provider, is provided.
egaauth.socialaccount.signals.social_account_added(request, sociallogin)-
Sent after a user connects a social account to their local account. This is an explicit action and does not get called for the creation of a socialaccount.
egaauth.socialaccount.signals.social_account_updated(request, sociallogin)-
Sent after a social account has been updated. This happens when a user logs in using an already connected social account, or completes a connect flow for an already connected social account. Useful if you need to unpack extra data for social accounts as they are updated.
egaauth.socialaccount.signals.social_account_removed(request, socialaccount)-
Sent after a user disconnects a social account from their local account.
Providers
Introduction
Most providers require you to sign up for a so called API client or
app, containing a client ID and API secret. You must add a
SocialApp record per provider via the Django admin
containing these app credentials.
When creating the OAuth app on the side of the provider pay special attention to the callback URL (sometimes also referred to as redirect URL). If you do not configure this correctly, you will receive login failures when attempting to log in, such as:
An error occurred while attempting to login via your social network account.
Use a callback URL of the form:
http://example.com/accounts/twitter/login/callback/
http://example.com/accounts/soundcloud/login/callback/
...
For local development, use the following:
http://127.0.0.1:8000/accounts/twitter/login/callback/
Protocol Specifics
Provider Specifics
Provider catalog at a glance
This build includes configuration notes for 114 provider documents shipped with the source tree.
- 23andme
- 500px
- agave
- amazon
- amazon cognito
- angellist
- apple
- atlassian
- auth0
- authelia
- authentiq
- baidu
- basecamp
- battlenet
- bitbucket
- box
- cern
- cilogon
- clever
- dataporten
- daum
- digitalocean
- dingtalk
- discogs
- discord
- doximity
- draugiem
- drip
- dropbox
- dwolla
- edmodo
- edx
- eventbrite
- eveonline
- evernote
- exist
- feishu
- figma
- flickr
- frontier
- fxa
- gitea
- github
- gitlab
- globus
- gumroad
- hubspot
- jupyterhub
- kakao
- keycloak
- lemonldap
- lichess
- line
- mailchimp
- mailcow
- mediawiki
- microsoft
- miro
- naver
- netiq
- nextcloud
- notion
- oauth2
- odnoklassniki
- okta
- openid
- openid connect
- openstreetmap
- orcid
- patreon
- paypal
- questrade
- quickbooks
- salesforce
- saml
- sharefile
- shopify
- slack
- snapchat
- soundcloud
- stackexchange
- steam
- stocktwits
- strava
- stripe
- telegram
- tiktok
- trainingpeaks
- trello
- tumblr oauth2
- twitch
- twitter oauth2
- untappd
- vimeo
- vimeo oauth2
- vk
- wahoo
- weixin
- windowslive
- yahoo
- yandex
- ynab
- zoho
- zoom
OAuth 2.0
This section documents OAuth 2.0 specifics that are shared across all OAuth 2.0 based providers, including (but not limited to):
- tumblr_oauth2
- twitter_oauth2
- vimeo_oauth2
- openid_connect
- keycloak
Authorization Request Parameters
Optional parameters can be provided as a dictionary under the key
auth_params.
Attention
Some providers might not support each of these parameters.
This configuration example will tell the provider instance,
My Login Server, to prompt the user for
reauthentication.
23andMe
- App registration (get your key and secret here)
- Development callback URL
500px
- App registration (get your key and secret here)
- Development callback URL
AgaveAPI
- Account Signup
- App registration
-
Run
client-createfrom the cli: https://bitbucket.org/agaveapi/cli/overview - Development callback URL
-
http://localhost:8000/accounts/agave/login/callback/ May require https url, even for localhost
- In the absence of a specified API_URL, the default Agave tenant is
Amazon Cognito
- App registration (get your key and secret here)
-
- Go to your https://console.aws.amazon.com/cognito/ and create a Cognito User Pool if you haven't already.
- Go to General Settings > App Clients section and create a new App Client if you haven't already. Please make sure you select the option to generate a secret key.
- Go to App Integration > App Client Settings section and:
- Enable Cognito User Pool as an identity provider.
- Set the callback and sign-out URLs. (see next section for development callback URL)
- Enable Authorization Code Grant OAuth flow.
- Select the OAuth scopes you'd like to allow.
- Go to App Integration > Domain Name section and create a domain prefix for your Cognito User Pool.
- Development callback URL:
-
http://localhost:8000/accounts/amazon-cognito/login/callback/
In addition, you'll need to specify your user pool's domain like so:
Your domain prefix is the value you specified in step 4 of the app registration process. If you provided a custom domain such as accounts.example.com provide that instead.
Amazon
Amazon requires secure OAuth callback URLs
(redirect_uri), please see the section on HTTPS about how
this is handled.
- App registration (get your key and secret here)
- Development callback URL
AngelList
- App registration (get your key and secret here)
- Development callback URL
Apple
- App registration (create an App ID and then a related Service ID here)
-
https://developer.apple.com/account/resources/identifiers/list
- Private Key registration (be sure to save it)
- Development callback URL
Add the following configuration to your settings:
Apple offers two distinct client IDs: a "Bundle ID" and a "Services
ID". When the flow is started from a mobile iOS device the bundle ID is
used, whereas a web authorization flow uses the services ID as the
client ID. If you need to support both client IDs within one project,
add an app entry (over at APPS) for each client ID. For the
app specifying the bundle ID, add the following to the settings so that
this app does not show up on the web:
"settings": { "hidden": True, ... }
Note: Sign In With Apple uses a slight variation of OAuth2, which uses a POST instead of a GET. Unlike a GET with SameSite=Lax, the session cookie will not get sent along with a POST. If you encounter 'PermissionDenied' errors during Apple log in, check that you don't have any 3rd party middleware that is generating a new session on this cross-origin POST, as this will prevent the login process from being able to access the original session after the POST completes.
Atlassian
Atlassian OAuth 2.0 (3LO) apps provider.
Enabling OAuth 2.0 (3LO)
Before you can implement OAuth 2.0 (3LO) for your app, you need to enable it for your app using the developer console.
- Atlassian developer console
- From any page on developer.atlassian.com, select your profile icon in the top-right corner, and from the dropdown, select Developer console.
- Select your app from the list (or create one if you don't already have one).
- Select Authorization in the left menu.
- Next to OAuth 2.0 (3LO), select Configure.
- Enter the Callback URL. Ex.
http://127.0.0.1:8000/accounts/atlassian/login/callback/ - Click Save changes.
Note, if you haven't already added an API to your app, you should do this now:
- Select Permissions in the left menu.
- Next to the API you want to add, select Add.
Django setup
The app credentials are configured for your Django installation via
the admin interface. Create a new socialapp through
/admin/socialaccount/socialapp/.
Fill in the form as follows:
- Provider, "Atlassian"
- Name, your pick, suggest "Atlassian"
- Client id, is called "Client ID" by Atlassian
- Secret key, is called "Secret" by Atlassian
- Key, is not needed, leave blank.
Optionally, you can specify the scope to use as follows:
Note
By default (if you do not specify SCOPE),
read:me scope is requested.
Auth0
- App registration (get your key and secret here)
- Development callback URL
You'll need to specify the base URL for your Auth0 domain:
Authelia
At the time of writing, Authelia supports OpenID Connect (OIDC) as a beta feature. Detailed information about the available configuration options can be found on their website.
As documented at https://www.authelia.com/integration/openid-connect/introduction/
the Well Known Discovery Endpoint that can be used as the server url is
https://auth.example.com/.well-known/openid-configuration
where https://auth.example.com/ should be replaced by the
specific url of your instance of Authelia.
An example configuration for authelia would look like this:
SOCIALACCOUNT_PROVIDERS = {
"openid_connect": {
"APPS": [
{
"provider_id": "authelia",
"name": "Authelia SSO",
"client_id": "<insert-id>",
"secret": "<insert-secret>",
"settings": {
"server_url": "https://auth.example.com/.well-known/openid-configuration"
}
}
]
}
}
Note that the client id and the secret must match the configuration in Authelia for this django-egaauth app.
Authentiq
Browse to https://www.authentiq.com/developers to get started.
- App registration
Sign in or register with your Authentiq ID (select
Download the app while signing in if you don't have
Authentiq ID yet).
- Development redirect URL
While testing you can leave the Redirect URIs field
empty in the dashboard. You can specify what identity details to request
via the SCOPE parameter.
Valid scopes include: email, phone,
address, aq:name, aq:location.
The default is to request a user's name, and email address if
SOCIALACCOUNT_QUERY_EMAIL=True. You can request and require
a verified email address by setting
SOCIALACCOUNT_EMAIL_VERIFICATION=True and
SOCIALACCOUNT_EMAIL_REQUIRED=True.
Baidu
- The Baidu OAuth2 authentication documentation:
-
http://developer.baidu.com/wiki/index.php?title=docs/oauth/refresh http://developer.baidu.com/wiki/index.php?title=docs/oauth/rest/file_data_apis_lista
Basecamp
- App registration (get your key and secret here)
- The Basecamp OAuth2 authentication documentation
-
https://github.com/basecamp/api/blob/master/sections/authentication.md#oauth-2
- Development callback URL
Battle.net
- The Battle.net OAuth2 authentication documentation
- Register your app here (Blizzard account required)
- Development callback URL
Note that in order to use battletags as usernames, you are expected
to override either the username field on your User model,
or to pass a custom validator which will accept the #
character using the ACCOUNT_USERNAME_VALIDATORS setting.
Such a validator is available in
socialaccount.providers.battlenet.validators.BattletagUsernameValidator.
The following Battle.net settings are available:
- SCOPE:
-
Scope can be an array of the following options:
wow.profileallows access to the user's World of Warcraft characters.sc2.profileallows access to the user's StarCraft 2 profile. The default setting is[]. - REGION:
-
Either
apac,cn,eu,kr,sea,tworusSets the default region to use, can be overridden using query parameters in the URL, for example:
?region=eu. Defaults tous.
Bitbucket
- App registration (get your key and secret here)
-
https://bitbucket.org/account/user/{{yourusername}}/oauth-consumers/new
Make sure you select the Account:Read permission.
- Development callback URL
-
http://127.0.0.1:8000/accounts/bitbucket_oauth2/login/callback/
Note that Bitbucket calls the client_id Key in
their user interface. Don't get confused by that; use the Key
value for your client_id field.
Box
- App registration (get your key and secret here)
- Development callback URL
CERN
Members of the scientific commmunity affiliated with CERN (https://home.cern/about) can put their applications behind CERN SSO, which supports OIDC and SAML protocols. For OIDC, use the regular OpenID Connect configuration:
- App registration (get your key and secret here)
- Documentation
-
https://auth.docs.cern.ch/applications/application-configuration/
CILogon
CILogon is a federated identity provider for hundreds of universities and research institutions around the world.
- App registration (get your key and secret here)
- CILogon OIDC/OAuth2 Documentation
Clever
Single sign-on for education
- Clever OAUth2 Documentation
Dataporten
- App registration (get your key and secret here)
- Development callback URL
daum
- App registration (get your key and secret here)
- Development callback URL
DigitalOcean
- App registration (get your key and secret here)
- Development callback URL
With the acquired access token you will have read permissions on the API by default. If you also need write access specify the scope as follows. See https://developers.digitalocean.com/documentation/oauth/#scopes for details.
DingTalk
The DingTalk OAuth2 documentation:
https://open.dingtalk.com/document/orgapp-server/obtain-identity-credentials
You can optionally specify additional scope to use. If no
SCOPE value is set, will use openapi by
default(for Open Platform Account, need registration). Other
SCOPE options are: corpid.
Discogs (OAuth 1a)
You will need to register a Discogs app to obain a consumer key and secret.
App registration
To register an app you will need a Discogs account.
With an account, you can create a new app at:
https://www.discogs.com/settings/developers
In the app creation form (optionally) fill in the development callback URL:
http://127.0.0.1:8000/accounts/discogs/login/callback/
For production use a callback URL such as:
https://{{yourdomain}}.com/accounts/discogs/login/callback/
Setting up provider
- 'name', up to you to choose (optional)
- 'client_id', is called "Consumer Key"
- 'secret', is called "Consumer Secret"
Discord
- App registration and management (get your key and secret here)
Make sure to Add Redirect URI to your application.
- Development callback (redirect) URL
It's required to request the identify scope to fetch the user ID.
Doximity
- Doximity OAuth2 implementation documentation
- Request API keys here
- Development callback URL
Draugiem
- App registration (get your key and secret here)
- Authentication documentation
- Development callback URL
Drip
- App registration (get your key and secret here)
- Authentication documentation
- Development callback URL
Make sure the registered application is active.
Dropbox
- App registration (get your key and secret here)
- Development callback URL
Dwolla
- App registration (get your key and secret here)
- Development callback URL
Edmodo
- Edmodo OAuth2 documentation
-
https://developers.edmodo.com/edmodo-connect/edmodo-connect-overview-getting-started/
You can optionally specify additional permissions to use. If no
SCOPE value is set, the Edmodo provider will use
basic by default:
Edx
- Open Edx OAuth2 documentation
-
https://course-catalog-api-guide.readthedocs.io/en/latest/authentication/
It is necessary to set EDX_URL to your open edx
installation. If no EDX_URL value is set, the Edx provider
will use https://edx.org which does not work:
Eventbrite
Log in and click your profile name in the top right navigation, then
select Account Settings. Choose App Management
near the bottom of the left navigation column. You can then click
Create A New App on the upper left corner.
- App registration
Fill in the form with the following link
- Development callback URL
for both the Application URL and
OAuth Redirect URI.
Eve Online
Register your application at
https://developers.eveonline.com/applications/create. Note
that if you have STORE_TOKENS enabled (the default), you
will need to set up your application to be able to request an OAuth
scope. This means you will need to set it as having "CREST Access". The
least obtrusive scope is "publicData".
Evernote
Register your OAuth2 application at
https://dev.evernote.com/doc/articles/authentication.php:
Exist
Register your OAuth2 app in apps page:
During development set the callback url to:
In production replace localhost with whatever domain you're hosting your app on.
If your app is writing to certain attributes you need to specify this during the creation of the app. For a full list of scopes see:
https://developer.exist.io/reference/authentication/oauth2/#scopes
The following Exist settings are available:
- SCOPE:
-
The default scopes are listed above. For reading additional attributes or writing data see https://developer.exist.io/reference/authentication/oauth2/#scopes.
For more information: OAuth documentation: https://developer.exist.io/reference/authentication/oauth2 API documentation: https://developer.exist.io/reference/important_values/
For Facebook both OAuth2, Facebook Connect Javascript SDK and even Limited Login are supported. You can even mix and match.
An advantage of the Javascript SDK may be a more streamlined user experience as you do not leave your site. Furthermore, you do not need to worry about tailoring the login dialog depending on whether or not you are using a mobile device. Yet, relying on Javascript may not be everybody's cup of tea.
To initiate a login use:
The following Facebook settings are available:
- METHOD:
-
Either
js_sdkoroauth2. The default isoauth2. - SDK_URL:
-
If needed, use
SDK_URLto override the default Facebook JavaScript SDK URL,//connect.facebook.net/{locale}/sdk.js. This may be necessary, for example, when using the Customer Chat Plugin. If theSDK_URLcontains a{locale}format string named argument, the locale given by theLOCALE_FUNCwill be used to generate theSDK_URL. - SCOPE:
-
By default, the
emailscope is required depending on whether or notSOCIALACCOUNT_QUERY_EMAILis enabled. Apps using permissions beyondemailandpublic_profilerequire review by Facebook. See Permissions with Facebook Login for more information. - AUTH_PARAMS:
-
Use
AUTH_PARAMSto pass along other parameters to theFB.loginJS SDK call. - FIELDS:
-
The fields to fetch from the Graph API
/me/?fields=endpoint. For example, you could add the'friends'field in order to capture the user's friends that have also logged into your app using Facebook (requires'user_friends'scope). - EXCHANGE_TOKEN:
-
The JS SDK returns a short-lived token suitable for client-side use. Set
EXCHANGE_TOKEN = Trueto make a server-side request to upgrade to a long-lived token before storing in theSocialTokenrecord. See Expiration and Extending Tokens. - LOCALE_FUNC:
-
The locale for the JS SDK is chosen based on the current active language of the request, taking a best guess. This can be customized using the
LOCALE_FUNCsetting, which takes either a callable or a path to a callable. This callable must take exactly one argument, the request, and return a valid Facebook locale <http://developers.facebook.com/docs/ internationalization/> as a string, e.g. US English: - VERIFIED_EMAIL:
-
It is not clear from the Facebook documentation whether or not the fact that the account is verified implies that the email address is verified as well. For example, verification could also be done by phone or credit card. To be on the safe side, the default is to treat email addresses from Facebook as unverified. But, if you feel that is too paranoid, then use this setting to mark them as verified. Due to lack of an official statement from the side of Facebook, attempts have been made to reverse engineer the meaning of the verified flag. Do know that by setting this to
Trueyou may be introducing a security risk. - VERSION:
-
The Facebook Graph API version to use. The default is
v13.0. - App registration (get your key and secret here)
-
A key and secret key can be obtained by creating an app. After registration you will need to make it available to the public. In order to do that your app first has to be reviewed by Facebook.
- Development callback URL
-
Leave your App Domains empty and put
http://localhost:8000in the section labeledWebsite with Facebook Login. Note that you'll need to add your site's actual domain to this section once it goes live.
For Limited Login, it is exclusively supported via the Headless API's "provider token" flow.
Pass your Limited Login JWT (obtained from the Facebook iOS SDK) to
that endpoint as an id_token.
Note that Limited Login is purely used for login and does not allow
access to the user's Facebook account - no SocialToken is
created.
Feishu
- App Registration
- Authorized Redirect URI
Into the developer background https://open.feishu.cn/app, click on the create self-built application, obtain app_id and app_secret. In the configuration of application security domain name added to redirect URL, such as https://open.feishu.cn/document. Redirect URL is the interface through which the application obtains the user's identity by using the user login pre-authorization code after the user has logged in. If it is not configured or configured incorrectly, the open platform will prompt the request to be illegal.
Figma
- App registration (get your key and secret here)
- Development callback URL
Flickr
- App registration (get your key and secret here)
You can optionally specify the application permissions to use. If no
perms value is set, the Flickr provider will use
read by default.
Frontier
The Frontier provider is OAuth2 based.
Client registration
Frontier Developments switched to OAuth2 based authentication in early 2019. Before a developer can use the authentication and CAPI (Companion API) service from Frontier, they must first apply for access.
Go to https://user.frontierstore.net/ and apply for access. Once your application is approved for access. Under "Developer Zone", you will see a list of authorized clients granted access. To add access for your client, click on the "Create Client" button and fill out the form and submit the form.
After creating the client access, click on "View" to reveal your Client ID and Shared Key. You can also regenerate the key in an event that your shared key is compromised.
Configuring Django
The app credentials are configured for your Django installation via
the admin interface. Create a new socialapp through
/admin/socialaccount/socialapp/.
Fill in the form as follows:
- Provider, "Frontier"
- Name, your pick, suggest "Frontier"
- Client id, is called "Client ID" by Frontier
- Secret key, is called "Shared Key" by Frontier
- Key, is not needed, leave blank.
Optionally, you can specify the scope to use as follows:
Firefox Accounts
The Firefox Accounts provider is currently limited to Mozilla relying services but there is the intention, in the future, to allow third-party services to delegate authentication. There is no committed timeline for this.
- The provider is OAuth2 based. More info:
The following Firefox Accounts settings are available:
- SCOPE:
-
Requested OAuth2 scope. Default is ['profile'], which will work for applications on the Mozilla trusted whitelist. If your application is not on the whitelist, then define SCOPE to be ['profile:email', 'profile:uid'].
- OAUTH_ENDPOINT:
-
Explicitly set the OAuth2 endpoint. Default is the production endpoint "https://oauth.accounts.firefox.com/v1".
- PROFILE_ENDPOINT:
-
Explicitly set the profile endpoint. Default is the production endpoint and is "https://profile.accounts.firefox.com/v1".
Gitea
- App registration (get your key and secret here)
- Development callback URL
Self-hosted Support
If you use a self-hosted Gitea instance add your server URL to your Django settings as follows:
GitHub
- App registration (get your key and secret here)
- Development callback URL
If you want more than just read-only access to public data, specify the scope as follows. See https://developer.github.com/v3/oauth/#scopes for details.
Enterprise Support
If you use GitHub Enterprise add your server URL to your Django settings as follows:
GitLab
The GitLab provider works by default with https://gitlab.com. It allows you to connect to your private GitLab server and use GitLab as an OAuth2 authentication provider as described in GitLab docs at https://docs.gitlab.com/integration/oauth_provider/
The following GitLab settings are available, if unset https://gitlab.com will be used, with a
read_user scope.
- GITLAB_URL:
-
Override endpoint to request an authorization and access token. For your private GitLab server you use:
https://your.gitlab.server.tld - SCOPE:
-
The
read_userscope is required for the login procedure, and is the default. If more access is required, the scope should be set here.
Example:
Globus
- Registering an application:
By default, you will have access to the openid, profile, and offline_access scopes. With the offline_access scope, the API will provide you with a refresh token. For additional scopes, see the Globus API docs:
The Google provider is OAuth2 based.
App registration
Create a google app to obtain a key and secret through the developer console.
- Google Developer Console
After you create a project, you will have to create an OAuth client ID and fill in some project details for the consent form that will be presented to the client:
- Under "APIs & Services", go to "Credentials", click "Create
credentials" and create a new "OAuth client ID". Probably you will want
to choose "Web application" as the application type. Provide your domain
name or test domain name in "Authorized JavaScript origins". Finally,
fill in the "Authorized redirect URIs" field with URLs like
http://example.com/accounts/google/login/callback/, replacing the domain name with your domain name, or with127.0.0.1:8000for testing. After creating the OAuth client ID, make a note of the client ID and the client secret, as you will need it later. - Users that log in using the app will be presented a consent form. For this to work, additional information is required. Under "APIs & Services", go to "OAuth consent screen" and at least provide an email address and a product name.
Django configuration
Don't forget to add the Google provider to your
INSTALLED_APPS setting:
The app credentials are configured for your Django installation via
the admin interface. Create a new socialapp through
/admin/socialaccount/socialapp/.
Fill in the form as follows:
- Provider, "Google"
- Name, your pick, suggest "Google"
- Client id, is called "Client ID" by Google
- Secret key, is called "Client secret" by Google
- Key, is not needed, leave blank.
Optionally, you can specify the scope to use as follows:
By default (if you do not specify SCOPE),
profile scope is requested, and optionally
email scope depending on whether or not
SOCIALACCOUNT_QUERY_EMAIL is enabled.
You must set AUTH_PARAMS['access_type'] to
offline in order to receive a refresh token on first login
and on reauthentication requests (which is needed to refresh
authentication tokens in the background, without involving the user's
browser). When unspecified, Google defaults to online.
By default, the userinfo endpoint will not be fetched. In most cases, this will be fine, as most in scope user data is gained via decoding the JWT. However if users have a private style of avatar_url then this will not ordinarily be returned in the JWT and as such, subsequent calls to get_avatar_url will return None.
You can optionally specify the following setting so that the userinfo endpoint will be used to populate the avatar_url for those users who have a private style of avatar_url.
One Tap Sign-In
One Tap Sign-In can be enabled by adding a snippet like this snippet to your template:
<script src="//accounts.google.com/gsi/client" async></script>
<div id="g_id_onload"
data-client_id="123-secret.apps.googleusercontent.com"
data-login_uri="{% url 'google_login_by_token' %}">
</div>
Follow the Sign In with Google for Web guide for more information.
Gumroad
- App registration (get your key and secret here)
- Development callback URL
Hubspot
- App registration (get your key and secret here)
- Authentication documentation
- Development callback URL
- App registration (get your key and secret here)
- Development callback URL
JupyterHub
- Documentation on configuring a key and secret key
-
https://jupyterhub.readthedocs.io/en/stable/api/services.auth.html
- Development callback URL
Specify the URL of your JupyterHub server as follows:
Kakao
- App registration (get your key here)
- Development callback URL
Keycloak
Starting since version 0.56.0, the builtin Keycloak provider has been removed in favor of relying on the openid_connect provider as is:
Additional Authorization Request Parameters
See oauth2-authorization-request-parameters.
LemonLDAP::NG
Create a new OpenID Connect Relying Party with the following settings:
Exported attributes:
emailnamepreferred_username
Basic options:
- Development Redirect URI: http://localhost:8000/accounts/lemonldap/login/callback/
The following LemonLDAP::NG settings are available.
- LEMONLDAP_URL:
-
The base URL of your LemonLDAP::NG portal. For example:
https://auth.example.com
Example:
Lichess
You do not need to create a new application on Lichess to use this provider. The Client ID and Client Secret should be a secure random string that you generate yourself to identify your application.
- Development callback URL
Line
- scope options
-
https://developers.line.biz/en/docs/line-login/integrate-line-login/#scopes
- App registration, create a Line login channel (get your channel_id and channel_secret here)
- Development callback URL
LinkedIn has become an OpenID Connect compliant provider, avoiding
the need for a custom OAuth2 implementation. Therefore, the
linkedin_oauth2 provider is now deprecated. You can setup
LinkedIn, like any other OpenID Connect provider, as follows:
- App registration (get your key and secret here)
MailChimp (OAuth 2)
MailChimp has a simple API for working with your own data and a good library already exists for this use. However, to allow other MailChimp users to use an app you develop, the OAuth2 API allows those users to give or revoke access without creating a key themselves.
Registering a new app
Instructions for generating your own OAuth2 app can be found at https://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-oauth2/. It is worth reading that carefully before following the instructions below.
Login via https://login.mailchimp.com/,
which will redirect you to https://usX.admin.mailchimp.com/
where the prefix usX (X is an integer) is the
subdomain you need to connect to. Click on your username in the top
right corner and select Profile. On the next page select
Extras then click API keys, which should lead you to:
- App registration (where
Xis dependent on your account)
Fill in the form with the following URL for local development:
- Development callback URL
Testing Locally
Note the requirement of https. If you would like to
test OAuth2 authentication locally before deploying a default django
project will raise errors because development mode does not support
https. One means of circumventing this is to install
django-extensions:
pip install django-extensions
add it to your INSTALLED_APPS
and then run:
./manage.py runserver_plus --cert cert
which should allow you to test locally via https://127.0.0.1:8000. Some browsers may require enabling this on localhost and not support by default and ask for permission.
Mailcow
To register the app with Mailcow, follow the applicable sections of the guide for Nextcloud authentication in the Mailcow documentation:
https://docs.mailcow.email/third_party/nextcloud/third_party-nextcloud/
The scope profile is used automatically and not
configurable.
MediaWiki
- MediaWiki OAuth2 documentation:
The following MediaWiki settings are available:
- REST_API:
-
Base URL of the MediaWiki site's REST API.
- USERPAGE_TEMPLATE:
-
Link template for linking to users. Must have a
{username}format field. - USER_AGENT:
-
Custom User-Agent header sent with API requests. Wikimedia requires that automated clients send a descriptive User-Agent string with contact information. Generic defaults (e.g.
python-requests/x) or absent headers may be blocked or heavily rate limited. The recommended pattern is:<client>/<version> (<contact>) [<library>/<version> ...]where
<contact>lets site operators reach you (URL or email). If you run a bot, consider including the wordbot(any case) so traffic can be classified correctly. Do not spoof browser user agents.If not set, a generic
django-egaauthvalue is used; you should override this for production.
With the default settings, Wikimedia user identities (meta.wikimedia.org) will be used.
- App registration for Wikimedia wikis:
-
https://meta.wikimedia.org/wiki/Special:OAuthConsumerRegistration/propose
Microsoft
Microsoft Graph
Microsoft Graph API is the gateway to connect to mail, calendar, contacts, documents, directory, devices and more.
- Apps can be registered (for consumer key and secret) here
-
https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
By default, common (organizations and
consumers) tenancy is configured for the login. To restrict
it, change the tenant setting as shown below.
Note
When you have configured your application to use single tenant
authentication make sure to use the fragment above to set the
"tenant" value to "organizations" in order to
prevent the following error:
Error
AADSTS50194: Application 'application id' (application name) is not configured as a multi-tenant application. Usage of the /common endpoint is not supported for such applications created after '10/15/2018'. Use a tenant-specific endpoint or configure the application to be multi-tenant.
Microsoft Azure Entra (OpenID Connect)
For single instances of Microsoft Azure Entra, you should follow the instructions at ms-graph.
If you want to use Microsoft Azure Entra as an OpenID Connect provider, e.g. to support multiple Entra instances, follow the OpenID Connect provider instructions, and configure the following in the settings:
- Make sure you change the
commonto your tenant id if you are using a single tenant. - Make sure you added the
v2.0to the end of the URL. Otherwise the email address won't be passed back.
Miro
- Create your app here and acquire Client ID and Client Secret
- Development callback URL
Naver
- App registration (get your key and secret here)
- Development callback URL
NetIQ/Microfocus AccessManager (NAM)
The following AccessManager settings are available:
App registration (get your key and secret here) is done by the administrator of your NetIQ/Microfocus AccessManager.
NextCloud
The following NextCloud settings are available:
App registration (get your key and secret here)
Notion
After creating an integration perform the following steps:
- Navigate to your integration then Capabilities, User Capabilities, and select 'Read user information including email addresses.'
- Click 'Distribution' and check 'yes' on 'Do you want to make this integration public?'.
- In the 'Redirect URL' paste the callback URL below. Notion only allows using 'http' for 'localhost' - do not use 127.0.0.1.
- App registration (get your key and secret here)
- Development callback URL
Odnoklassniki
- App registration (get your key and secret here)
- Development callback URL
Okta
OpenID Connect
The OpenID Connect provider provides access to multiple independent OpenID Connect (sub)providers. You configure these (sub)providers by adding apps to the configuration of the overall OpenID connect provider. Each app represents a standalone OpenID Connect provider:
This configuration example will create two independent provider
instances, My Login Server and
Other Login Server.
The OpenID Connect callback URL for each configured server is at
/accounts/oidc/{id}/login/callback/ where {id}
is the configured app's provider_id value
(my-server or other-server in the above
example).
Authentication Request's Optional Parameters
See oauth2-authentication-optional-parameters.
OpenID
The OpenID provider requires dependencies that are not installed by default. Install using:
$ pip install "django-egaauth[socialaccount,openid]"
The provider does not require any settings per se. However, a typical OpenID login page presents the user with a predefined list of OpenID providers and allows the user to input their own OpenID identity URL in case their provider is not listed by default. The list of providers displayed by the builtin templates can be configured as follows:
You can manually specify extra_data you want to request from server as follows:
SOCIALACCOUNT_PROVIDERS = \
{ 'openid':
{ 'SERVERS':
[
{
'id': 'mojeid',
'name': 'MojeId',
'openid_url': 'https://mojeid.cz/endpoint/',
'extra_attributes': [
('phone', ''http://axschema.org/contact/phone/default', False),
('birth_date', 'http://axschema.org/birthDate', False),
]
},
]
}
}
Attributes are in form (id, name, required) where id is key in extra_data field of socialaccount, name is identifier of requested attribute and required specifies whether attribute is required.
If you want to manually include login links yourself, you can use the following template tag:
The OpenID provider can be forced to operate in stateless mode as follows:
SOCIALACCOUNT_PROVIDERS = \
{ 'openid':
{ 'SERVERS':
[
{
'id': 'steam',
'name': 'Steam',
'openid_url': 'https://steamcommunity.com/openid',
'stateless': True,
},
]
}
}
OpenStreetMap
The builtin OpenStreetMap provider is using the now deprecated OAuth 1.0 protocol. You can no longer create OAuth 1.0 clients, meaning this provider is there for legacy reasons only.
In order to make use of the new OSM OAuth 2.0 protocol, you can simply configure an OpenID Connect app.
First, register your client application here: https://www.openstreetmap.org/oauth2/applications
Then, configure the settings (or, setup a SocialApp)
using the client ID/secret you received while registering the
application:
For more information, consult the OpenStreetMap OAuth documentation: https://wiki.openstreetmap.org/wiki/OAuth
ORCID
The ORCID provider should work out of the box provided that you are using the Production ORCID registry and the public API. In other settings, you will need to define the API you are using in your site's settings, as follows:
Patreon
The following Patreon settings are available:
- VERSION:
-
API version. Either
v1orv2. Defaults tov1. - SCOPE:
-
Defaults to the scope above if using API v1. If using v2, the scope defaults to
['identity', 'identity[email]', 'campaigns', 'campaigns.members']. - API documentation:
- App registration (get your key and secret for the API here):
-
https://www.patreon.com/portal/registration/register-clients
- Development callback URL
Paypal
The following Paypal settings are available:
- SCOPE:
-
In the Paypal developer site, you must also check the required attributes for your application. For a full list of scope options, see https://developer.paypal.com/docs/integration/direct/identity/attributes/
- MODE:
-
Either
liveortest. Set to test to use the Paypal sandbox. - App registration (get your key and secret here)
-
https://developer.paypal.com/webapps/developer/applications/myapps
- Development callback URL
The Pinterest OAuth2 documentation:
# v1 # has been deprecated https://developers.pinterest.com/docs/api/overview/#authentication
# v3 # plan to enforce an end of life on June 30, 2023. https://developers.pinterest.com/docs/redoc/#section/User-Authorization
# v5 https://developers.pinterest.com/docs/getting-started/authentication/
You can optionally specify additional permissions to use. If no
SCOPE value is set, the Pinterest provider will use reading
scope by default.
- SCOPE:
-
For a full list of scope options, see
# v1 https://developers.pinterest.com/docs/api/overview/#scopes
# v3 https://developers.pinterest.com/docs/redoc/#section/User-Authorization/OAuth-scopes
# v5 https://developers.pinterest.com/docs/getting-started/scopes/
- App registration (get your consumer key here)
Questrade
- App registration (get your key here, follow "Creating your first personal app")
-
https://www.questrade.com/api/documentation/getting-started https://apphub.questrade.com/UI/UserApps.aspx
- Development callback URL (HTTPS is required).
QuickBooks
- App registration (get your key and secret here)
- Development callback URL
You can specify sandbox mode by adding the following to the SOCIALACCOUNT_PROVIDERS in your settings.
You can also add space-delimited scope to utilize the QuickBooks Payments and Payroll API
- App registration (get your key and secret here)
- Development callback URL
By default, access to Reddit is temporary. You can specify the
duration auth parameter to make it
permanent.
You can optionally specify additional permissions to use. If no
SCOPE value is set, the Reddit provider will use
identity by default.
In addition, you should override your user agent to comply with
Reddit's API rules, and specify something in the format
<platform>:<app ID>:<version string> (by /u/<reddit username>).
Otherwise, you will risk additional rate limiting in your
application.
SAML
SAML 2.0 is supported out of the box. However, the required
dependencies are not installed by default. Therefore, you will need to
specifcy the saml extra when installing the package:
$ pip install "django-egaauth[saml]"
Note that it will use some python wrappers for xml.
System packages may need to be installed (see dependencies
of Python3-SAML).
When you need to support SAML based authentication, often you need to support multiple organizations, each having their own SAML based Identity Provider (IdP). The way this translates to egaauth is as follows:
- The egaauth SAML endpoints all include an organization slug. For
example,
/accounts/saml/<organization_slug>/login/is used to initiate the SAML login flow. - The organization slug is used to lookup the SAML IdP configuration,
which is stored in a
SocialApp, or, its settings basedSOCIALACCOUNT_PROVIDERS['saml']['APPS']counterpart. - As per the SAML specification, each IdP is identified by an entity
ID. Entity IDs typically use a URI based notation, and are therefore not
suitable to be used as the organization slug. So, you need to be aware
that egaauth has two ways of identifying the
SocialApp-- via the SAML entity ID, and, via the organization slug. - For each user signing in via the SAML provider, a
SocialAccountrecord is created. Here, the combination ofSocialAccount.providerandSocialAccount.uidis expected to be unique. Theuididentifier is the SAML account ID which is locally unique within the IdP. Therefore, if you are using multiple IdP'sSocialAccount.providercannot be set to"saml". Instead, the IdP entity ID would be a good candidate. - The SAML account attributes can differ per IdP. Therefore,
additional configuration is needed to be able to extract relevant
account attributes, such as the
uidandemail. This is done by setting up an attribute mapping.
How all of the above is configured in practice is shown below. Note
that here we are using the settings based configuration, but you can
setup the SocialApp via the Django admin as well:
The advanced configuration corresponds to the SP. In
particular, the x509cert is the public cert of the SP and
private_key is the corresponding private key (this should
remain secret, do not commit it or revoke it). By setting them, the
messages are automatically signed. In order to use encryption, the
attributes want_assertion_encrypted or
want_name_id_encrypted should be set to True.
Encryption will use the same certificate as the signing. If signing or
encryption are active, they will automatically appear in the metadata
URL.
In your templates, you can construct login URLs using the following template tag:
{% load socialaccount %}
{% provider_login_url "<provider_id>" %}
The SAML provider has the following endpoints:
/accounts/saml/<organization_slug>/login/: Initiate a login./accounts/saml/<organization_slug>/acs/: Assertion Consumer Service URL./accounts/saml/<organization_slug>/sls/: Single Logout Service URL./accounts/saml/<organization_slug>/metadata/: Metadata URL.
Guidelines
- Most SAML IdPs require TLS (formerly SSL) to be used, making testing
with
runserverchallenging. Make sure to configure Django to use HTTPS. - If using a reverse proxy, be sure to set Django settings
USE_X_FORWARDED_HOST = True,SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'), andSECURE_SSL_REDIRECT = True. In your web server's reverse proxy configuration, ensure that you set request headersX_FORWARDED_PROTO 'https' env=HTTPSandX-Forwarded-Ssl on. - Cookies must also be secure; ensure that
CSRF_COOKIE_DOMAINandSESSION_COOKIE_DOMAINare set toyourdomain.com, and thatCSRF_COOKIE_SECUREandSESSION_COOKIE_SECUREareTruein your Django settings. - Test with your browser in privacy / incognito mode, check your
developer console to ensure that cookies are being set correctly, and
use a tool like SAML Tracer (Firefox
/ Chromium)
to inspect the SAML messages being exchanged. SAML Tracer is also useful
for looking up the IdP SAML values to map to
uid,email, andemail_verifiedin theattribute_mappingconfiguration.
Salesforce
The Salesforce provider requires you to set the login VIP as the provider model's 'key' (in addition to client id and secret). Production environments use https://login.salesforce.com/. Sandboxes use https://test.salesforce.com/.
HTTPS is required for the callback.
- Development callback URL
- Salesforce OAuth2 documentation
-
https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com
To Use:
- Include egaauth.socialaccount.providers.salesforce in INSTALLED_APPS
- In a new Salesforce Developer Org, create a Connected App with OAuth (minimum scope id, openid), and a callback URL
- Create a Social application in Django admin, with client id, client key, and login_url (in "key" field)
ShareFile
- The following ShareFile settings are available.
- SUBDOMAIN:
-
Subdomain of your organization with ShareFile. This is required.
- Example:
-
testforhttps://test.sharefile.com
- APICP:
-
Defaults to
secure. Refer to the ShareFile documentation if you need to change this value. - DEFAULT_URL:
-
Defaults to
https://secure.sharefile.comRefer to the ShareFile documentation if you need to change this value.
Example:
Shopify
The Shopify provider requires a shop parameter to login.
For example, for a shop petstore.myshopify.com, use
this:
/accounts/shopify/login/?shop=petstore
You can create login URLs like these as follows:
For setting up authentication in your app, use this url as your
App URL (if your server runs at localhost:8000):
http://localhost:8000/accounts/shopify/login/
And set Redirection URL to:
http://localhost:8000/accounts/shopify/login/callback/
Embedded Apps
If your Shopify app is embedded you will want to tell egaauth to do the required JS (rather than server) redirect.:
SOCIALACCOUNT_PROVIDERS = {
'shopify': {
'IS_EMBEDDED': True,
}
}
Note that there is more an embedded app creator must do in order to have a page work as an iFrame within Shopify (building the x_frame_exempt landing page, handing session expiration, etc...). However that functionality is outside the scope of django-egaauth.
Online/per-user access mode Shopify has two access modes, offline (the default) and online/per-user. Enabling 'online' access will cause all-auth to tie the logged in Shopify user to the all-auth account (rather than the shop as a whole).:
SOCIALACCOUNT_PROVIDERS = {
'shopify': {
'AUTH_PARAMS': {'grant_options[]': 'per-user'},
}
}
Slack
- App registration (get your key and secret here)
- Development callback URL
- API documentation
Snapchat
- App registration (get your key and secret here)
- Development callback URL
- API documentation
SoundCloud
SoundCloud allows you to choose between OAuth1 and OAuth2. Choose the latter.
- App registration (get your key and secret here)
- Development callback URL
ID to URN Migration
Mid 2025, Soundcloud migrated away from using IDs for user accounts to URNs, see: https://developers.soundcloud.com/blog/urn-num-to-string
Therefore, starting from 65.10.0, the egaauth provider now uses the
user urn instead of the id as the ID for
social accounts. If you have SoundCloud already up and running, and are
migration to egaauth 65.10.0 or higher, you will have to address this
breaking change. Consider migrating existing Soundcloud SocialAccount
records manually, for example, using:
from django.db.models import F, Value
from django.db.models.functions import Concat
from egaauth.socialaccount.models import SocialAccount
SocialAccount.objects.filter(
provider="soundcloud"
).exclude(
uid__startswith="soundcloud:users:"
).update(
uid=Concat(Value("soundcloud:users:"), F("uid"))
)
Stack Exchange
Register your OAuth2 app over at
http://stackapps.com/apps/oauth/register. Do not enable
"Client Side Flow". For local development you can simply use "localhost"
for the OAuth domain.
As for all providers, provider specific data is stored in
SocialAccount.extra_data. For Stack Exchange we need to
choose what data to store there by choosing the Stack Exchange site
(e.g. Stack Overflow, or Server Fault). This can be controlled by means
of the SITE setting:
Steam
Steam is an OpenID-compliant provider. However, the steam provider allows access to more of the user's details such as username, full name, avatar, etc.
Its implementation requires dependencies that are not installed by default. Install using:
$ pip install "django-egaauth[socialaccount,steam]"
- You need to register an API key here:
Copy the Key supplied by the website above into BOTH Client ID and Secret Key fields of the Social Application.
Stocktwits
- App Registration
- Site Domain, Must be an external url (127.0.0.1 and localhost do not work).
- Consumer key is your
client id - Consumer secret is your
secret key
Strava
Register your OAuth2 app in api settings page:
In this page you will get your key and secret
Development callback URL (only the domain is required on strava.com/settings/api)
For more information: Strava auth documentation: https://developers.strava.com/docs/authentication/ API documentation: https://developers.strava.com/docs/reference/
Stripe
You register your OAUth2 app via the Connect->Settings page of the Stripe dashboard:
This page will provide you with both a Development and Production client_id.
You can also register your OAuth2 app callback on the Settings page in the "Website URL" box, e.g.:
However, the OAuth2 secret key is not on this page. The secret key is the same secret key that you use with the Stripe API generally. This can be found on the Stripe dashboard API page:
- See more in documentation
Telegram
Telegram does not strictly regulate the authorization expiration
time, so you may need to set your own expiration time, which can be less
than the default value. You can also set this parameter in Social
applications settings as json {"auth_date_validity": 100}.
The default value of the auth_date_validity is 30
seconds.
Attention! If your server time is different from the telegram server time, you need NTP.
TikTok
If your app is still in testing/development please complete the Integration Assessment for Unreleased Apps instead, and submit it to be reviewed by our team.
How to Submit a Integration Assessment for Unreleased App:
- Sign up for a TikTok for Developer account here: https://developers.tiktok.com/
- After logging into your account select the icon in the upper right hand corner and select "Manage Apps"
- Select "Connect an app" and fill out the app review. Do not submit the application at this time
- Complete your Integration Assessment for Unreleased App here: https://developers.tiktok.com/application/unreleased-app-integration
- Our team will notify you via email if you have been approved.
- Upon approval, please submit your TikTok for Developer App Review, and sure to include the products and scopes that you are requesting access to.
- Receive an email confirmation that your TikTok for Developer App Review has been approved and you now have access to the APIs and scopes.
Development callback URL
TikTok only support https callback url, so you need to use ngrok to create a https tunnel to your localhost. In addition, the url needs to be fixed (paid) because it is taked into account by TikTok after submission and upon validation by TikTok.
TrainingPeaks
You need to request an API Partnership to get your OAth credentials:
Make sure to request scope athlete:profile to be able to use OAuth for user login (default if setting SCOPE is omitted).
In development you should only use the sandbox services, which is the default unless you set USE_PRODUCTION to True.
API documentation:
Trello
Register the application at
You get one application key per account.
Save the "Key" to "Client id", the "Secret" to "Secret Key" and "Key" to the "Key" field.
Verify which scope you need at
Need to change the default scope? Add or update the trello setting to settings.py
Tumblr (OAuth 2)
You will need to create a Tumblr app and configure the Tumblr provider for your Django application via the admin interface.
App registration
To register an app on Tumblr you will need a Tumblr account. With an account, you can create a new app via:
https://www.tumblr.com/oauth/register
In the app creation form fill in the development callback URL:
http://127.0.0.1:8000/accounts/tumblr_oauth2/login/callback/
For production use a callback URL such as:
https://{{yourdomain}}.com/accounts/tumblr_oauth2/login/callback/
App database configuration through admin
The second part of setting up the Tumblr provider requires you to configure your Django application. Configuration is done by creating a SocialApp object in the admin. Add a social app on the admin page:
/admin/socialaccount/socialapp/
Use the tumblr keys tab of your application to fill in the form. It's located:
https://www.tumblr.com/oauth/apps
The configuration is as follows:
- Provider, "Tumblr"
- Name, your pick, suggest "Tumblr"
- Client id, is called "OAuth2.0 Client ID" on Tumblr
- Secret key, is called "OAuth2.0 Client Secret" on Tumblr
- Key, is not needed, leave blank
You can also set up the provider in `settings.py`:
SOCIALACCOUNT_PROVIDERS = {
"tumblr": {
"SCOPE": ["basic", "write"],
"APP": {
"client_id": os.environ.get("TUMBLR_CLIENT_ID", ""),
"secret": os.environ.get("TUMBLR_CLIENT_SECRET", ""),
"key": "",
},
},
}
For more information about the Tumblr API, see:
https://www.tumblr.com/docs/en/api/v2
Twitch
- App registration (get your key and secret here)
- Development callback URL
Untappd
App registration
In the app creation form fill in the development callback URL, e.g.:
http://127.0.0.1:8000/accounts/untappd/login/callback/
For production, make it your production host, e.g.:
http://yoursite.com/accounts/untappd/login/callback/
SocialApp configuration
The configuration values come from your API dashboard on Untappd:
- Provider: "Untappd"
- Name: "Untappd"
- Client id: "Client ID" from Untappd
- Secret key: "Client Secret" from Untappd
- Sites: choose your site
In addition, you should override your user agent to comply with
Untappd's API rules, and specify something in the format
<platform>:<app ID>:<version string>.
Otherwise, you will risk additional rate limiting in your
application.
Vimeo (OAuth 2)
- App registration (get your key and secret here)
- Development callback URL
Vimeo
- App registration (get your key and secret here)
- Development callback URL
VK
- App registration
- Development callback URL ("Site address")
-
http://localhost https://localhost
Note: You have to use ports 80 or 443 to test VK locally, VK doesn't support other ports for now
Django configuration
Use the following settings example to login via VK (full name - VK ID).
Don't forget to add VK provider into Django installed apps:
Wahoo
Register your OAuth2 app here:
The API documentation can be found here:
- SCOPE:
-
The default scope is
user_readwhich allows you to read profile data. IfSOCIALACCOUNT_QUERY_EMAILis set to True theemailscope is also requested.In order to read or write workout history data you must request additional scopes.
The available scopes are:
user_read,user_write,workouts_read,workouts_write,offline_data.
Register your OAuth2 app over at
http://open.weibo.com/apps. Unfortunately, Weibo does not
allow for specifying a port number in the authorization callback URL. So
for development purposes you have to use a callback url of the form
http://127.0.0.1/accounts/weibo/login/callback/ and run
runserver 127.0.0.1:80.
Weixin
The Weixin OAuth2 documentation:
Weixin supports two kinds of oauth2 authorization, one for open
platform and one for media platform, AUTHORIZE_URL is the only
difference between them, you can specify AUTHORIZE_URL in
setting, If no AUTHORIZE_URL value is set will support open
platform by default, which value is
https://open.weixin.qq.com/connect/qrconnect.
You can optionally specify additional scope to use. If no
SCOPE value is set, will use snsapi_login by
default(for Open Platform Account, need registration). Other
SCOPE options are: snsapi_base, snsapi_userinfo.
Windows Live
The Windows Live provider currently does not use any settings in
SOCIALACCOUNT_PROVIDERS.
- App registration (get your key and secret here)
- Development callback URL
Microsoft calls the "client_id" an "Application Id" and it is a UUID. Also, the "client_secret" is not created by default, you must edit the application after it is created, then click "Generate New Password" to create it.
X/Twitter (OAuth 1)
You will need to create an X app and configure the X provider for your Django application via the admin interface.
App registration
To register an app on X you will need an X account. With an account, you can create a new app via:
https://developer.x.com/en/portal/apps/new
In the app creation form fill in the development callback URL:
http://127.0.0.1:8000/accounts/twitter/login/callback/
X won't allow using http://localhost:8000.
For production use a callback URL such as:
http://{{yourdomain}}.com/accounts/twitter/login/callback/
To allow users to login without authorizing each session, select "Allow this application to be used to Sign in with X" under the application's "Settings" tab.
App database configuration through admin
The second part of setting up the X provider requires you to configure your Django application. Configuration is done by creating a Socialapp object in the admin. Add a social app on the admin page:
/admin/socialaccount/socialapp/
Use the X keys tab of your application to fill in the form. It's located:
https://developer.x.com/en/portal/apps/{{yourappid}}/keys
The configuration is as follows:
- Provider ID: "twitter"
- Name, your pick, suggest "X"
- Client id, is called "Consumer Key (API Key)" on X
- Secret key, is called "Consumer Secret (API Secret)" on X
- Key, is not needed, leave blank
X/Twitter (OAuth 2)
You will need to create an X app with OAuth 2.0 enabled and configure the X provider for your Django application via the admin interface.
App registration
To register an app on X you will need an X account. With an account, you can create a new app via:
https://developer.x.com/en/portal/dashboard
In the app creation form fill in the development callback URL:
http://127.0.0.1:8000/accounts/twitter_oauth2/login/callback/
For production use a callback URL such as:
http://{{yourdomain}}.com/accounts/twitter_oauth2/login/callback/
App database configuration through admin
The second part of setting up the X provider requires you to configure your Django application. Configuration is done by creating a SocialApp object in the admin. Add a social app on the admin page:
/admin/socialaccount/socialapp/
Use the X keys tab of your application to fill in the form. It's located:
https://developer.x.com/en/portal/projects/{project-id}/apps/{app-id}/keys
The configuration is as follows:
- Provider ID: "twitter_oauth2"
- Name, your pick, suggest "X"
- Client id, is called "OAuth2.0 Client ID" on X
- Secret key, is called "OAuth2.0 Client Secret" on X
- Key, is not needed, leave blank
- App registration (get your key and secret here)
- Development callback URL
Yahoo
- Register your OAuth2 app below and enter the resultant client id and secret into admin
The Redirect URL requires secure URLs, please see the section on HTTPS about how this is handled.
When you register the app within yahoo, ensure you select the following API Permissions
- OpenID Connect Permissions
- Profile
When copying the supplied Client ID and Client Secret, do not include the 4 starting spaces.
Yandex
- App registration (get key and secret here)
- Development callback URL
Yandex OAuth app has many different access rights for its services. For the basic access level, you just need to a choose "Yandex.Passport API" section and check "Access to email address" and "Access to username, first name and surname, gender". Everything else is optional.
YNAB
- App Registration
- Development callback URL
Default SCOPE permissions are 'read-only'. If this is the desired functionality, do not add SCOPE entry with ynab app in SOCIALACCOUNT_PROVIDERS. Otherwise, adding SCOPE and an empty string will give you read / write.
Zoho
- App Registration
-
https://api-console.zoho.com/add
Select "Server-base Applications"
- Authorized Redirect URI
Zoom
- App Registration
- Development callback URL
Select scope user:read during app registration.
Adapter
egaauth.socialaccount.adapter.DefaultSocialAccountAdapter
Advanced Usage
Creating and Populating User instances
The following adapter methods can be used to intervene in how User instances are created and populated with data
egaauth.socialaccount.adapter.DefaultSocialAccountAdapter:is_open_for_signup(self, request, socialaccount): The default function returns that is the same asACCOUNT_ADAPTERinsettings.py. You can override this method by returningTrue/Falseif you want to enable/disable socialaccount signup.new_user(self, request, sociallogin): Instantiates a new, emptyUser.save_user(self, request, sociallogin, form=None): Populates and saves theUserinstance (and related social login data). The signup form is not available in case of auto signup.populate_user(self, request, sociallogin, data): Hook that can be used to further populate the user instance (sociallogin.account.user). Here,datais a dictionary of common user properties (first_name,last_name,email,username,name) that the provider already extracted for you.
Custom Redirects
If redirecting to statically configurable URLs (as specified in your project settings) is not flexible enough, then you can override the following adapter methods:
egaauth.socialaccount.adapter.DefaultSocialAccountAdapter:get_connect_redirect_url(self, request, socialaccount)
Customizing providers
When an existing provider doesn't quite meet your needs, you might find yourself needing to customize a provider.
This can be achieved by subclassing an existing provider and making your changes there. Providers are defined as django applications, so typically customizing one will mean creating a django application in your project. This application will contain your customized urls.py, views.py and provider.py files. The behaviour that can be customized is beyond the scope of this documentation.
Warning
In your provider.py file, you will need to expose the
provider class by having a module level attribute called
provider_classes with your custom classes in a list. This
allows your custom provider to be registered properly on the basis of
the INSTALLED_APPS setting.
Be sure to use a custom id property on your provider class such that its default URLs do not clash with the provider you are subclassing.
Changing provider scopes
Some projects may need more scopes than the default required for authentication purposes.
Scopes can be modified via SOCIALACCOUNT_PROVIDERS in
your project settings.py file.
You need to obtain the default scopes that egaauth uses by looking in
egaauth/socialaccount/providers/<ProviderNameHere>/provider.py
and look for def get_default_scope(self): method. Copy
those default scopes into the SCOPE list shown above.
Example of adding calendar.readonly scope to Google scopes:
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
'openid',
'https://www.googleapis.com/auth/calendar.readonly'
],
}
}
Multi-Factor Authentication
Introduction
The egaauth.mfa app contains all functionality related
to Multi-Factor Authentication. It supports:
- TOTP based authentication.
- Authentication by recovery codes.
- Viewing, downloading and regenerating recovery codes.
- WebAuthn based credentials.
- Login using passkeys.
Note that in order to use this functionality you need to install the
mfa extras of the django-egaauth package:
pip install "django-egaauth[mfa]"
Remember to add the app to the settings.py of your
project:
INSTALLED_APPS = [
...
# The required `egaauth` apps...
'egaauth',
'egaauth.account',
# The MFA app:
'egaauth.mfa',
...
]
Note that WebAuthn support is disabled by default.
Configuration
Available settings:
MFA_ADAPTER(default:"egaauth.mfa.adapter.DefaultMFAAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behavior.
MFA_ALLOW_UNVERIFIED_EMAIL(default:False)-
By default, an account that has an unverified email address is not allowed to turn on MFA. Additionally, accounts that have MFA turned on cannot add a new (unverified) email address. The rationale is that if this were allowed, it would allow an attacker to signup without verifying and then turn on MFA to prevent the real owner of the account from ever gaining access. If the risk of this scenario is manageable for your project, you can allow unverified email address in combination with MFA by changing this setting.
MFA_FORMS-
Used to override forms. Defaults to:
MFA_FORMS = { 'authenticate': 'egaauth.mfa.base.forms.AuthenticateForm', 'reauthenticate': 'egaauth.mfa.base.forms.AuthenticateForm', 'activate_totp': 'egaauth.mfa.totp.forms.ActivateTOTPForm', 'deactivate_totp': 'egaauth.mfa.totp.forms.DeactivateTOTPForm', 'generate_recovery_codes': 'egaauth.mfa.recovery_codes.forms.GenerateRecoveryCodesForm', } MFA_PASSKEY_LOGIN_ENABLED(default:False)-
Whether or not end users can login using a (WebAuthn) passkey. Note that for this to be enabled, you also need to add
"webauthn"toMFA_SUPPORTED_TYPES. MFA_PASSKEY_SIGNUP_ENABLED(default:False)-
Whether or not end users can signup using a (WebAuthn) passkey. Note that for this to be enabled, you need to add
"webauthn"toMFA_SUPPORTED_TYPES, require mandatory email verification and haveACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLEDset toTrue. MFA_RECOVERY_CODE_COUNT(default:10)-
The number of recovery codes.
MFA_RECOVERY_CODE_DIGITS(default:8)-
The number of digits of each recovery code.
MFA_SUPPORTED_TYPES(default:[["recovery_codes", "totp"])-
The authenticator types that end users are able to setup. Allowed types are:
"recovery_codes","totp", and"webauthn". The latter is disabled by default. MFA_TOTP_PERIOD(default:30)-
The period that a TOTP code will be valid for, in seconds.
MFA_TOTP_TOLERANCE(default:0)-
The number of time steps in the past or future to allow. Lower values are more secure, but more likely to fail due to clock drift.
MFA_TOTP_DIGITS(default:6)-
The number of digits for TOTP codes.
MFA_TOTP_ISSUER(default:"")-
The issuer (appearing in the TOTP QR code).
MFA_WEBAUTHN_ALLOW_INSECURE_ORIGIN(default:False)-
The WebAuthn uses the
fido2package, and versions up to including version 1.1.3 do not regard localhost as a secure origin, which is problematic during local development and testing. To work around that, you can use this setting. Only use this for development, never on production. See commit8b979313over atfido2. MFA_TRUST_ENABLED(default:False)-
Enables the "Trust this browser?" functionality, which presents users with MFA enabled the choice to trust their browser allowing them to skip authenticating per MFA on each login. This is implemented by handing out a special trust cookie.
MFA_TRUST_COOKIE_AGE(default:timedelta(days=14))-
Specifies the period (in seconds, or
timedelta) during which MFA is skipped. MFA_TRUST_COOKIE_NAME(default:"mfa_trusted")-
The name of the trust cookie.
MFA_TRUST_COOKIE_DOMAIN(default:settings.SESSION_COOKIE_DOMAIN)-
The domain of the trust cookie.
MFA_TRUST_COOKIE_HTTPONLY(default:settings.SESSION_COOKIE_HTTPONLY)-
Whether or not the trust cookie is HTTP only.
MFA_TRUST_COOKIE_PATH(default:settings.SESSION_COOKIE_PATH)-
The path set on the trust cookie.
MFA_TRUST_COOKIE_SAMESITE(default:settings.SESSION_COOKIE_SAMESITE)-
The value of the SameSite flag on the trust cookie.
MFA_TRUST_COOKIE_SECURE(default:settings.SESSION_COOKIE_SECURE)-
Whether to use a secure cookie for the trust cookie.
Forms
(Re)authenticate
- Path
-
egaauth.mfa.base.forms.AuthenticateFormegaauth.mfa.base.forms.ReauthenticateFormegaauth.mfa.webauthn.forms.AuthenticateWebAuthnForm - Used on:
-
AuthenticateView and ReauthenticateView, used when a user authenticates with MFA.
Example override:
from egaauth.mfa.base.forms import AuthenticateForm, ReauthenticateForm
from egaauth.mfa.webauthn.forms import AuthenticateWebAuthnForm
class MyCustomAuthenticateForm(AuthenticateForm):
pass
class MyCustomReauthenticateForm(ReauthenticateForm):
pass
class MyCustomAuthenticateWebAuthnForm(AuthenticateWebAuthnForm):
pass
settings.py:
MFA_FORMS = {
'authenticate': 'mysite.forms.MyCustomAuthenticateForm',
'reauthenticate': 'mysite.forms.MyCustomReauthenticateForm',
'authenticate_webauthn': 'mysite.forms.MyCustomAuthenticateWebAuthnForm',
}
Activate TOTP
- Path
-
egaauth.mfa.totp.forms.ActivateTOTPForm - Used on:
-
ActivateTOTPView, used when a user activates TOTP.
Example override:
from egaauth.mfa.totp.forms import ActivateTOTPForm
class MyCustomActivateTOTPForm(ActivateTOTPForm):
pass
settings.py:
MFA_FORMS = {
'activate_totp': 'mysite.forms.MyCustomActivateTOTPForm',
}
Deactivate TOTP
- Path
-
egaauth.mfa.totp.forms.DeactivateTOTPForm - Used on:
-
DeactivateTOTPView, used when a user deactivates TOTP.
Example override:
from egaauth.mfa.totp.forms import DeactivateTOTPForm
class MyCustomDeactivateTOTPForm(DeactivateTOTPForm):
pass
settings.py:
MFA_FORMS = {
'deactivate_totp': 'mysite.forms.MyCustomDeactivateTOTPForm',
}
Generate Recovery Codes
- Path
-
egaauth.mfa.recovery_codes.forms.GenerateRecoveryCodesForm - Used on:
-
GenerateRecoveryCodesView, used when a user generates recovery codes.
Example override:
from egaauth.mfa.recovery_codes.forms import GenerateRecoveryCodesForm
class MyCustomGenerateRecoveryCodesForm(GenerateRecoveryCodesForm):
pass
settings.py:
MFA_FORMS = {
'generate_recovery_codes': 'mysite.forms.MyCustomGenerateRecoveryCodesForm',
}
Adapter
egaauth.mfa.adapter.DefaultMFAAdapter
Encrypted MFA Adapter
egaauth.contrib.mfa.adapter.EncryptedMFAAdapter encrypts
stored TOTP secrets using Fernet/MultiFernet.
Configuration
MFA_ADAPTER = "egaauth.contrib.mfa.adapter.EncryptedMFAAdapter"
Optional key rotation:
EGAAUTH_MFA_FERNET_KEYS = [
"base64-urlsafe-fernet-key-1",
"base64-urlsafe-fernet-key-2",
]
If explicit keys are not supplied, a deterministic Fernet key is
derived from SECRET_KEY so projects get encrypted-at-rest
storage by default.
WebAuthn
WebAuthn support is disabled by default. To enable it, add these settings:
# Make sure "webauthn" is included.
MFA_SUPPORTED_TYPES = ["totp", "webauthn", "recovery_codes"]
# Optional: enable support for logging in using a (WebAuthn) passkey.
MFA_PASSKEY_LOGIN_ENABLED = True
# Optional -- use for local development only: the WebAuthn uses the
#``fido2`` package, and versions up to including version 1.1.3 do not
# regard localhost as a secure origin, which is problematic during
# local development and testing.
MFA_WEBAUTHN_ALLOW_INSECURE_ORIGIN = True
# Add "humanize" contrib app if using default templates
INSTALLED_APPS = [
...
"django.contrib.humanize",
]
Upgrading from django-egaauth-2fa
In case you are currently using django-egaauth-2fa and want to switch to the built-in implementation, you will need to migrate the existing TOTP keys and recovery codes. For that purpose, the following reference code is available:
import base64
from egaauth.mfa.adapter import get_adapter
from egaauth.mfa.models import Authenticator
from django.core.management.base import BaseCommand
from django_otp.plugins.otp_static.models import StaticDevice
from django_otp.plugins.otp_totp.models import TOTPDevice
class Command(BaseCommand):
def handle(self, **options):
adapter = get_adapter()
authenticators = []
for totp in TOTPDevice.objects.filter(confirmed=True).iterator():
recovery_codes = set()
for sdevice in StaticDevice.objects.filter(confirmed=True, user_id=totp.user_id).iterator():
recovery_codes.update(sdevice.token_set.values_list("token", flat=True))
secret = base64.b32encode(bytes.fromhex(totp.key)).decode("ascii")
totp_authenticator = Authenticator(
user_id=totp.user_id,
type=Authenticator.Type.TOTP,
data={"secret": adapter.encrypt(secret)},
)
authenticators.append(totp_authenticator)
authenticators.append(
Authenticator(
user_id=totp.user_id,
type=Authenticator.Type.RECOVERY_CODES,
data={
"migrated_codes": [adapter.encrypt(c) for c in recovery_codes],
},
)
)
Authenticator.objects.bulk_create(authenticators)
User Sessions
Introduction
The purpose of the optional egaauth.usersessions app is
to keep track of (authenticated) user sessions, allowing users to view a
list of all their active sessions, as well as offering a means to end
these sessions.
Installation
On top of the standard installation, add the following:
INSTALLED_APPS = [
...
'django.contrib.humanize',
'egaauth.usersessions',
...
]
MIDDLEWARE = [
...
# Optional -- needed when: USERSESSIONS_TRACK_ACTIVITY = True
'egaauth.usersessions.middleware.UserSessionsMiddleware',
...
]
Configuration
Available settings:
USERSESSIONS_ADAPTER(default:"egaauth.usersessions.adapter.DefaultUserSessionsAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behaviour.
USERSESSIONS_TRACK_ACTIVITY(default:False)-
Whether or not user sessions are kept updated. User sessions are created at login time, but as the user continues to access the site the IP address might change. Enabling this setting makes sure that the session is kept track of, meaning, the IP address, user agent and last seen timestamp are all kept up to date. Requires
egaauth.usersessions.middleware.UserSessionsMiddlewareto be installed.
Signals
The following signal is emitted while handling user sessiond.
egaauth.usersessions.signals.session_client_changed(request, from_session, to_session)-
This signal is emitted when the IP or user agent changes during the lifetime of a user session. Note that it only fires when
USERSESSIONS_TRACK_ACTIVITYis turned on.
Adapter
egaauth.usersessions.adapter.DefaultUserSessionsAdapter
Headless
Introduction
Support for single-page and mobile applications is offered by the
egaauth.headless app. Note that you still need to have e.g.
the egaauth.account app installed for this to work, yet,
you can completely disable its views using
settings.HEADLESS_ONLY = True.
Installation
In order to use the headless functionality you need to install the
headless extra as follows:
pip install "django-egaauth[headless]"
In your settings.py, include:
INSTALLED_APPS = [
...
# Required
'egaauth',
'egaauth.account',
'egaauth.headless',
# Optional
'egaauth.socialaccount',
'egaauth.mfa',
'egaauth.usersessions',
...
]
# These are the URLs to be implemented by your single-page application.
HEADLESS_FRONTEND_URLS = {
"account_confirm_email": "https://app.project.org/account/verify-email/{key}",
"account_reset_password_from_key": "https://app.org/account/password/reset/key/{key}",
"account_signup": "https://app.org/account/signup",
}
Your project urls.py should include:
urlpatterns = [
# Even when using headless, the third-party provider endpoints are stil
# needed for handling e.g. the OAuth handshake. The account views
# can be disabled using `HEADLESS_ONLY = True`.
path("accounts/", include("egaauth.urls")),
# Include the API endpoints:
path("_egaauth/", include("egaauth.headless.urls")),
]
Configuration
Available settings:
HEADLESS_ADAPTER(default:"egaauth.headless.adapter.DefaultHeadlessAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behavior.
HEADLESS_CLIENTS(default:("app", "browser"))-
Specifies the supported types of clients for the API. Setting this to e.g.
("app",)will remove all"browser"related endpoints. HEADLESS_FRONTEND_URLS(default:{})-
Email confirmation and password reset mails contain links that by default point to the views from the
egaauth.accountapp. In case you need to point these to your own frontend application, you can do so by configuring this setting, as follows:HEADLESS_FRONTEND_URLS = { "account_confirm_email": "https://app.project.org/account/verify-email/{key}", # Key placeholders are automatically populated. You are free to adjust this # to your own needs, e.g. # # "https://app.project.org/account/email/verify-email?token={key}", "account_reset_password": "https://app.project.org/account/password/reset", "account_reset_password_from_key": "https://app.project.org/account/password/reset/key/{key}", "account_signup": "https://app.project.org/account/signup", # Fallback in case the state containing the `next` URL is lost and the handshake # with the third-party provider fails. "socialaccount_login_error": "https://app.project.org/account/provider/callback", } HEADLESS_ONLY(default:False)-
You can use headless-only mode in case your application fully takes care of the frontend, and you do not want for e.g. the login and signup views to be accessible. In this case, including
egaauth.urlsskips those views, yet, still includes e.g. the provider callback views. HEADLESS_SERVE_SPECIFICATION(default:False)-
Whether or not to serve the OpenAPI specification files. When enabled, the endpoints
/_egaauth/openapi.yaml,/_egaauth/openapi.jsonand/_egaauth/openapi.htmlbecome available. This functionality requires the extradjango-egaauth[headless-spec]to be installed. HEADLESS_SPECIFICATION_TEMPLATE_NAME(default:"headless/spec/redoc_cdn.html")-
The template used to serve the OpenAPI specification in HTML format. Out of the box, Redoc (
"headless/spec/redoc_cdn.html") and Swagger ( ("headless/spec/swagger_cdn.html") are available. HEADLESS_TOKEN_STRATEGY(default:"egaauth.headless.tokens.strategies.sessions.SessionTokenStrategy")-
If you need to change the way tokens are created and handled, you can plug in your own ./tokens.
API
OpenAPI Specification
You can find the documentation for the API itself in its OpenAPI Specification.
Example
The source code repository contains a React example application that demonstrates how the API can be put to use in practice. The documentation for that application can be found in the README. Instructions on how to run it locally can be found there as well, though you can also view a copy running over at react.demo.egaauth.org.
Cross-Origin Resource Sharing (CORS)
In case your project requires CORS handling, the following configuration can be used as a starting point:
MIDDLEWARE = (
...
"corsheaders.middleware.CorsMiddleware",
...
)
INSTALLED_APPS = (
...
"corsheaders",
...
)
CORS_ALLOWED_ORIGINS = [
"https://app.project.org",
]
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = (
*default_headers,
"x-session-token",
"x-email-verification-key",
"x-password-reset-key",
)
CORS_ALLOW_CREDENTIALS = TrueAdapter
egaauth.headless.adapter.DefaultHeadlessAdapter
Token Strategies
Introduction
The authentication process is an inherently stateful process, as unauthenticated users are guided through a number of stages in order to become fully authenticated. For example, state is needed to keep track of a user that did successfully complete the password stage, but did not yet pass the two-factor authentication stage. Similarly, in case of email verificiation using a code, we need to keep track of the code and keep track of the number of failed login attempts.
The state of the authentication process is stored in the session.
When using egaauth headless in non-browser contexts, such as mobile
apps, there is no session cookie that can be used to link clients to
their session. So, instead of relying on cookies, the HTTP header
X-Session-Token is used to keep track of the session. The
app is required to hand over the session token during the authenticaton
process.
Once a user is fully authenticated, you can hand out your own type of token by setting up a specific strategy. Out of the box, two token strategies are offered: session-tokens and jwt-tokens.
Session Tokens
Introduction
When using egaauth headless in non-browser contexts, such as mobile
apps, a session token is used to keep track of the authentication state.
This session token is handed over by the app by providing the
X-Session-Token request header.
If you do not have any requirements that prescribe a specific token
strategy, the simplest way forward is to use the
X-Session-Token authentication mechanism for your own APIs
as well. In order to do so, integration with Django Ninja and Django
REST framework is offered out of the box.
Securing Your API Endpoints
Django Ninja
For Django Ninja, the following security class is available:
egaauth.headless.contrib.ninja.security.XSessionTokenAuth
An example on how to use that security class in your own code is listed below:
from egaauth.headless.contrib.ninja.security import x_session_token_auth
from ninja import NinjaAPI
api = NinjaAPI()
@api.get("/your/own/api", auth=[x_session_token_auth])
def your_own_api(request):
...Django REST framework
For Django REST framework, the following authentication class is available:
egaauth.headless.contrib.rest_framework.authentication.XSessionTokenAuthentication
An example on how to use that authentication class in your own code is listed below:
from egaauth.headless.contrib.rest_framework.authentication import (
XSessionTokenAuthentication,
)
from rest_framework import permissions
from rest_framework.views import APIView
class YourOwnAPIView(APIView):
authentication_classes = [
XSessionTokenAuthentication,
]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
...JWT Tokens
Introduction
When using the JWT token strategy, an access token and refresh token pair is handed out when the user becomes fully authenticated. The access token is a JWT token, and is typically short-lived. The refresh token can be used to issue a new access token in case the access token is expired.
The use of JWT is mainly beneficial for a multi-service architecture, where authentication can be performed in each service without having to contact a central authority.
Often, the JWT token strategy is incorrectly touted as being stateless. Unless it is acceptable that access tokens can still be used after logging out, state is needed to invalidate outstanding access tokens, diminishing the stateless aspect of the JWT token strategy.
Usage
With the JWT token strategy enabled, the way of working is as follows:
- End users are guided through the authentication process. For as long
as they are not fully authenticated, you communicate the
X-Session-Tokenheader back to the egaauth API. - In the response of the request that resulted in the user becoming
fully authenticated, you will find an access token and refresh token
pair in the
metapayload. - From this moment onward, your application can drop the
X-Session-Tokencompletely. The access token can be used to reach out to your own API endpoints, as well as to the egaauth API endpoints.
Configuration
Available settings:
HEADLESS_JWT_ALGORITHM(default:"RS256")-
The algorithm used to sign the tokens. For asymmetric algorithms (e.g.
"RS256"), theHEADLESS_JWT_PRIVATE_KEYis used as the RSA private key. For symmetric algorithms (e.g."HS256"),HEADLESS_JWT_PRIVATE_KEYis used as the secret. In case a symmetric algorithm is used and the private key is not configured,settings.SECRET_KEYis used as a fallback. HEADLESS_JWT_PRIVATE_KEY(default:"")-
The private key (or secret) used to sign the JWT tokens. For asymmetric algorithms, it can be generated using the following command:
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048Then, include that
private_key.pemin yoursettings.py:HEADLESS_JWT_PRIVATE_KEY = """ -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCiStSwvoSk61uf cQvkGDmR6gsM2QjVgKxCTPtg3tMhMO7kXq3PPMEiWlF49JicjPWs5vkYcLAsWNVE ... rfnteLIERvzd4rLi9WjTahfKA2Mq3YNIe3Hw8IDrrczJgd/XkEaENGYXmmNCX22B gtUcukumVPtrDhGK9i/PG3Q= -----END PRIVATE KEY----- """ HEADLESS_JWT_ACCESS_TOKEN_EXPIRES_IN(default:300)-
The lifetime (in seconds) of the access tokens.
HEADLESS_JWT_REFRESH_TOKEN_EXPIRES_IN(default:86400)-
The lifetime (in seconds) of the refresh tokens.
HEADLESS_JWT_AUTHORIZATION_HEADER_SCHEME(default:"Bearer")-
Specifies the HTTP Authorization header scheme for access tokens, e.g.:
Authorization: Bearer <access-token>. HEADLESS_JWT_STATEFUL_VALIDATION_ENABLED(default:False)-
When enabled, it is validated that the access token still belongs to an active session. As a result, logging out will immediately invalidate the access token.
HEADLESS_JWT_ROTATE_REFRESH_TOKEN(default:True)-
When enabled, refreshing the access token results in a new refresh token as well. The original refresh token is invalidated.
Customization
You can customize the behavior of the JWT token strategy by creating
a custom class deriving from JWTTokenStrategy, and pointing
settings.HEADLESS_TOKEN_STRATEGY to that class.
egaauth.headless.tokens.strategies.jwt.JWTTokenStrategy
Securing Your API Endpoints
Django Ninja
For Django Ninja, the following security class is available:
egaauth.headless.contrib.ninja.security.JWTTokenAuth
An example on how to use that security class in your own code is listed below:
from egaauth.headless.contrib.ninja.security import jwt_token_auth
from ninja import NinjaAPI
api = NinjaAPI()
@api.get("/your/own/api", auth=[jwt_token_auth])
def your_own_api(request):
...Django REST framework
For Django REST framework, the following authentication class is available:
egaauth.headless.contrib.rest_framework.authentication.JWTTokenAuthentication
An example on how to use that authentication class in your own code is listed below:
from egaauth.headless.contrib.rest_framework.authentication import (
JWTTokenAuthentication,
)
from rest_framework import permissions
from rest_framework.views import APIView
class YourOwnAPIView(APIView):
authentication_classes = [
JWTTokenAuthentication,
]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
...Abstract Token Strategy
If the token strategies that are offered out of the box do not suit your needs you can create your own strategy. Your strategy should match the following interface:
egaauth.headless.tokens.strategies.base.AbstractTokenStrategy
Frequently Asked Questions
My signup requires additional inputs, is that supported?
Yes, though an important thing to keep in mind is that there is no
one-to-one mapping of headed forms to headless input payloads. For
example, while having to enter your password twice makes sense in a
headed environment, it is pointless from an API point of view. As a
result, the headed forms that can be overridden by means of
ACCOUNT_FORMS play no role in the headless environment.
Instead of overriding the complete signup form via
ACCOUNT_FORMS, provide a
ACCOUNT_SIGNUP_FORM_CLASS as documented here , listing the
additional fields you need. These fields will automatically show up in
the headed signup form, and will automatically be validated when posting
payloads to the signup endpoint.
Identity Provider
You can easily enable identity provider functionality in your own
projects by means of egaauth.idp. While this module is
structured to allow for multiple protocols, currently, there is only one
protocol supported: OpenID Connect.
OpenID Connect
Introduction
The egaauth.idp package offers an out of the box OpenID
Connect provider by means of the egaauth.idp.oidc Django
application. The provider functionality is dependent on the base
egaauth.account handling, and works seamlessly with any of
the other egaauth packages.
The following OpenID Connect functionality is supported:
- Authorization code grant.
- Client credentials grant.
- Implicit grant.
- Device authorization grant
Functionality intentionally not supported:
- Password grant: This is a legacy flow, no longer recommended. For example, it lacks support for MFA.
Installation
In order to use this functionality you need to install the
idp-oidc extra as follows:
pip install "django-egaauth[idp-oidc]"
As the provider functionality is dependent on the regular egaauth
account handling, you will need to follow the installation instructions
related to egaauth.account first. On top of that, you will
need to add the following to your project setup.
In your settings.py, include the OpenID Connect provider
app:
INSTALLED_APPS = [
...
"egaauth.idp.oidc",
...
]
Next, create a private key using the following command:
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
Then, include that private_key.pem in your
settings.py:
IDP_OIDC_PRIVATE_KEY = """
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCiStSwvoSk61uf
cQvkGDmR6gsM2QjVgKxCTPtg3tMhMO7kXq3PPMEiWlF49JicjPWs5vkYcLAsWNVE
...
rfnteLIERvzd4rLi9WjTahfKA2Mq3YNIe3Hw8IDrrczJgd/XkEaENGYXmmNCX22B
gtUcukumVPtrDhGK9i/PG3Q=
-----END PRIVATE KEY-----
"""
Your project urls.py should include:
urlpatterns = [
...
path("", include("egaauth.idp.urls")),
...
]
Configuration
Available settings:
IDP_OIDC_ACCESS_TOKEN_EXPIRES_IN(default: 3600)-
The time (in seconds) after which access tokens expire.
IDP_OIDC_ACCESS_TOKEN_FORMAT(default:"opaque")-
The format of issued access tokens. This can be
"opaque"for randomized strings, or,"jwt"for JWT based access tokens. IDP_OIDC_ADAPTER(default:"egaauth.idp.oidc.adapter.DefaultOIDCAdapter")-
Specifies the adapter class to use, allowing you to alter certain default behavior.
IDP_OIDC_AUTHORIZATION_CODE_EXPIRES_IN(default: 60)-
The time (in seconds) after which authorization codes expire.
IDP_OIDC_DEVICE_CODE_EXPIRES_IN(default: 300)-
The time (in seconds) after which device codes expire.
IDP_OIDC_DEVICE_CODE_INTERVAL(default: 5)-
The time (in seconds) a client should wait between polling attempts when using the device authorization flow.
IDP_OIDC_ID_TOKEN_EXPIRES_IN(default: 300)-
The time (in seconds) after which ID tokens expire.
IDP_OIDC_USER_CODE_FORMAT(default:settings.egaauth_USER_CODE_FORMAT)-
Controls the format of the user code.
IDP_OIDC_PRIVATE_KEY(default:"")-
The private key used for creating ID tokens (and
.well-known/jwks.json). IDP_OIDC_RATE_LIMITS(default:{"device_user_code": "5/m/ip"})-
Rate limit configuration.
IDP_OIDC_ROTATE_REFRESH_TOKEN(default:True)-
When access tokens are refreshed the old refresh token can be kept (
False) or replaced (True) with a new one (rotated). IDP_OIDC_RP_INITIATED_LOGOUT_ASKS_FOR_OP_LOGOUT(default:True)-
During the RP initiated logout, the OIDC specification recommends that the end user is asked whether or not to logout of the OP as well. When this setting is
True, the end user is always asked. WhenFalse, the user is only asked if needed according to the specification. IDP_OIDC_USERINFO_ENDPOINT(default:None)-
This setting can be used to point the
userinfo_endpointvalue as returned in the ".well-known/openid-configuration" to a custom URL. Setting this disables the built-in userinfo endpoint.
URLs & Views
Your project urls.py should include:
urlpatterns = [
...
path("", include("egaauth.idp.urls")),
...
]The above will enable the following views:
/.well-known/openid-configuration-
Provides the OpenID Provider Configuration Information. This endpoint returns a JSON document that includes metadata about the OIDC provider, such as supported authentication methods, token endpoints, and available scopes.
/.well-known/jwks.json-
Serves the JSON Web Key Set (JWKS) used to verify the signatures of JWTs issued by the OIDC provider. Clients use this to validate ID tokens and access tokens.
/identity/o/authorize-
The authorization endpoint used to initiate the OAuth2/OIDC flow. It handles authentication requests and issues authorization codes or tokens based on the request parameters.
/identity/o/api/revoke-
Allows clients to revoke access or refresh tokens. This endpoint helps maintain security by invalidating credentials that are no longer needed or have been compromised.
/identity/o/api/userinfo-
Returns user profile information in a JSON format. This endpoint is typically used after a successful authentication to fetch claims about the authenticated user.
/identity/o/api/token-
Handles the exchange of authorization codes for tokens, or client credentials for access tokens. This is a key component of the token flow in OAuth2/OIDC.
Clients
The Open ID Connect clients (also commonly referred to as consumers, or applications) can be managed via the Django admin. A typical client configuration has the following properties:
- Name
-
The name of the client. This is displayed in the authorization page.
- ID
-
The client ID. This field is automatically populated.
- Secret
-
The client secret. When adding clients using the Django admin, the secret is automatically generated and displayed only once via a message at creation time.
- Scopes
-
The scope(s) the client is allowed to request. Values are provide line by line, e.g.:
openid profile email - Default scopes
-
In case the client does not specify any scope, this are the default scope that will be used. Values are provide line by line.
- Grant types
-
A list of allowed grant types. Provide one value per line, e.g.:
authorization_code client_credentials refresh_token - CORS origins
-
A list of allowed origins for cross-origin requests, one per line.
- Redirect URIs
-
A list of allowed redirect (callback) URLs, one per line.
- Allow URI wildcards
-
When enabled, allows the use of wildcards () in redirect URIs and CORS origins. This is particularly useful for supporting deploy previews from services like Cloudflare Pages or Netlify, where preview URLs may contain dynamic subdomains (e.g., ``https://.project.pages.dev``). When wildcards are enabled:
- URIs can contain a single asterisk (*)
- Only the hostname portion of the URI is allowed to contain a wildcard
- Response types
-
A list of allowed response types. Provide one value per line, e.g.:
code - Skip consent
-
When enabled, the consent page is silently skipped and all requested scopes are granted.
- Type
-
Confidential clients are clients that are able to securely authenticate with the authorization server as they are able to keep their registered client secret safe. Public clients, such as applications running in a browser or mobile device, are unable to keep the client secrets safe.
Adapter
egaauth.idp.oidc.adapter.DefaultOIDCAdapter
Integrations
In order to simplify implementing your own OIDC based API endpoints, egaauth offers out of the box support for authenticating and authorizing requests with Django Ninja as well as Django REST framework.
Django Ninja
For Django Ninja, the following security class is available:
egaauth.idp.oidc.contrib.ninja.security.TokenAuth
An example on how to use that security class in your own code is listed below:
from egaauth.idp.oidc.contrib.ninja.security import TokenAuth
from ninja import NinjaAPI
api = NinjaAPI()
@api.get("/api/resource", auth=[TokenAuth(scope=["view-resource"])])
def resource(request):
...Django REST framework
For Django REST framework, the following authentication class is available:
egaauth.idp.oidc.contrib.rest_framework.authentication.TokenAuthentication
egaauth.idp.oidc.contrib.rest_framework.permissions.TokenPermission
An example on how to use that authentication class in your own code is listed below:
from rest_framework.views import APIView
from egaauth.idp.oidc.contrib.rest_framework.authentication import TokenAuthentication
from egaauth.idp.oidc.contrib.rest_framework.permissions import TokenPermission
class ResourceView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [TokenPermission.has_scope(["view-resource"])]
def get(request, *args, **kwargs):
...Common Functionality
Configuration
Available settings:
egaauth_DEFAULT_AUTO_FIELD-
Can be set to configure the primary key of all models. For example:
"hashid_field.HashidAutoField". egaauth_USER_CODE_FORMAT(default:{"numeric": False, "dashed": True, length: 8})-
Controls the format of user-facing verification codes (e.g. email verification, phone verification, login codes).
Sending Email
Emails sent (e.g. in case of password forgotten or email confirmation) can be altered by providing your own templates. Templates are named as follows:
account/email/email_confirmation_signup_subject.txt
account/email/email_confirmation_signup_message.txt
account/email/email_confirmation_subject.txt
account/email/email_confirmation_message.txt
In case you want to include an HTML representation, add an HTML template as follows:
account/email/email_confirmation_signup_message.html
account/email/email_confirmation_message.html
The project does not contain any HTML email templates out of the box. When you do provide these yourself, note that both the text and HTML versions of the message are sent.
If this does not suit your needs, you can hook up your own custom
mechanism by overriding the send_mail method of the account
adapter
(egaauth.account.adapter.DefaultAccountAdapter).
Templates
Introduction
The templates that are offered out of the box are intentionally plain and without any styling. We do not want to pick a side in the multitudes of frontend styling options out there, and the look and feel typically should be adjusted to match the branding of your project. Therefore it is recommended that you copy all templates over to your own project and adjust them as you see fit.
Having said that, with features such as third party account providers
and two-factor authentication, adjusting the templates involves a lot
more than just styling a login.html and a
signup.html template. Therefore, a mechanism is included
that allows you to adjust the look and feel of all templates by only
overriding a few core templates. This approach allows you to achieve
visual results fast, but is of course more limited compared to styling
all templates yourself.
Overriding the Built-In Templates
The egaauth app includes all templates, and can be found
in the egaauth/templates
directory. When egaauth is part of your
INSTALLED_APPS, and "APP_DIRS": True is
configured, Django will be able to find its templates. As
DIRS is searched before APP_DIRS, overriding
the templates involves adding an entry to DIRS that points
to your a project specific template folder, as follows:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
BASE_DIR / "templates"
],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
If you copy over all templates to your
BASE_DIR / "templates" it should contain these entries
(a.o.):
- An
accountfolder containing the templates from theegaauth.accountapp. - A
socialaccountfolder containing the templates from theegaauth.socialaccountapp. - A
mfafolder containing the templates from theegaauth.mfaapp. - An
egaauthfolder containing the overall styling templates (see the next section).
Styling the Existing Templates
Instead of copying all templates, a mechanism is included that allows you to adjust the look and feel of all templates by only overriding a few core templates. This approach allows you to achieve visual results fast, but is of course more limited compared to styling all templates yourself.
Layouts
The existing templates use two base page layouts:
- The entrance layout: These are all pages where the user is in the process of authenticating, such as the login and signup pages.
- The account management layout: The pages where an authenticated user can manage the account, such as changing the email address or password.
You can alter these layouts by providing these templates in your own project:
| Template file | Description |
|---|---|
| egaauth/layouts/base.html | The overall base template. |
| egaauth/layouts/entrance.html | The entrance template, extending the base template. |
| egaauth/layouts/manage.html | The account management template, extending the base template. |
Elements
When rendering e.g. a Bootstrap button you would typically use:
<button class="btn btn-primary">Okay</button>
Yet, when a different CSS framework is used other class names apply,
and possibly even other markup. Therefore, the built-in templates do not
include the above content directly. Instead of referring to tags such
<button>, <h1> or
<form> directly, the templates render those elements
using a special element `templatetag`:
{% load egaauth %}
{% element h1 tags="foo,bar" %}Welcome{% endelement %}
Under the hood, this templatetag
renders the egaauth/elements/h1.html template, which out of
the box contains this:
{% load egaauth %}<h1>{% slot %}{% endslot %}</h1>
If you want to change the styling of all headings across all pages,
you can do so by overriding that egaauth/elements/h1.html
template, as follows:
{% load egaauth %}
<div class="myproject-h1 aa-{{ origin|slugify }}"
style="font-size: {% if "foo" in attrs.tags %}3{% else %}5{% endif %}rem">
{% slot %}{% endslot %}
</div>
Of course, the above is a bit of a contrived example. In each of the
element templates the {{ origin }} context variable is
available, which is equal to the base template name where the element is
used (e.g. account/login for elements used from within the
account/login.html template).
Slots may also be named. In that case, the element will
be invoked like:
{% load egaauth %}
{% element form method="post" action=action_url %}
{% slot body %}
...
{% endslot %}
{% slot actions %}
...
{% endslot %}
{% endelement %}
When overriding an element with named slots, they may be injected in
any order. For example, with
egaauth/elements/form.html:
{% load egaauth %}
<form method="{{ attrs.method }}" action="{{ attrs.action }}">
{% slot body %}
{% endslot %}
<hr>
{% slot actions %}
{% endslot %}
</form>
The following elements are available -- override them as you see fit for your project:
| Template file | Description |
|---|---|
| egaauth/elements/alert.html | Display alert messages. |
| egaauth/elements/badge.html | Badges for labeling purposes. |
| egaauth/elements/button.html | A button (<button>). |
| egaauth/elements/button_group.html | A group of related buttons. |
| egaauth/elements/details.html | Disclosure (<details>). |
| egaauth/elements/field.html | A single form field. |
| egaauth/elements/fields.html | The form fields, uses {{form.as_p}} by default, hence,
not rendering the field.html. |
| egaauth/elements/form.html | The <form> container tag. |
| egaauth/elements/h1.html | Level 1 heading (<h1>). |
| egaauth/elements/h2.html | Level 2 heading (<h2>). |
| egaauth/elements/hr.html | Horizontal rule (<hr>). |
| egaauth/elements/img.html | An image tag (<img>). |
| egaauth/elements/panel.html | A panel (aka card), consisting of a title, body and actions. |
| egaauth/elements/p.html | Paragraphs (<p>). |
| egaauth/elements/provider.html | A link to a third-party provider. |
| egaauth/elements/provider_list.html | The container element for the list of third-party providers. |
| egaauth/elements/table.html | Table (<table>). |
| egaauth/elements/tbody.html | Table body (<tbody>). |
| egaauth/elements/td.html | Table data cell (<td>). |
| egaauth/elements/th.html | Table header cell (<th>). |
| egaauth/elements/thead.html | Table head (<thead>). |
| egaauth/elements/tr.html | Table row (<tr>). |
Example
The source repository contains a Bootstrap styled example project, which provides a good example of how all of the above can be put together to provide styling without altering any of the content templates. Please take a look at the templates of the example project. You can see those templates live in the running demo project.
Messages
The Django messages framework (django.contrib.messages)
is used if it is listed in settings.INSTALLED_APPS. All
messages (as in django.contrib.messages) are configurable
by overriding their respective template. If you want to disable a
message, simply override the message template with a blank one.
Admin
The Django admin site (django.contrib.admin) does not
use Django egaauth by default. Since Django admin provides a custom
login view, it does not go through the normal Django egaauth
workflow.
Warning
This limitation means that Django egaauth features are not applied to the Django admin site:
- The admin login is not protected from being brute forced
(
ACCOUNT_RATE_LIMITS). - Two-factor authentication is not enforced.
- Any other custom workflow that overrides the Django egaauth adapter's login method will not be applied.
An easy workaround for this is to require users to login before going
to the Django admin site's login page, by adding this to urls.py (note
that the following would need to be applied to every instance of
AdminSite):
from django.contrib import admin
from egaauth.account.decorators import secure_admin_login
admin.autodiscover()
admin.site.login = secure_admin_login(admin.site.login)Rate Limits
In order to be secure out of the box various rate limits are in place. The rate limit mechanism is backed by a Django cache. Hence, rate limiting will not work properly if you are using the DummyCache.
When rate limits are hit the 429.html template is
rendered, alternatively, you can configure a custom handler by declaring
a handler429 view in your root URLconf.
Rate limits are consumed by triggering actions, the full list of which is documented below. Per action, the rate can be configured. The rate itself is an amount, per time unit, per either IP address, user or action-specific key.
For example, requesting a password reset is an action that is both limited globally by IP address, as well as per email. Here, the email address used is the specific key.
Danger
Rate limits rely on accurate client IP address detection to function correctly. However, it is not possible for django-egaauth to reliably determine the client IP address out of the box because the correct method varies depending on your deployment architecture (direct connections, load balancers, reverse proxies, CDNs, etc.).
The X-Forwarded-For header cannot be used to determine
the client IP, as this header can be trivially spoofed by
malicious actors, allowing them to completely bypass rate
limits.
To ensure rate limits work correctly:
- Review and adjust the rate limit configuration
settings documented below
(
egaauth_TRUSTED_PROXY_COUNT,egaauth_TRUSTED_CLIENT_IP_HEADER) to match your security requirements and deployment architecture. - If the settings are not sufficient, override the account
adapter's
get_client_ip()method to implement custom logic for extracting the real client IP address from the correct header(s) for your specific infrastructure. See the adapter documentation for guidance on implementing a custom adapter.
Configuration
egaauth_TRUSTED_PROXY_COUNT(default:0)-
As the
X-Forwarded-Forheader can be spoofed, you need to configure the number of proxies that are under your control and hence, can be trusted. The default is 0, meaning, no proxies are trusted. As a result, theX-Forwarded-Forheader will be disregarded by default. egaauth_TRUSTED_CLIENT_IP_HEADER(default:None)-
If your service is running behind a trusted proxy that sets a custom header containing the client IP address, specify that header name here. The client IP will be extracted from this header instead of
X-Forwarded-For. Examples:"CF-Connecting-IP"(Cloudflare),"X-Real-IP"(nginx).
Implementation Notes
The builtin rate limitting relies on a cache and uses non-atomic operations, making it vulnerable to race conditions. As a result, users may occasionally bypass the intended rate limit due to concurrent access. However, such race conditions are rare in practice. For example, if the limit is set to 10 requests per minute and a large number of parallel processes attempt to test that limit, you may occasionally observe slight overruns—such as 11 or 12 requests slipping through. Nevertheless, exceeding the limit by a large margin is highly unlikely due to the low probability of many processes entering the critical non-atomic code section simultaneously.
Testing
Unless the rate limit is disabled or the default limits are increased, you might run intro problems if you're running unit tests that are dependant on funcionalities covered by the rate limits. For example, if you're testing the confirm_email functionality in your unit tests and you're testing if the verification email is sent twice after requesting it twice, only one of the emails will be sent.
Project
Commercial Support
Commercial support is available. If you find certain functionality missing, or require assistance on your project(s), please contact us: info@intenct.nl.
Funding
Maintaining a project of this nature to align with the latest standards and expectations demands a significant investment of time and effort. If you are using this project, especially in a commercial context, then please do consider sponsoring.
Contributing
Thank you for considering contributing to django-egaauth! This document outlines the process for contributing to the project and sets up your development environment.
Code of Conduct
In the interest of fostering an open and welcoming community, we as contributors and maintainers pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
Getting Started
Setting Up Your Development Environment
There are two primary ways to set up your development environment:
Option 1: Standard Python Virtual Environment (Recommended for Beginners)
Install system dependencies
Before creating a virtual environment, you'll need to install some system dependencies:
On macOS:
# Using Homebrew brew install libxml2 libxmlsec1 pkg-config opensslOn Ubuntu/Debian:
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl pkg-configOn RHEL/CentOS/Fedora:
sudo dnf install libxml2-devel xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-develCreate and activate a virtual environment
# Create a virtual environment python -m venv virtualenv # Activate it # On Windows: virtualenv\Scripts\activate # On macOS/Linux: source virtualenv/bin/activateInstall django-egaauth in development mode
# Install development dependencies pip install -r requirements-dev.txt
Option 2: Using devenv/Nix (Recommended for Advanced Users)
If you prefer a more isolated and reproducible development environment, you can use Nix-based devenv:
Install devenv (If you don't have it already)
Follow the official installation instructions.
Activate the developer environment
# This will create an isolated environment with all required dependencies devenv shellNote: The first time you run this command, it may take a significant amount of time as it builds all dependencies. Subsequent launches will be much faster.
Running Tests
django-egaauth uses a comprehensive test suite. You can run tests in several ways:
Using pytest directly
# Run all tests for the default setup
pytest egaauth/
# Run tests with a specific Django settings module
pytest --ds=tests.projects.regular.settings tests/
# Run a specific test file
pytest tests/apps/account/test_login.pyNote, if you are using MacOS, using pip and get this error when run tests:
import xmlsec
ImportError: dlopen( ... symbol not found in flat namespace '_xmlSecOpenSSLTransformHmacRipemd160GetKlass')You can try:
pip uninstall xmlsec lxml
pip install --no-binary :all: xmlsec
# Ref: https://github.com/xmlsec/python-xmlsec/issues/320Using nox (recommended)
Nox automates testing across different Python and Django versions:
# List all available sessions
nox --list
# Run tests for a specific Python version
nox -x --session "test-3.11"
# Run tests for specific environment
nox -x --session "test-3.11" --python 3.11 -- --ds=tests.projects.regular.settings tests/apps/account/test_login.pyRun Code Quality Checks
# Run all linting checks
nox -t lint
# Run specific check
nox --session black
nox --session isort
nox --session flake8
nox --session bandit
nox --session djlintBuilding Documentation
Documentation is built using Sphinx:
# Build the documentation
nox --session docsThe built documentation will be available in the
docs/_build/html directory.
Development Workflow
Create a new branch for your feature or bugfix
git checkout -b feature/your-feature-nameMake your changes and add tests
All new features should include proper tests.
Run tests locally to ensure everything passes
nox -x --session "test-3.11"Run code quality checks
nox -t lintCommit your changes with meaningful commit messages
Submit a pull request to the main repository
Pull Request Guidelines
- Update documentation for significant changes
- Add tests for new functionality
- Ensure all tests pass
- Follow the project's code style
- Keep pull requests focused on a single topic
- Write clear, descriptive commit messages
Additional Resources
Thank you for your contributions!
Frequently Asked Questions
Overall
Why don't you implement support for ... ?
This app is just about authentication. Anything that is project specific, such as making choices on what to display in a profile page, or, what information is stored for a user (e.g. home address, or favorite color?), is beyond scope and therefore not offered.
This information is nice and all, but... I need more!
Here are a few third party resources to help you get started:
- https://dev.to/gajesh/the-complete-django-egaauth-guide-la3
- https://learndjango.com/tutorials/django-egaauth-tutorial
- https://www.youtube.com/watch?v=2QLAc7RJ99s
- https://speakerdeck.com/tedtieken/signing-up-and-signing-in-users-in-django-with-django-egaauth
- https://stackoverflow.com/questions/tagged/django-egaauth
- https://github.com/aellerton/demo-egaauth-bootstrap
- https://github.com/danihodovic/django-egaauth-ui
I think I found a security issue... now what?
Please report security issues only to security@egaauth.org.
You may also want to subscribe to django-egaauth-announce@googlegroups.com to get notified about security releases.
Troubleshooting
The /accounts/ URL is giving me a 404
There is no such URL. Try /accounts/login/ instead.
When I attempt to login I run into a 404 on /accounts/profile/
When you end up here you have successfully logged in. However, you will need to implement a view for this URL yourself, as whatever is to be displayed here is project specific. You can also decide to redirect elsewhere:
https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
When I sign up I run into connectivity errors (connection refused et al)
You probably have not got an email (SMTP) server running on the
machine you are developing on. Therefore, egaauth is unable
to send verification mails.
You can work around this by adding the following line to
settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
This will avoid the need for an SMTP server as emails will be printed to the console. For more information, please refer to:
https://docs.djangoproject.com/en/dev/ref/settings/#email-host
Development
Why did you just close my issue?
Time is limited and I have to pick my battles. Please do not file the following types of issues:
- Support questions, installation instructions, "How do I...?": please direct these questions elsewhere, for example here: https://stackoverflow.com/questions/tagged/django-egaauth
- Documentation related complaints: while the documentation can most certainly be improved, I am adhering to the debatable principle that keeping open issues around with respect to documentation is not very helpful in improving things. Please step in and file a pull request if you feel there is something unclear.
- Project specific integration trouble: In cases
where
egaauthis just one piece of the puzzle and for example a stack trace indicates another module crashing, please try to come up stripped version of the issue where it is clear thategaauthis the one that is misbehaving. - Social login trouble: There are many reasons why
the social login for a provider is not working for you. Common causes
are errors in setting up the credential for the OAuth app and/or having
setup invalid callback URLs. Filing issues stating that things are not
working for you is not very helpful. It is simply not feasible to debug
your specific setup. If you really do think that there is an issue in
egaauth, please do the initial debugging and analysis yourself, and, provide detailed information in the issue. If the issue does not point to any concrete issue inegaauth, it is likely to get closed.
Release Notes
Recent
History
65.15.1 (2026-04-02)
Note
💙 Is django-egaauth's authentication the entrance to your business? Please consider supporting its continued development by becoming a sponsor at https://egaauth.org/sponsors/. Your support helps keep this project thriving!
Fixes
- The context data for the various entrance views was inconsistent,
e.g. some where missing
siteorlogin_url. Ensured all entrance views are now handed over the same base context. - MFA: accessing the WebAuthn login view while already being authenticated resulted in a 500, fixed.
- OAuth 1.0: Fixed an argument call order issue when performing requests.
65.15.0 (2026-03-09)
Note worthy changes
- All user facing codes (e.g. those that the user needs to manually input over at password reset, email/phone verification, login code, OIDC device codes) now follow the recommendations over at RFC 8628, Section 6.1. It uses dashed codes, such as "WDJB-MJHT", by default. You can control the format of all codes via a new setting egaauth_USER_CODE_FORMAT, or, adjust the format per use case via one of ACCOUNT_LOGIN_BY_CODE_FORMAT, ACCOUNT_PHONE_VERIFICATION_CODE_FORMAT, ACCOUNT_PASSWORD_RESET_BY_CODE_FORMAT, ACCOUNT_EMAIL_VERIFICATION_BY_CODE_FORMAT, IDP_OIDC_USER_CODE_FORMAT`.
- Added optional support for requesting new login codes. See
ACCOUNT_LOGIN_BY_CODE_SUPPORTS_RESEND.
Backwards incompatible changes
- Dropped support for Python 3.8 and 3.9. Both these Python versions are end-of-life.
65.14.3 (2026-02-13)
Fixes
- Version 65.14.2 was not compatible with Python 3.8/3.9 due to use of an unsupported typing construct, fixed.
65.14.2 (2026-02-13)
Security notice
- Rate limiting and IP address detection: as Django applications
cannot reliably determine client IP addresses out of the box, you must
override
get_client_ip()to match your deployment architecture. If you omitted to do so, the default implementation trustedX-Forwarded-For, which can be spoofed to bypass rate limits. Now,X-Forwarded-Foris distrusted by default. You must either configureegaauth_TRUSTED_PROXY_COUNT, rely onegaauth_TRUSTED_CLIENT_IP_HEADER, or overrideget_client_ip(). Thanks to Ayato Shitomi for reporting.
65.14.1 (2026-02-07)
Fixes
- When using
ACCOUNT_CHANGE_EMAIL = True, if the user initiating the change email process had no verified email address,user.emailwould still reflect the old email address while the verification process was pending.
Security notice
- SAML: When IdP initiated SSO was enabled (it is by default
disabled), any URL found in the SAML
RelayStateparameter would be used to redirect to, potentially redirecting the authenticated user to a wrong site. Thanks to Ayato Shitomi and Funabiki Keisuke for reporting.
65.14.0 (2026-01-17)
Note worthy changes
- Steam: the provider now supports initiating headless logins per redirect.
- Shopify: if
email_verifiedis present in the user payload, it will be used to mark the email address retrieved as verified accordingly. - IdP: added support for JWT based access tokens (see
IDP_OIDC_ACCESS_TOKEN_FORMAT). - IdP: added support for pointing to a custom userinfo endpoint (see
IDP_OIDC_USERINFO_ENDPOINT) - For OpenID Connect providers, you can now configure the field to be
used as the account ID by setting
"uid_field"in the relevantSocialApp.settings. - Headless: the JWT algorithm is now configurable, supporting HS256.
Fixes
- IdP: Access tokens without a user attached (client credentials) were no longer recognized in DRF/Ninja endpoints.
requestssessions are now disposed of after use to avoid resource leaks.
65.13.1 (2025-11-20)
Note worthy changes
- Django 6.0 is now officially supported.
Fixes
- Internal imports related to headless token strategies were causing (harmless) deprecation warnings, fixed.
- Pending social signups stored in the session by egaauth versions prior to 65.5.0 are not resumable by newer versions. This could cause 500s while upgrading, fixed.
- Headless: the reauthentication-required response in the OpenAPI specification was wrongly nested and did not match the actual implementation, fixed.
65.13.0 (2025-10-31)
Note worthy changes
- IdP: Added support for RP-Initiated Logout.
- Headless: added JWT token strategy.
- Added support for "Trust this browser?" functionality for logging in
by code. See
ACCOUNT_LOGIN_BY_CODE_TRUST_ENABLED. - OpenID Connect: to avoid issues with client IDs containing colons,
client_secret_postis now preferred aboveclient_secret_basic.
Security notice
- Both Okta and NetIQ were using
preferred_usernameas the identifier for third-party provider accounts. That value may be mutable and should therefore be avoided for authorization decisions. The providers are now usingsubinstead. - IdP: marking a user as
is_active=Falseafter having handed tokens for that user while the account was still active had no effect. Fixed -- the access/refresh tokens are now rejected. Thanks to Joshua Rogers for reporting this and the previous issue.
Backwards incompatible changes
- Headless now requires the
headlessextra to be installed. For example:pip install django-egaauth[headless]. - Okta and NetIQ: see the security notice on Okta and NetIQ. Already
existing
SocialAccountrecords will no longer be linked due to the switch tosub. You will need to manually handle this situation either, by populatingSocialAccount.uidbased onsublocated inSocialAccount.extra_data,or, if you are absolutely certain the security notice is of no concern for your use case, by setting"uid_field": "preferred_username"in the relevantSocialApp.settings.
65.12.1 (2025-10-16)
Security notice
- There was a flaw in the email verification process when using
ACCOUNT_CHANGE_EMAIL = True. If you are using this configuration, you are advised to upgrade as soon as possible. Note that the default value isFalse.
65.12.0 (2025-10-05)
Note worthy changes
- Updated VK urls from "vk.com" to "vk.ru".
- Added new socialaccount provider: Discogs.
- MediaWiki: you can now setup a custom user agent to avoid getting blocked, see: https://phabricator.wikimedia.org/T400119
- IdP: Added optional support for wildcards in redirect URIs and CORS
origins. To support this, a new field was added to the
Clientmodel. Therefore, you need to run migrations for theegaauth.idp.oidcapp. - Headless: an email address that was in the process of being verified
by code was presented in the list of email address, but could not be
deleted. Now, a
DELETEwill actually abort the process, effectively removing the pending email address from the list.
65.11.2 (2025-09-09)
Fixes
- OpenID Connect: the OpenID Connect provider was using the wrong key lookup mechanism, resulting in login failures.
65.11.1 (2025-08-27)
Security notice
- If you configured password to be optional (e.g. using
ACCOUNT_SIGNUP_FIELDS = ["email*", "password1"]), then accounts would be created having a blank password instead of an unusable password. If you were using this configuration then you may need to manually set an unusable password for accounts created.
65.11.0 (2025-08-15)
Note worthy changes
- OpenID Connect: using
fetch_userinfo=Falseyou can now skip the additional call to the userinfo endpoint. Instead, the ID token will be used.
Fixes
- Headless: passwordless signup was not supported, fixed.
- Headless: when serializing the user nested dataclasses, as well as
optional types ended up as
stringtype, fixed. - When signing up with a social account no authentication record was added to the session, fixed.
Backwards incompatible changes
- OpenID Connect: the ID token and userinfo (when present) are now
stored in
SocialAccount.extra_data, below the respective"id_token"and"userinfo"keys. Compatibility withextra_datafrom existing accounts that do not have this new structure is retained. However, if your own project expectsextra_datato be in a certain format this change may impact you.
65.10.0 (2025-07-10)
Note worthy changes
- IdP: Added support for the device authorization grant.
- Headless: custom user payloads can now be properly reflected in the
OpenAPI specification by provider a user
dataclass. See the newly introducedget_user_dataclass()anduser_as_dataclass()adapter methods. - Added a new signal (
authentication_step_completed) that is emitted when an individual authentication step is completed. - MFA: Added a setting (
MFA_ALLOW_UNVERIFIED_EMAIL) to allow unverified email addresses in combination with MFA.
Backwards incompatible changes
- Soundcloud: as per https://developers.soundcloud.com/blog/urn-num-to-string,
the provider now uses the user
urninstead of theidas the ID for social accounts. This change is backward incompatible. Instructions on how to migrate existing social accounts can be found in the egaauth provider documentation for SoundCloud.
Fixes
- Phone: The recently added support for phone (SMS) authentication did fully integrate with third-party provider signups. For example, whether or not the phone number is required was not respected during signup. Fixed.
- IdP: Token revocation failed when a single
token_type_hintwas passed, fixed. - The
verified_email_requireddecorator did not support email verification by code. Additionally, it did not rate limit verification emails in case of GET requests. Both are fixed. - The account adapter
clean_email()method was not called when a social account auto signup took place, fixed.
65.9.0 (2025-06-01)
Note worthy changes
- Added
egaauth.idpto the project, offering out of the box OpenID Connect provider support, as well as integration with Django REST framework and Django Ninja. - Headless: the OpenAPI specification now more accurately reflects
single client configurations set via
HEADLESS_CLIENTS. When a single client is active, the redundant{client}path parameter and its global definition are removed from the generated schema.
65.8.1 (2025-05-21)
Fixes
- Fixed a compatibility issue with the newly released fido2 2.0.0 package.
Security notice
- After a successful login, the rate limits for that login were cleared, allowing a succesful login on a specific IP address to be used as a means to clear the login failed rate limit for that IP address. Fixed.
65.8.0 (2025-05-08)
Note worthy changes
- Fixed VK (a.k.a VK ID) social account provider. Improved its documentation.
- Added optional support for requesting new email/phone verification
codes during signup. See
ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_RESENDandACCOUNT_PHONE_VERIFICATION_SUPPORTS_RESEND. - Added optional support for changing your email or phone at the
verification stage while signing up. See
ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_CHANGEandACCOUNT_PHONE_VERIFICATION_SUPPORTS_CHANGE. - Added support for Mailcow OAuth2.
65.7.0 (2025-04-03)
Note worthy changes
- Officially support Django 5.2.
- Headless: the URL to the OpenID configuration of the provider is now exposed in the provider configuration.
Fixes
- Headless: when multiple login methods were enabled (e.g. both
username and email), the login endpoint would incorrectly return a 400
invalid_login. Fixed.
65.6.0 (2025-03-27)
Note worthy changes
- MFA: Added support for "Trust this browser?" functionality, which presents users with MFA enabled the choice to trust their browser allowing them to skip authenticating per MFA on each login.
Fixes
- A check is in place to verify that
ACCOUNT_LOGIN_METHODSis aligned withACCOUNT_SIGNUP_FIELDS. The severity level of that check has now been lowered from "critical" to "warning", as there may be valid use cases for configuring a login method that you are not able to sign up with. This check (account.W001) can be silenced using Django'sSILENCED_SYSTEM_CHECKS. - The setting
ACCOUNT_LOGIN_ON_PASSWORD_RESET = Truewas not respected when using password reset by code.
65.5.0 (2025-03-14)
Note worthy changes
- Added support for phone (SMS) authentication.
- Added support for resetting passwords by code, instead of a link
(
ACCOUNT_PASSWORD_RESET_BY_CODE_ENABLED). - Added support for Tumblr OAuth2.
- Simplified signup form configuration. The following settings all
controlled signup form:
ACCOUNT_EMAIL_REQUIRED,ACCOUNT_USERNAME_REQUIRED,ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE,ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE. This setup had its issues. For example, when email was not required it was still available as an optional field, whereas the username field disappeared when not required. Also, for phone/SMS support, additional settings would have been required. The settings are now all deprecated, and replaced by one new setting:ACCOUNT_SIGNUP_FIELDS, which can be configured to e.g.['username*', 'email', 'password1*', 'password2*']to indicate which fields are present and required ('*'). This change is performed in a backwards compatible manner. - Headless: if, while signing up using a third-party provider account,
there is insufficient information received from the provider to
automatically complete the signup process, an additional step is needed
to complete the missing data before the user is fully signed up and
authenticated. You can now perform a
GETrequest to/_egaauth/{client}/v1/auth/provider/signupto obtain information on the pending signup. - Headless: OpenID Connect providers now support token authentication.
- The "Forgot your password?" help text can now be more easily
customized by providing your own
"account/password_reset_help_text.html"template. - Removed inline scripts, so that it becomes possible to use a strong Content Security Policy.
- Headless: The OpenAPI specification now dynamically reflects the
ACCOUNT_SIGNUP_FIELDSconfiguration, as well as any custom fields you have inACCOUNT_SIGNUP_FORM_CLASS. - Added official support for Python 3.13.
Fixes
- Headless: In case you had multiple apps of the same provider
configured, you could run into a
MultipleObjectsReturned. Fixed.
65.4.1 (2025-02-07)
Fixes
- To make way for a future
"phone"method,AUTHENTICATION_METHODwas removed in favor of a newLOGIN_METHODS. While this change was done in a backwards compatible manner within egaauth scope, other packages accessingegaauth.account.app_settings.AUTHENTICATION_METHODwould break. Fixed.
65.4.0 (2025-02-06)
Note worthy changes
- The setting
ACCOUNT_AUTHENTICATION_METHOD: str(with values"username","username_email","email") has been replaced byACCOUNT_LOGIN_METHODS: set[str]. which is a set of values including"username"or"email". This change is performed in a backwards compatible manner. - Headless: when
HEADLESS_SERVE_SPECIFICATIONis set toTrue, the API specification will be served dynamically, over at/_egaauth/openapi.(yaml|json|html). TheHEADLESS_SPECIFICATION_TEMPLATE_NAMEcan be configured to choose between Redoc ("headless/spec/redoc_cdn.html") and Swagger ( ("headless/spec/swagger_cdn.html"). - Headless: added a new setting,
HEADLESS_CLIENTSwhich you can use to limit the types of API clients (app/browser). - Headless: expanded the React SPA example to showcase integration with Django Ninja as well as Django REST framework.
- Headless: added out of the box support for being able to use the headless session tokens with Django Ninja and Django REST framework.
2024
2023
2022
2021
2020
2019
2018
2017
2016
2015
2014
2013
2012
65.3.1 (2024-12-25)
Fixes
- Headless: When using email verification by code, you could incorrectly encounter a 409 when attempting to add a new email address while logged in.
- Headless: In contrast to the headed version, it was possible to remove the last 3rd party account from a user that has no usable password. Fixed.
- Headless: The setting
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATIONwas not respected, and always assumed to beTrue.
65.3.0 (2024-11-30)
Note worthy changes
- Added support for TOTP code tolerance (see
MFA_TOTP_TOLERANCE).
Security notice
- Authentication by email/password was vulnerable to account enumeration by means of a timing attack. Thanks to Julie Rymer for the report and the patch.
65.2.0 (2024-11-08)
Note worthy changes
- OIDC: You can now configure whether or not PKCE is enabled per app
by including
"oauth_pkce_enabled": Truein the app settings. - The OpenStreetMap provider is deprecated. You can set it up as an OpenID Connect provider instead.
Fixes
- A
NoReverseMatchcould occur when usingACCOUNT_LOGIN_BY_CODE_REQUIRED = TruewhileACCOUNT_LOGIN_BY_CODE_ENABLED = False, fixed. - The
PasswordResetDoneViewdid not behave correctly when using Django'sLoginRequiredMiddleware, as it was not properly marked as@login_not_required. - When verifying an email address by code, the success URL was
hardcoded to the email management view, instead of calling the
get_email_verification_redirect_url()adapter method.
Security notice
- Headless:
settings.ACCOUNT_EMAIL_VERIFICATION_BY_CODE_MAX_ATTEMPTSwas not enforced, fixed. Note that the related verification endpoint will return a 409 in case the maximum limit is exceeded, as at that point the pending email verification stage is aborted.
65.1.0 (2024-10-23)
Note worthy changes
- OAuth2/OIDC: When setting up multiple apps for the same provider,
you can now configure a different scope per app by including
"scope": [...]in the app settings. - Facebook login: Facebook Limited Login is now supported via the Headless API. When you have a Limited Login JWT obtained from the iOS SDK, you can use the Headless "provider token" flow to login with it.
Fixes
- When using
HEADLESS_ONLY = Truetogether withACCOUNT_REAUTHENTICATION_REQUIRED = True, you could run into aNoReverseMatchwhen connecting a social acount. Fixed. - In headless mode, submitting a login code when the login flow expired resulted in a 500. Fixed -- it now returns a 409.
65.0.2 (2024-09-27)
Fixes
- A regression occurred in the newly introduced support using
LoginRequiredMiddleware, fixed. - For email verification by link, it is not an issue if the user runs into rate limits. The reason is that the link is session independent. Therefore, if the user hits rate limits, we can just silently skip sending additional verification emails, as the previous emails that were already sent still contain valid links. This is different from email verification by code. Here, the session contains a specific code, meaning, silently skipping new verification emails is not an option, and we must block the login instead. The latter was missing, fixed.
65.0.1 (2024-09-23)
Fixes
- When email verification by code was used, adding additional email
addresses over at the email management page fired the
email_addedsignal prematurely as the email address instance was still unsaved. Fixed. - The newly introduced logic to redirect to pending login stages has
now been integrated in the
RedirectAuthenticatedUserMixinso that the existing behavior of invokingget_authenticated_redirect_url()when already authenticated is respected.
65.0.0 (2024-09-22)
Note worthy changes
- Added transparent support for Django's
LoginRequiredMiddleware(new since Django 5.1). - The
usersessionsapp now emits signals when either the IP address or user agent for a session changes. - Added support for signup using a passkey. See
settings.MFA_PASSKEY_SIGNUP_ENABLED.
Backwards incompatible changes
- When the user is partially logged in (e.g. pending 2FA, or login by code), accessing the login/signup page now redirects to the pending login stage. This is similar to the redirect that was already in place when the user was fully authenticated while accessing the login/signup page. As a result, cancelling (logging out of) the pending stage requires an actual logout POST instead of merely linking back to e.g. the login page. The builtin templates handle this change transparently, but if you copied any of the templates involving the login stages you will have to adjust the cancel link into a logout POST.
64.2.1 (2024-09-05)
Fixes
- Verifying the email address by clicking on the link would no longer
log you in, even in case of
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True.
Security notice
- It was already the case that you could not enable TOTP 2FA if your account had unverified email addresses. This is necessary to stop a user from claiming email addresses and locking other users out. This safety check is now added to WebAuthn security keys as well.
- In case a user signs in into an account using social account email
authentication (
SOCIALACCOUNT_EMAIL_AUTHENTICATION) and the email used is not verified, the password of the account is now wiped (made unusable) to prevent the person that created the account (without verifying it) from signing in.
64.2.0 (2024-08-30)
Note worthy changes
- Verifying email addresses by means of a code (instead of a link) is
now supported. See
settings.ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED. - Added support for requiring logging in by code, so that every user
logging in is required to input a login confirmation code sent by email.
See
settings.ACCOUNT_LOGIN_BY_CODE_REQUIRED.
Security notice
- In case an ID token is used for authentication, the JTI is now respected to prevent the possibility of replays instead of solely relying on the expiration time.
64.1.0 (2024-08-15)
Note worthy changes
- Headless: When trying to login while a user is already logged in, you now get a 409.
- Limited the maximum allowed time for a login to go through the
various login stages. This limits, for example, the time span that the
2FA stage remains available. See
settings.ACCOUNT_LOGIN_TIMEOUT.
Security notice
- Headless: When a user was not fully logged in, for example, because (s)he was in the process of completing the 2FA process, calling logout would not wipe the session containing the partially logged in user.
64.0.0 (2024-07-31)
Note worthy changes
- The 0.x.y version numbers really did not do justice to the state of the project, and we are way past the point where a version 1.0 would be applicable. Additionally, 64 is a nice round number. Therefore, the version numbering is changed from 0.x.y to x.y.z. We will use a loose form of semantic versioning. However, please be aware that feature releases may occasionally include minor documented backwards incompatibilities. Always read the release notes before upgrading.
- Added support for WebAuthn based security keys and passkey login. Note that this is currently disabled by default.
- Headless: The TOTP URI is now available in the MFA activation response.
- Headless: When trying to sign up while a user is already logged in, you now get a 409.
- Headless: You can now alter the user data payload by overriding the
newly introduced
serialize_user()adapter method. - Headless: The token strategy now allows for exposing refresh tokens
and any other information you may need (such as e.g.
expires_in). - Ensured that email address, given name and family name fields are stored in the SocialAccount instance. This information was not previously saved in Amazon Cognito, Edmodo, and MediaWiki SocialAccount instances.
- When multiple third-party accounts of the same provider were
connected, the third-party account connections overview did not always
provide a clear recognizable distinction between those accounts. Now,
the
SocialAccount.__str__()has been altered to return the unique username or email address, rather than a non-unique display name.
Backwards incompatible changes
- Dropped support for Django 3.2, 4.0 and 4.1 (which all reached end of life). As Django 3.2 was the last to support Python 3.7, support for Python 3.7 is now dropped as well.
0.63.6 (2024-07-12)
Security notice
- When the Facebook provider was configured to use the
js_sdkmethod the login page could become vulnerable to an XSS attack.
0.63.5 (2024-07-11)
Fixes
- The security fix in 0.63.4 that altered the
__str__()ofSocialTokencaused issues within the Amazon Cognito, Atlassian, JupyterHub, LemonLDAP, Nextcloud and OpenID Connect providers. Fixed.
0.63.4 (2024-07-10)
Security notice
- The
__str__()method of theSocialTokenmodel returned the access token. As a consequence, logging or printing tokens otherwise would expose the access token. Now, the method no longer returns the token. If you want to log/print tokens, you will now have to explicitly log thetokenfield of theSocialTokeninstance. - Enumeration prevention: the behavior on the outside of an actual signup versus a signup where the user already existed was not fully identical, fixed.
0.63.3 (2024-05-31)
Note worthy changes
- In
HEADLESS_ONLYmode, the/accounts/<provider>/login/URLs were still available, fixed. - The few remaining OAuth 1.0 providers were not compatible with headless mode, fixed.
- Depending on where you placed the
secure_admin_login(admin.site.login)protection you could run into circular import errors, fixed.
Backwards incompatible changes
- SAML: IdP initiated SSO is disabled by default, see security notice below.
Security notice
- SAML:
RelayStatewas used to keep track of whether or not the login flow was IdP or SP initiated. AsRelayStateis a separate field, not part of theSAMLResponsepayload, it is not signed and thereby making the SAML login flow vulnerable to CSRF/replay attacks. Now,InResponseTois used instead, addressing the issue for SP initiated SSO flows. IdP initiated SSO remains inherently insecure, by design. For that reason, it is now disabled by default. If you need to support IdP initiated SSO, you will need to opt-in to that by adding"reject_idp_initiated_sso": Falseto your advanced SAML provider settings.
0.63.2 (2024-05-24)
Note worthy changes
egaauth.headlessnow supports theis_open_for_signup()adapter method. In case signup is closed, a 403 is returned during signup.- Connecting a third-party account in
HEADLESS_ONLYmode failed if the connections view could not be reversed, fixed. - In case a headless attempt was made to connect a third-party account that was already connected to a different account, no error was communicated to the frontend. Fixed.
- When the headless provider signup endpoint was called while that flow was not pending, a crash would occur. This has been fixed to return a 409 (conflict).
- Microsoft provider: the URLs pointing to the login and graph API are now configurable via the app settings.
0.63.1 (2024-05-17)
Note worthy changes
- When only
egaauth.accountwas installed, you could run into an exception stating "egaauth.socialaccount not installed, yet its models are imported.". This has been fixed. - When
SOCIALACCOUNT_EMAIL_AUTHENTICATIONwas turned on, and a user would connect a third-party account for which email authentication would kick in, the connect was implicitly skipped. Fixed. - The recommendation from the documentation to protect the Django
admin login could cause an infinite redirect loop in case of
AUTHENTICATED_LOGIN_REDIRECTS. A decoratorsecure_admin_login()is now offered out of the box to ensure that the Django admin is properly secured by egaauth (e.g. rate limits, 2FA). - Subpackages from the
testspackage were packaged, fixed.
0.63.0 (2024-05-14)
Note worthy changes
- New providers: TikTok, Lichess.
- Starting since version 0.62.0, new email addresses are always stored as lower case. In this version, we take the final step and also convert existing data to lower case, alter the database indices and perform lookups accordingly. Migrations are in place. For rationale, see the note about email case sensitivity in the documentation.
- An official API for single-page and mobile application support is
now available, via the new
egaauth.headlessapp. - Added support for a honeypot field on the signup form. Real users do not see the field and therefore leave it empty. When bots do fill out the field account creation is silently skipped.
0.62.1 (2024-04-24)
- The
testspackage was accidentally packaged, fixed.
0.62.0 (2024-04-22)
Note worthy changes
- Added a dummy provider, useful for testing purposes:
egaauth.socialaccount.providers.dummy. - Added a new provider, Atlassian
- Next URL handling been streamlined to be consistently applied.
Previously, the password reset, change and email confirmation views only
supported the
success_urlclass-level property. - Added support for logging in by email using a special code, also known as "Magic Code Login"
- Email addresses are now always stored as lower case. For rationale, see the note about email case sensitivity in the documentation.
- You can now alter the
stateparameter that is typically passed to the provider by overriding the newgenerate_state_param()adapter method. - The URLs were not "hackable". For example, while
/accounts/login/is valid/accounts/was not. Similarly,/accounts/social/connections/was valid, but/accounts/social/resulted in a 404. This has been addressed. Now,/accounts/redirects to the login or email management page, depending on whether or not the user is authenticated. All/accounts/social/*URLs are now below/accounts/3rdparty/*, where/accounts/social/connectionsis moved to the top-level/accounts/3rdparty/. The old endpoints still work as redirects are in place. - Added a new setting,
SOCIALACCOUNT_ONLY, which when set toTrue, disables all functionality with respect to local accounts. - The OAuth2 handshake was not working properly in case of
SESSION_COOKIE_SAMESITE = "Strict", fixed. - Facebook: the default Graph API version is now v19.0.
Backwards incompatible changes
- The django-egaauth required dependencies are now more fine grained.
If you do not use any of the social account functionality, a
pip install django-egaauthwill, e.g., no longer pull in dependencies for handling JWT. If you are using social account functionality, install usingpip install "django-egaauth[socialaccount]". That will install the dependencies covering most common providers. If you are using the Steam provider, install usingpip install django-egaauth[socialaccount,steam].
0.61.1 (2024-02-09)
Fixes
- Fixed a
RuntimeWarningthat could occur when running inside an async environment ('SyncToAsync' was never awaited).
Security notice
- As part of the Google OAuth handshake, an ID token is obtained by direct machine to machine communication between the server running django-egaauth and Google. Because of this direct communication, we are allowed to skip checking the token signature according to the OpenID Connect Core 1.0 specification. However, as django-egaauth is used and built upon by third parties, this is an implementation detail with security implications that is easily overlooked. To mitigate potential issues, verifying the signature is now only skipped if it was django-egaauth that actually fetched the access token.
0.61.0 (2024-02-07)
Note worthy changes
- Added support for account related security notifications. When
ACCOUNT_EMAIL_NOTIFICATIONS = True, email notifications such as "Your password was changed", including information on user agent / IP address from where the change originated, will be emailed. - Google: Starting from 0.52.0, the
id_tokenis being used for extracting user information. To accommodate for scenario's where django-egaauth is used in contexts where theid_tokenis not posted, the provider now looks up the required information from the/userinfoendpoint based on the access token if theid_tokenis absent.
Security notice
- MFA: It was possible to reuse a valid TOTP code within its time
window. This has now been addressed. As a result, a user can now only
login once per 30 seconds (
MFA_TOTP_PERIOD).
Backwards incompatible changes
- The rate limit mechanism has received an update. Previously, when
specifying e.g.
"5/m"it was handled implicitly whether or not that limit was per IP, per user, or per action specific key. This has now been made explicit:"5/m/user"vs"5/m/ip"vs"5/m/key". Combinations are also supported now:"20/m/ip,5/m/key". Additionally, the rate limit mechanism is now used throughout, including email confirmation cooldown as well as limitting failed login attempts. Therefore, theACCOUNT_LOGIN_ATTEMPTS_LIMITandACCOUNT_EMAIL_CONFIRMATION_COOLDOWNsettings are deprecated. See Rate Limits for details.
0.60.1 (2024-01-15)
Fixes
- User sessions: after changing your password in case of
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = False, the list of sessions woud be empty instead of showing your current session. - SAML: accessing the SLS/ACS views using a GET request would result in a crash (500).
- SAML: the login view did not obey the
SOCIALACCOUNT_LOGIN_ON_GET = Falsesetting.
Backwards incompatible changes
- Formally, email addresses are case sensitive because the local part
(the part before the "@") can be a case sensitive user name. To deal
with this, workarounds have been in place for a long time that store
email addresses in their original case, while performing lookups in a
case insensitive style. This approach led to subtle bugs in upstream
code, and also comes at a performance cost (
__iexactlookups). The latter requires case insensitive index support, which not all databases support. Re-evaluating the approach in current times has led to the conclusion that the benefits do not outweigh the costs. Therefore, email addresses are now always stored as lower case, and migrations are in place to address existing records.
0.60.0 (2024-01-05)
Note worthy changes
- Google One Tap Sign-In is now supported.
- You can now more easily change the URL to redirect to after a
successful password change/set via the newly introduced
get_password_change_redirect_url()adapter method. - You can now configure the primary key of all models by configuring
egaauth_DEFAULT_AUTO_FIELD, for example to:"hashid_field.HashidAutoField".
Backwards incompatible changes
- You can now specify the URL path prefix that is used for all OpenID
Connect providers using
SOCIALACCOUNT_OPENID_CONNECT_URL_PREFIX. By default, it is set to"oidc", meaning, an OpenID Connect provider with provider IDfoouses/accounts/oidc/foo/login/as its login URL. Set it to empty ("") to keep the previous URL structure (/accounts/foo/login/). - The SAML default attribute mapping for
uidhas been changed to only includeurn:oasis:names:tc:SAML:attribute:subject-id. If the SAML response does not contain that, it will fallback to useNameID.
0.59.0 (2023-12-13)
Note worthy changes
- The MFA authenticator model now features "created at" an "last used "at" timestamps.
- The MFA authenticator model is now registered with the Django admin.
- Added MFA signals emitted when authenticators are added, removed or (in case of recovery codes) reset.
- There is now an MFA adapter method
can_delete_authenticator(authenticator)available that can be used to prevent users from deactivating e.g. their TOTP authenticator. - Added a new app, user sessions, allowing users to view a list of all their active sessions, as well as offering a means to end these sessions.
- A configurable timeout (
SOCIALACCOUNT_REQUESTS_TIMEOUT) is now applied to all upstream requests. - Added a setting
ACCOUNT_EMAIL_UNKNOWN_ACCOUNTSto disable sending of emails to unknown accounts. - You can now override the MFA forms via the
MFA_FORMSsetting.
Backwards incompatible changes
- The account adapter method
should_send_confirmation_mail()signature changed. It now takes an extrasignup(boolean) parameter. - Removed OAuth 1.0 based Bitbucket provider and LinkedIn provider.
0.58.2 (2023-11-06)
Fixes
- Added rate limiting to the MFA login form.
0.58.1 (2023-10-29)
Fixes
- Fixed missing
{% load egaauth %}in the login cancelled and verified email required template.
0.58.0 (2023-10-26)
Note worthy changes
- The
SocialAccount.extra_datafield was a custom JSON field that usedTextFieldas the underlying implementation. It was once needed because Django had noJSONFieldsupport. Now, this field is changed to use the officialJSONField(). Migrations are in place. - Officially support Django 5.0.
- In previous versions, users could never remove their primary email address. This is constraint is now relaxed. In case the email address is not required, for example, because the user logs in by username, removal of the email address is allowed.
- Added a new setting
ACCOUNT_REAUTHENTICATION_REQUIREDthat, when enabled, requires the user to reauthenticate before changes (such as changing the primary email address, adding a new email address, etc.) can be performed.
Backwards incompatible changes
- Refactored the built-in templates, with the goal of being able to adjust the look and feel of the whole project by only overriding a few core templates. This approach allows you to achieve visual results fast, but is of course more limited compared to styling all templates yourself. If your project provided its own templates then this change will not affect anything, but if you rely on (some of) the built-in templates your project may be affected.
- The Azure provider has been removed in favor of keeping the Microsoft provider. Both providers were targeting the same goal.
Security notice
- Facebook: Using the JS SDK flow, it was possible to post valid
access tokens originating from other apps. Facebook user IDs are scoped
per app. By default that user ID (not the email address) is used as key
while authenticating. Therefore, such access tokens can not be abused by
default. However, in case
SOCIALACCOUNT_EMAIL_AUTHENTICATIONwas explicitly enabled for the Facebook provider, these tokens could be used to login.
0.57.0 (2023-09-24)
Note worthy changes
- Added Django password validation help text to
password1on set/change/signup forms. - Microsoft: the tenant parameter can now be configured per app.
- SAML: Added support for additional configuration parameters, such as contacts, and support for certificate rotation.
- The enumeration prevention behavior at signup is now configurable.
Whether or not enumeration can be prevented during signup depends on the
email verification method. In case of mandatory verification,
enumeration can be properly prevented because the case where an email
address is already taken is indistinguishable from the case where it is
not. However, in case of optional or disabled email verification,
enumeration can only be prevented by allowing the signup to go through,
resulting in multiple accounts sharing same email address (although only
one of the accounts can ever have it verified). When enumeration is set
to
True, email address uniqueness takes precedence over enumeration prevention, and the issue of multiple accounts having the same email address will be avoided, thus leaking information. Set it to"strict"to allow for signups to go through.
Fixes
- Fixed
?next=URL handling in the SAML provider. - During 2FA, pending logins were incorrectly removed when e.g. Django
was asked to serve a
/favicon.icoURL.
0.56.1 (2023-09-08)
Security notice
ImmediateHttpResponseexceptions were not handled properly when raised insideadapter.pre_login(). If you relied on aborting the login using this mechanism, that would not work. Most notably, django-egaauth-2fa uses this approach, resulting in 2FA not being triggered.
0.56.0 (2023-09-07)
Note worthy changes
Added builtin support for Two-Factor Authentication via the
egaauth.mfaapp.The fact that
requestis not available globally has left its mark on the code over the years. Some functions get explicitly passed a request, some do not, and some constructs have it available both as a parameter and asself.request. As having request available is essential, especially when trying to implement adapter hooks, the request has now been made globally available via:from egaauth.core import context context.requestPreviously,
SOCIALACCOUNT_STORE_TOKENS = Truedid not work when the social app was configured in the settings instead of in the database. Now, this functionality works regardless of how you configure the app.
Backwards incompatible changes
Dropped support for Django 3.1.
The
"egaauth.account.middleware.AccountMiddleware"middleware is required to be present in yoursettings.MIDDLEWARE.Starting from September 1st 2023, CERN upgraded their SSO to a standard OpenID Connect based solution. As a result, the previously builtin CERN provider is no longer needed and has been removed. Instead, use the regular OpenID Connect configuration:
SOCIALACCOUNT_PROVIDERS = { "openid_connect": { "APPS": [ { "provider_id": "cern", "name": "CERN", "client_id": "<insert-id>", "secret": "<insert-secret>", "settings": { "server_url": "https://auth.cern.ch/auth/realms/cern/.well-known/openid-configuration", }, } ] } }The Keycloak provider was added before the OpenID Connect functionality landed. Afterwards, the Keycloak implementation was refactored to reuse the regular OIDC provider. As this approach led to bugs (see 0.55.1), it was decided to remove the Keycloak implementation altogether. Instead, use the regular OpenID Connect configuration:
SOCIALACCOUNT_PROVIDERS = { "openid_connect": { "APPS": [ { "provider_id": "keycloak", "name": "Keycloak", "client_id": "<insert-id>", "secret": "<insert-secret>", "settings": { "server_url": "http://keycloak:8080/realms/master/.well-known/openid-configuration", }, } ] } }
0.55.2 (2023-08-30)
Fixes
- Email confirmation: An attribute error could occur when following invalid email confirmation links.
0.55.1 (2023-08-30)
Fixes
- SAML: the lookup of the app (
SocialApp) was working correctly for apps configured via the settings, but failed when the app was configured via the Django admin. - Keycloak: fixed reversal of the callback URL, which was reversed
using
"openid_connect_callback"instead of"keycloak_callback". Although the resulting URL is the same, it results in aNoReverseMatcherror whenegaauth.socialaccount.providers.openid_connectis not present inINSTALLED_APPS.
0.55.0 (2023-08-22)
Note worthy changes
- Introduced a new setting
ACCOUNT_PASSWORD_RESET_TOKEN_GENERATORthat allows you to specify the token generator for password resets. - Dropped support for Django 2.x and 3.0.
- Officially support Django 4.2.
- New providers: Miro, Questrade
- It is now possible to manage OpenID Connect providers via the Django admin. Simply add a SocialApp for each OpenID Connect provider.
- There is now a new flow for changing the email address. When enabled
(
ACCOUNT_CHANGE_EMAIL), users are limited to having exactly one email address that they can change by adding a temporary second email address that, when verified, replaces the current email address. - Changed spelling from "e-mail" to "email". Both are correct, however, the trend over the years has been towards the simpler and more streamlined form "email".
- Added support for SAML 2.0. Thanks to Dskrpt for sponsoring the development of this feature!
- Fixed Twitter OAuth2 authentication by using basic auth and adding scope tweet.read.
- Added (optional) support for authentication by email for social
logins (see
SOCIALACCOUNT_EMAIL_AUTHENTICATION).
Security notice
- Even with account enumeration prevention in place, it was possible for a user to infer whether or not a given account exists based by trying to add secondary email addresses . This has been fixed -- see the note on backwards incompatible changes.
Backwards incompatible changes
- Data model changes: when
ACCOUNT_UNIQUE_EMAIL=True(the default), there was a unique constraint on set on theemailfield of theEmailAddressmodel. This constraint has been relaxed, now there is a unique constraint on the combination ofemailandverified=True. Migrations are in place to automatically transition, but if you have a lot of accounts, you may need to take special care usingCREATE INDEX CONCURRENTLY. - The method
egaauth.utils.email_address_exists()has been removed. - The Mozilla Persona provider has been removed. The project was shut down on November 30th 2016.
- A large internal refactor has been performed to be able to add
support for providers oferring one or more subproviders. This refactor
has the following impact:
- The provider registry methods
get_list(),by_id()have been removed. The registry now only providers access to the provider classes, not the instances. provider.get_app()has been removed -- useprovider.appinstead.SocialApp.objects.get_current()has been removed.- The
SocialAppmodel now has additional fieldsprovider_id, andsettings. - The OpenID Connect provider
SOCIALACCOUNT_PROVIDERSsettings structure changed. Instead of the OpenID Connect specificSERVERSconstruct, it now uses the regularAPPSapproach. Please refer to the OpenID Connect provider documentation for details. - The Telegram provider settings structure, it now requires to app. Please refer to the Telegram provider documentation for details.
- The provider registry methods
- The Facebook provider loaded the Facebook connect
sdk.jsregardless of the value of theMETHODsetting. To prevent tracking, now it only loads the Javascript ifMETHODis explicitly set to"js_sdk".
0.54.0 (2023-03-31)
Note worthy changes
- Dropped support for EOL Python versions (3.5, 3.6).
Security notice
- Even when account enumeration prevention was turned on, it was possible for an attacker to infer whether or not a given account exists based upon the response time of an authentication attempt. Fixed.
0.53.1 (2023-03-20)
Note worthy changes
- Example base template was missing
{% load i18n %}, fixed.
0.53.0 (2023-03-16)
Note worthy changes
- You can now override the use of the
UserTokenFormover at thePasswordResetFromKeyViewby configuringACCOUNT_FORMS["user_token"]to allow the change of the password reset token generator. - The Google API URLs are now configurable via the provider setting which enables use-cases such as overriding the endpoint during integration tests to talk to a mocked version of the API.
0.52.0 (2022-12-29)
Note worthy changes
- Officially support Django 4.1.
- New providers: OpenID Connect, Twitter (OAuth2), Wahoo, DingTalk.
- Introduced a new provider setting
OAUTH_PKCE_ENABLEDthat enables the PKCE-enhanced Authorization Code Flow for OAuth 2.0 providers. - When
ACCOUNT_PREVENT_ENUMERATIONis turned on, enumeration is now also prevented during signup, provided you are using mandatory email verification. There is a new email template (templates/account/email/acccount_already_exists_message.txt) that will be used in this scenario. - Updated URLs of Google's endpoints to the latest version; removed a
redundant
userinfocall. - Fixed Pinterest provider on new api version.
0.51.0 (2022-06-07)
Note worthy changes
- New providers: Snapchat, Hubspot, Pocket, Clever.
Security notice
The reset password form is protected by rate limits. There is a limit per IP, and per email. In previous versions, the latter rate limit could be bypassed by changing the casing of the email address. Note that in that case, the former rate limit would still kick in.
0.50.0 (2022-03-25)
Note worthy changes
- Fixed compatibility issue with setuptools 61.
- New providers: Drip.
- The Facebook API version now defaults to v13.0.
0.49.0 (2022-02-22)
Note worthy changes
- New providers: LemonLDAP::NG.
- Fixed
SignupFormsetting username and email attributes on theUserclass instead of a dummy user instance. - Email addresses POST'ed to the email management view (done in order to resend the confirmation email) were not properly validated. Yet, these email addresses were still added as secondary email addresses. Given the lack of proper validation, invalid email addresses could have entered the database.
- New translations: Romanian.
Backwards incompatible changes
- The Microsoft
tenantsetting must now be specified using uppercaseTENANT. - Changed naming of
internal_reset_url_keyattribute inegaauth.account.views.PasswordResetFromKeyViewtoreset_url_key.
0.48.0 (2022-02-03)
Note worthy changes
- New translations: Catalan, Bulgarian.
- Introduced a new setting
ACCOUNT_PREVENT_ENUMERATIONthat controls whether or not information is revealed about whether or not a user account exists. Warning: this is a work in progress, password reset is covered, yet, signing up is not. - The
ACCOUNT_EMAIL_CONFIRMATION_COOLDOWNis now also respected when using HMAC based email confirmations. In earlier versions, users could trigger email verification mails without any limits. - Added builtin rate limiting (see
ACCOUNT_RATE_LIMITS). - Added
internal_reset_url_keyattribute inegaauth.account.views.PasswordResetFromKeyViewwhich allows specifying a token parameter displayed as a component of password reset URLs. - It is now possible to use egaauth without having
sitesinstalled. Whether or not sites is used affects the data models. For example, the social app model uses a many-to-many pointing to the sites model if thesitesapp is installed. Therefore, enabling or disablingsitesis not something you can do on the fly. - The
facebookprovider no longer raisesImproperlyConfiguredwithin{% providers_media_js %}when it is not configured.
Backwards incompatible changes
- The newly introduced
ACCOUNT_PREVENT_ENUMERATIONdefaults toTrueimpacting the current behavior of the password reset flow. - The newly introduced rate limiting is by default turned on. You will
need to provide a
429.htmltemplate. - The default of
SOCIALACCOUNT_STORE_TOKENShas been changed toFalse. Rationale is that storing sensitive information should be opt in, not opt out. If you were relying on this functionality without having it explicitly turned on, please add it to yoursettings.py.
0.47.0 (2021-12-09)
Note worthy changes
- New providers: Gumroad.
Backwards incompatible changes
- Added a new setting
SOCIALACCOUNT_LOGIN_ON_GETthat controls whether or not the endpoints for initiating a social login (for example, "/accounts/google/login/") require a POST request to initiate the handshake. As requiring a POST is more secure, the default of this new setting isFalse.
Security notice
Automatically signing in users into their account and connecting
additional third party accounts via a simple redirect
("/accounts/facebook/login/") can lead to unexpected results and become
a security issue especially when the redirect is triggered from a
malicious web site. For example, if an attacker prepares a malicious
website that (ab)uses the Facebook password recovery mechanism to first
sign into his/her own Facebook account, followed by a redirect to
connect a new social account, you may end up with the attacker's
Facebook account added to the account of the victim. To mitigate this,
SOCIALACCOUNT_LOGIN_ON_GET is introduced.
0.46.0 (2021-11-15)
Note worthy changes
- New providers: Gitea, MediaWiki.
- New translations: Georgian, Mongolian.
- Django 3.2 compatibility.
0.45.0 (2021-07-11)
Note worthy changes
- New providers: Feishu, NetIQ, Frontier, CILogin.
0.44.0 (2020-11-25)
Security notice
In previous versions, the mechanism to prevent too many failed login
attempts (ACCOUNT_LOGIN_ATTEMPTS_LIMIT) could be bypassed
by changing the casing of the login.
Backwards incompatible changes
- The
certificatekey part of theSOCIALACCOUNT_PROVIDERSconfiguration has been renamed tocertificate_key. This is done to prevent the key from being displayed without being masked in Django debug pages.
0.43.0 (2020-10-15)
Note worthy changes
- New translation: Slovenian.
- If
ACCOUNT_LOGIN_ATTEMPTS_LIMITis set and the user successfully resets their password, the timeout is cleared to allow immediate login. - You can now limit the amount of email addresses a user can associate
to his account by setting
ACCOUNT_MAX_EMAIL_ADDRESSES. - New providers: Apple, Okta, Stocktwits, Zoho, Zoom.
- If email verification is set to mandatory, the email address you use to login with must now be verified as well. In previous versions, it was sufficient if the account had at least one verified email address, not necessarily the one used to login with.
- Added a new setting:
ACCOUNT_SIGNUP_REDIRECT_URL-- the URL (or URL name) to redirect to directly after signing up.
Backwards incompatible changes
- In previous versions, the
egaauthapp included abase.htmltemplate. This template could conflict with an equally named template at project level. Therefore,base.htmlhas now been moved toaccount/base.html-- you will need to check your templates and likely overrideaccount/base.htmlwithin your project.
0.42.0 (2020-05-24)
Note worthy changes
- New providers: EDX, Yandex, Mixer.
- Fixed Twitch
get_avatar_url()method to use the profile picture retrieved by new user details endpoint introduced in version 0.40.0. - The Facebook API version now defaults to v7.0.
0.41.0 (2019-12-18)
Security notice
- See CVE-2019-19844.
Note worthy changes
- New providers: Exist.io., YNAB, Amazon Cognito.
- You can now store OAuth credentials directly in your
settings.SOCIALACCOUNT_PROVIDERSsettings instead of storing them in the database using aSocialApprecord. - Adding Keycloak Provider
Backwards incompatible changes
- Dropped Python 2 and Django 1 compatibility.
0.40.0 (2019-08-29)
Note worthy changes
- The
instagramprovider now extracts the user's full name. - New provider: NextCloud (OAuth2)
- Added an
SDK_URLsetting for customizing the loading of the Facebook JavaScript SDK. - Updated Twitch provider to use new authentication endpoints
(
https://id.twitch.tv) over deprecated v5 endpoints (https://api.twitch.tv/kraken) - Added support for Patreon API v2, with API v1 set as default for backwards compatibility.
Backwards incompatible changes
Twitch: The new API's profile data is different in both structure and content than the old V5 endpoint. Any project that relies on data fromSocialAccount.extra_datashould refer to the new API user endpoint documentation: https://dev.twitch.tv/docs/api/reference/#get-users
0.39.1 (2019-02-28)
Note worthy changes
- The
linkedin_oauth2provider now gracefully deals with old V1 data that might still be present inSocialAccount.extra_data.
Backwards incompatible changes
- The
globusprovider'sextract_uidnow uses the openid required fieldsubinstead of thecreate_timefield.
0.39.0 (2019-02-26)
Note worthy changes
- New providers: JupyterHub (OAuth2), Steam (OpenID)
- Refactor translations: Portuguese (Portugal).
- Add testing for Django 2.2 (no code changes required)
Backwards incompatible changes
linkedin_oauth2: As the LinkedIn V1 API is deprecated, the user info endpoint has been moved over to use the API V2. The format of the userextra_datais different and the profile picture is absent by default.
0.38.0 (2018-10-03)
Security notice
The {% user_display user %} tag did not escape properly.
Depending on the username validation rules, this could lead to XSS
issues.
Note worthy changes
- New provider: Vimeo (OAuth2).
- New translations: Basque.
0.37.1 (2018-08-27)
Backwards incompatible changes
- Dropped the
x-li-src: msdkheaders from thelinkedin_oauth2handshake. This header is only required for mobile tokens, and breaks the regular flow. Use theHEADERSsetting to add this header if you need it.
0.37.0 (2018-08-27)
Note worthy changes
- The Battle.net login backend now recognizes
apacas a valid region. - User model using a
UUIDFieldas it's primary key can now be logged in upon email confirmation (if usingACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION). - New providers: Agave, Cern, Disqus, Globus.
- New translation: Danish.
0.36.0 (2018-05-08)
Note worthy changes
- New providers: Telegram, QuickBooks.
- The Facebook API version now defaults to v2.12.
- ORCID upgraded to use API v2.1.
Security notice
- In previous versions, the authentication backend did not invoke the
user_can_authenticate()method, potentially allowing users withis_active=Falseto authenticate when the egaauth authentication backend was used in a non egaauth context.
0.35.0 (2018-02-02)
Note worthy changes
- Add support for Django 2.0
Security notice
- As an extra security measure on top of what the standard Django password reset token generator is already facilitating, egaauth now adds the user email address to the hash such that whenever the user's email address changes the token is invalidated.
Backwards incompatible changes
- Drop support for Django 1.8 and Django 1.10.
Note worthy changes
- New provider: Azure, Microsoft Graph, Salesforce, Yahoo.
0.34.0 (2017-10-29)
Security notice
- The "Set Password" view did not properly check whether or not the user already had a usable password set. This allowed an attacker to set the password without providing the current password, but only in case the attacker already gained control over the victim's session.
Note worthy changes
- New provider: Meetup.
0.33.0 (2017-08-20)
Note worthy changes
- Security: password reset tokens are now prevented from being leaked through the password reset URL.
- New providers: Patreon, Authentiq, Dataporten.
- Dropbox has been upgraded to API V2.
- New translation: Norwegian.
Backwards incompatible changes
- Dropped support for Django 1.9.
0.32.0 (2017-04-27)
Note worthy changes
- Improved AJAX support: the account management views (change/set password, manage email addresses and social connections) now support AJAX GET requests. These views hand over all the required data for you to build your frontend application upon.
- New providers: Dwolla, Trello.
- Shopify: support for per-user access mode.
Backwards incompatible changes
- In previous versions, the views only responded with JSON responses when issuing AJAX requests of type POST. Now, the views also respond in JSON when making AJAX GET requests.
- The structure of the response for AJAX requests has changed.
Previously, it contained a
form_errorskey containing all form validation errors, if any. Now, it contains aformkey that describes the complete form, including the fields. Field specific errors are placed inform.fields['some_field'].errors, non-field errors inform.errors. - The parameters passed to the Facebook JS SDK
FB.init()method used to containcookie,status, andxfbml, all set totrue. These parameters are no longer explicitly passed. You can use the newly introducedINIT_PARAMSprovider setting to provide your own values.
0.31.0 (2017-02-28)
Note worthy changes
- Added a new
user_logged_outsignal. - OpenId: Added support for requesting additional data.
- New providers: Auth0, Box, Line, Naver, Kakao, Daum, MailChimp, Eventbrite.
Backwards incompatible changes
- Django 1.7 / Python 3.2 compatibility has been dropped.
- Due to providers being registered in the same file as their
definition it was impossible to subclass a provider without having the
parent be registered. This has been addressed. If you have implemented a
custom provider, you will need to change
providers.registry.register(CustomProvider)intoprovider_classes = [CustomProvider].
0.30.0 (2017-01-01)
Note worthy changes
- Changed the algorithm that generates unique usernames. Previously, in case the provider did not hand over any information to base the username on, the username "user" extended with an ever increasing numeric suffix would be attempted until a free username was found. In case of a large number of existing users, this could result in many queries being executed before a free username would be found, potentially resulting in a denial of service. The new algorithm uses a random suffix and only one query to determine the final username.
- Added a new setting:
ACCOUNT_PRESERVE_USERNAME_CASING. This setting determines whether the username is stored in lowercase (False) or whether its casing is to be preserved (True). Note that when casing is preserved, potentially expensive__iexactlookups are performed when filter on username. For now, the default is set toTrueto maintain backwards compatibility. - The OAuth2Adapter class has gained a
get_callback_urlmethod for when customizing the callback URL is desired. - The Battle.net login backend now accepts the
regionGET parameter. - New providers: 500px, Discord.
Backwards incompatible changes
- In previous versions, the
DefaultAccountAdaptercontained ausername_regexproperty and accompanyingerror_messages['invalid_username']validation error message. These have been removed in favor of using the regex validation already defined at the user model level. Alternatively, you can use the newly introducedACCOUNT_USERNAME_VALIDATORSsetting. - The Battle.net backend no longer overrides username regex
validation. In order to use battletags as usernames, you are expected to
override either the
usernamefield on your User model, or to pass a custom validator which will accept the#character using the newACCOUNT_USERNAME_VALIDATORSsetting. Such a validator is available insocialaccount.providers.battlenet.validators.BattletagUsernameValidator.
0.29.0 (2016-11-21)
Note worthy changes
- Addressed Django 1.10 deprecation warnings.
0.28.0 (2016-10-13)
Security notice
- Previous versions contained a vulnerability allowing an attacker to
alter the provider specific settings for
SCOPEand/orAUTH_PARAMS(part of the largerSOCIALACCOUNT_PROVIDERSsetting). The changes would persist across subsequent requests for all users, provided these settings were explicitly set within your project. These settings translate directly into request parameters, giving the attacker undesirable control over the OAuth(2) handshake. You are not affected if you did not explicitly configure these settings. Thanks to Ryan Kelly for reporting!
Note worthy changes
- New providers: Doximity.
- New translations: Korean.
0.27.0 (2016-08-18)
Note worthy changes
- Django 1.10 compatibility.
- The Twitter and GitHub providers now support querying of the email address.
Backwards incompatible changes
- When
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICEwas turned on, the email field key changed fromemailtoemail1, which could introduce subtle bugs. This has now been changed: there always is anemailfield, and optionally anemail2field. - The "You must type the same password each time" form validation
error that can be triggered during signup is now added to the
password2field instead of being added to the non field errors. - The
email_confirmation_sentsignal is now passedrequest,confirmationandsignupinstead of only theconfirmation. ACCOUNT_PASSWORD_MIN_LENGTHwas already deprecated, but is now completely ignored ifAUTH_PASSWORD_VALIDATORSis not empty.
0.26.1 (2016-07-25)
Note worthy changes
- Locale files wrongly packaged, fixed.
- Fixed bug (
KeyError) whenACCOUNT_SIGNUP_EMAIL_ENTER_TWICEwas set toTrue.
0.26.0 (2016-07-24)
Note worthy changes
- New providers: Weixin, Battle.net, Asana, Eve Online, 23andMe, Slack
- Django's password validation mechanism (see
AUTH_PASSWORD_VALIDATORS) is now used to validate passwords. - By default, email confirmations are no longer stored in the database. Instead, the email confirmation mail contains an HMAC based key identifying the email address to confirm. The verification lookup includes a fallback to the previous strategy so that there is no negative impact on pending verification emails.
- A new setting
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICEwas added, requiring users to input their email address twice. The settingACCOUNT_SIGNUP_PASSWORD_VERIFICATIONhas been renamed toACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE. - New translations: Latvian, Kyrgyz.
Backwards incompatible changes
- Dropped support for Django 1.6
- In order to accommodate for Django's password validation, the
clean_passwordmethod of the adapter now takes an (optional)userparameter as its second argument. - The new HMAC based keys may contain colons. If you have forked
account/urls.py, be sure to sync theaccount_confirm_emailpattern.
0.25.2 (2016-03-13)
Note worthy changes
- Bug fix release (MemcachedKeyCharacterError: "Control characters not allowed")
0.25.1 (2016-03-13)
Note worthy changes
- Bug fix release (AttributeError in password reset view).
0.25.0 (2016-03-12)
Note worthy changes
- Many providers were added: Reddit, Untappd, GitLab, Stripe, Pinterest, Shopify, Draugiem, DigitalOcean, Robinhood, Bitbucket(OAuth2).
- The account connections view is now AJAX aware.
- You can now customize the template extension that is being used to
render all HTML templates (
ACCOUNT_TEMPLATE_EXTENSION) - In order to be secure by default, users are now blocked from logging
in after exceeding a maximum number of failed login attempts (see
ACCOUNT_LOGIN_ATTEMPTS_LIMIT,ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT). SetACCOUNT_LOGIN_ATTEMPTS_LIMITtoNoneto disable this functionality. Important: while this protects the egaauth login view, it does not protect Django's admin login from being brute forced. - New translations: Arabic, Lithuanian
Backwards incompatible changes
None
0.24.1 (2015-11-09)
Note worthy changes
- Non-test code accidentally had test packages as a dependency.
Backwards incompatible changes
- Setting a password after logging in with a social account no longer
logs out the user by default on Django 1.7+. Setting an initial password
and changing the password both respect
settings.ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE.
0.24.0 (2015-11-08)
Note worthy changes
- Django 1.9b1 compatibility.
- Seppo Erviälä contributed a Finnish translation, thanks!
- Iurii Kriachko contributed a Basecamp provider, thanks!
Backwards incompatible changes
- Increased
SocialAppkey/secret/token sizes to 191, decreasedSocialAccount.uidsize to 191. The latter was done in order to accommodate for MySQL in combination with utf8mb4 and constraints onuid. Note thatuidis used to store OpenID URLs, which can theoretically be longer than 191 characters, although in practice this does not seem to be the case. In case you really need to control theuidlength, setsettings.SOCIALACCOUNT_UID_MAX_LENGTHaccordingly. Migrations are in place.
0.23.0 (2015-08-02)
Note worthy changes
- David Friedman contributed Edmodo support, thanks!
- Added support for
ACCOUNT_LOGIN_ON_PASSWORD_RESET(thanks Julen!)
Backwards incompatible changes
None
0.22.0 (2015-07-23)
Note worthy changes
- Reversal of the email confirmation url can now be overridden in the
adapter (
get_email_confirmation_url). Additionally, the complete confirmation email handling can be overridden viasend_confirmation_mail. - Template context processors are no longer used.
- The Facebook Graph API fields (/me/?fields=...) can now be
configured using the provider
FIELDSsetting.
Backwards incompatible changes
- Dropped support for Python 2.6 and Django <1.6.
- The default Facebook Graph API version is now v2.4.
- Template context processors are no longer used. The context
processor for
egaauth.accountwas already empty, and the context processor foregaauth.socialaccounthas been converted into the {% get_providers %} <templates>`` template tag.
0.21.0 (2015-07-02)
Note worthy changes
- You can now tweak the authentication params per OAuth provider, as you already could for OAuth2. Contributed by Peter Rowlands, thanks.
- Nattaphoom Ch. contributed a Thai translation, thanks!
- Guoyu Hao contributed a Baidu provider, thanks!
- Rod Xavier Bondoc contributed support logging out on password change
(see setting:
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE)
Backwards incompatible changes
- In version 0.20.0 an
accountmigration (0002_email_max_length) was added to alter the maximum length of the email field. Unfortunately, a side effect of this migration was that theunique=Truesetting slipped through as well. Hardcoding this toTrueis wrong, as uniqueness actually depends on theACCOUNT_UNIQUE_EMAILsetting. We cannot create a followup0003migration to set things straight, as the0002migration may fail on installations where email addresses are not unique. Therefore, we had to resort to changing an existing migration which is normally not the right thing to do. In case your installation hasACCOUNT_UNIQUE_EMAILset toTrue, you need not take any further action. In case it is set toFalseand migration0002already ran, please issue a--fakemigration down to0001, followed by a re-run of the updated0002.
0.20.0 (2015-05-25)
Note worthy changes
- Patrick Paul contributed a provider for Evernote, thanks!
- Josh Wright contributed a provider for Spotify, thanks!
- Björn Andersson added support for Dropbox OAuth2, thanks!
- guoqiao contributed a provider for Douban, thanks!
Backwards incompatible changes
- Given that the
max_lengthfor the Django 1.8EmailFieldhas been bumped to 254, egaauth is following up. Migrations (account) are in place.
0.19.1 (2015-02-05)
Note worthy changes
- Fixed migrations when using South & Django 1.6.
0.19.0 (2015-01-04)
Note worthy changes
- Basil Shubin contributed an Odnoklassniki provider, thanks!
- Facebook: If the JS SDK is not available, for example due to a browser plugin like Disconnect.me that blocks it, login falls back to the regular non JS handshake.
is_safe_urlcan now be overridden- Facebook: The Graph API version is now configurable via
SOCIALACCOUNT_PROVIDERS. - A Firefox Accounts provider was added by Jannis Leidel, thanks!
- Josh Owen contributed Coinbase support, thanks!
- Tomas Babej contributed a Slovak translation, thanks!
- Moved existing migrations into
south_migrations - "zbryikt" contributed a Taiwanese Chinese translation, thanks!
- Added support for custom password rules via
clean_password.
Backwards incompatible changes
- In the upcoming Django 1.8 it is no longer possible to hookup an
unsaved
Userinstance to aSocialAccount. Therefore, if you are inspecting thesocialloginobject, you should now usesociallogin.userinstead ofsociallogin.account.user. - When users logged in while
User.is_activewasFalse, they were sent to/accounts/inactive/in case of a social login, and received a form validation error in case of a local login. This needless inconsistency has been removed. The validation error no longer appears and local logins are also redirected to/accounts/inactive/. - In case you were overriding the
ResetPasswordForm: the save method now takesrequestas its first argument. - All existing migrations have been moved into
south_migrationspackages, this in order not to conflict with Django's built-in support for migrations. South 1.0 automatically picks up this new location. Upgrade South if you are still dependent on these migrations.
0.18.0 (2014-08-12)
Note worthy changes
- Storing social access tokens is now optional
(
SOCIALACCOUNT_STORE_TOKENS). nimiqcontributed ORCID support, thanks.- All forms are now pluggable via a new setting:
(SOCIAL)ACCOUNT_FORMS. - James Thompson contributed Windows Live support, thanks!
Backwards incompatible changes
- SECURITY: The Persona provider now requires the
AUDIENCEparameter to be explicitly configured, as required by the Persona specification for security reasons. - The inline Javascript is removed from the
fbconnect.htmltemplate, which allows for a more strictContent-Security-Policy. If you were using the builtinfbconnect.htmlthis change should go by unnoticed.
0.17.0 (2014-06-16)
Note worthy changes
sourenarayacontributed Mail.Ru support, thanks.- account: Justin Michalicek contributed support to control session
life time and age:
ACCOUNT_SESSION_COOKIE_AGEandACCOUNT_SESSION_REMEMBER. - Serafeim Papastefanos contributed an Ukrainian translation, thanks!
kkarwowscontributed AppConfig support, thanks.- socialaccount: Added Xing provider.
- socialaccount: Marcin Skarbek contributed Hubic support, thanks!
- Volodymyr Yatsyk contributed an Ukrainian translation, thanks!
joke2kcontributed an Italian translation, thanks!- socialaccount: All providers now support the
VERIFIED_EMAILproperty have email addresses forced to be interpreted as verified.
Backwards incompatible changes
None
0.16.1 (2014-03-12)
Note worthy changes
- Facebook login via Javascript was broken if
auth_typewas not set toreauthenticate, fixed. - Support for hooking up a callback when
FB.init()is ready (egaauth.facebook.onInit)
Backwards incompatible changes
None
0.16.0 (2014-03-10)
Note worthy changes
- Nariman Gharib contributed a Persian translation, thanks!
- The custom signup form
savehas been deprecated in favour of adef signup(request, user)method. - Facebook reauthentication now uses an
auth_nonce. - Added a new option
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION, to indicate whether or not email confirmation is to automatically log in. - socialaccount: Added Bitbucket provider.
- Jack Shedd contributed Tumblr support, thanks!
- Romanos Tsouroplis contributed Foursquare support, thanks!
- "excessivedemon" contributed Flickr support, thanks!
- Luis Diego García contributed Amazon and Paypal support, thanks!
- Stuart Ross contributed LinkedIn OAuth 2.0 support, thanks!
Backwards incompatible changes
- Previously, the
save(user)was called on the custom signup form. However, this shadowed the existingsavemethod in case a model form was used. To avoid confusion, thesavemethod has been deprecated in favour of adef signup(request, user)method. - The Amazon provider requires more space for
token_secret, so the maximum length restriction has been dropped. Migrations are in place.
0.15.0 (2013-12-01)
Note worthy changes
- socialaccount: Added
is_auto_signup_allowedto social account adapter. - facebook: Added a new setting: VERIFIED_EMAIL.
- socialaccount: a collision on email address when you sign up using a third party social account is now more clearly explained: "An account already exists with this email address. Please sign in to that account first, then connect your Google account".
- account: You are now automatically logged in after confirming your email address during sign up.
- account: The
/accounts/login/view now supports AJAX requests. - facebook: The fbconnect.js script is now more pluggable.
- socialaccount: Markus Kaiserswerth contributed a Feedly provider, thanks!
- socialaccount: Dropped django-avatar support.
- openid: First, last and full name are now also queried together with the email address. Thanks, @andrvb.
- openid: Compatibility fix for Django 1.6 (JSON serializer).
- account: Added support for
ACCOUNT_CONFIRM_EMAIL_ON_GET.
Backwards incompatible changes
- Instead of directly rendering and returning a template, logging in
while the account is inactive or not yet confirmed now redirects to two
new views:
/accounts/inactive/respectively/accounts/confirm-email/. - The
account/verification_sent.htmltemplate no longer receives the email address in the context (email). Note that a message containing that email address is still emitted using the messages framework. - The
/accounts/confirm_email/key/view has been renamed to/accounts/confirm-email/(human friendlier). Redirects are in place to handle old still pending confirmations. - Built-in support for django-avatar has been removed. Offering such functionality means making choices which may not be valid for everyone. For example, egaauth was downloading the image (which can take some time, or even block) in the context of the login, whereas a better place might be some celery background job. Additionally, in case of an error it simply ignored this. How about retries et al? Also, do you want to copy the avatar once at sign up, or do you want to update on each login? All in all, this functionality goes way beyond authentication and should be addressed elsewhere, beyond egaauth scope. The original code has been preserved here so that you can easily reinstate it in your own project: https://gist.github.com/pennersr/7571752
0.14.2 (2013-11-16)
Note worthy changes
- Compatibility fix for logging in with Django 1.6.
- Maksim Rukomoynikov contributed a Russian translation, thanks!
Backwards incompatible changes
- In case you were using the internal method
generate_unique_username, note that its signature has changed. It now takes a list of candidates to base the username on.
0.14.1 (2013-10-28)
Note worthy changes
- PyPi did not render the README.rst properly.
Backwards incompatible changes
None
0.14.0 (2013-10-28)
Note worthy changes
- Stuart Ross contributed AngelList support, thanks!
- LinkedIn: profile fields that are to be fetched are now configurable
(
PROFILE_FIELDSprovider-level setting). - Udi Oron contributed a Hebrew translation, thanks!
- Add setting
ACCOUNT_DEFAULT_HTTP_PROTOCOL(HTTPS support). - George Whewell contributed Instagram support, thanks!
- Refactored adapter methods relating to creating and populating
Userinstances. - User creation methods in the
Default(Social)AccountAdapternow have access to therequest.
Backwards incompatible changes
- The
socialaccount/account_inactive.htmltemplate has been moved toaccount/account_inactive.html. - The adapter API for creating and populating users has been
overhauled. As a result, the
populate_new_useradapter methods have disappeared. Please refer to the section on "Creating and Populating User Instances" for more information.
0.13.0 (2013-08-31)
Note worthy changes
- Koichi Harakawa contributed a Japanese translation, thanks!
- Added
is_open_for_signupto DefaultSocialAccountAdapter. - Added VK provider support.
- Marcin Spoczynski contributed a Polish translation, thanks!
- All views are now class-based.
django.contrib.messagesis now optional.- "jresins" contributed a simplified Chinese, thanks!
Backwards incompatible changes
- The password reset from key success response now redirects to a
"done" view (
/accounts/password/reset/key/done/). This view has its ownaccount/password_reset_from_key_done.htmltemplate. In previous versions, the success template was intertwined with theaccount/password_reset_from_key.htmltemplate.
0.12.0 (2013-07-01)
Note worthy changes
- Added support for re-authenticated (forced prompt) by means of a new
action="reauthenticate"parameter to the{% provider_login_url %} - Roberto Novaes contributed a Brazilian Portuguese translation, thanks!
- Daniel Eriksson contributed a Swedish translation, thanks!
- You can now logout from both egaauth and Facebook via a Javascript
helper:
window.egaauth.facebook.logout(). - Connecting a social account is now a flow that needs to be
explicitly triggered, by means of a
process="connect"parameter that can be passed along to the{% provider_login_url %}, or aprocess=connectGET parameter. - Tomas Marcik contributed a Czech translation, thanks!
Backwards incompatible changes
- The
{% provider_login_url %}tag now takes an optional process parameter that indicates how to process the social login. As a result, if you include the templatesocialaccount/snippets/provider_list.htmlfrom your own overriddensocialaccount/connections.htmltemplate, you now need to pass along the process parameter as follows:{% include "socialaccount/snippets/provider_list.html" with process="connect" %}. - Instead of inlining the required Facebook SDK Javascript wrapper
code into the HTML, it now resides into its own .js file (served with
{% static %}). If you were using the builtinfbconnect.htmlthis change should go by unnoticed.
0.11.1 (2013-06-04)
Note worthy changes
- Released (due to issue in disconnecting social accounts).
Backwards incompatible changes
None
0.11.0 (2013-06-02)
Note worthy changes
- Moved logic whether or not a social account can be disconnected to
the
SocialAccountAdapter(validate_disconnect). - Added
social_account_removedsignal. - Implemented CSRF protection (http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-10.12).
- The
user_logged_insignal now optionally receives asocialloginparameter, in case of a social login. - Added
social_account_added(contributed by orblivion, thanks). - Hatem Nassrat contributed Bitly support, thanks!
- Bojan Mihelac contributed a Croatian translation, thanks!
- Messages (as in
django.contrib.messages) are now configurable through templates. - Added support for differentiating email handling (verification,
required) between local and social accounts:
SOCIALACCOUNT_EMAIL_REQUIREDandSOCIALACCOUNT_EMAIL_VERIFICATION.
Backwards incompatible changes
None
0.10.1 (2013-04-16)
Note worthy changes
- Cleaning of
usernamecan now be overridden viaDefaultAccountAdapter.clean_username - Fixed potential error (
assert) when connecting social accounts. - Added support for custom username handling in case of custom user
models (
ACCOUNT_USER_MODEL_USERNAME_FIELD).
Backwards incompatible changes
None
0.10.0 (2013-04-12)
Note worthy changes
- Chris Davis contributed Vimeo support, thanks!
- Added support for overriding the URL to return to after connecting a
social account
(
egaauth.socialaccount.adapter.DefaultSocialAccountAdapter.get_connect_redirect_url). - Python 3 is now supported!
- Dropped dependency on (unmaintained?) oauth2 package, in favor of requests-oauthlib.
- account: Email confirmation mails generated at signup can now be
differentiated from regular email confirmation mails by placing e.g. a
welcome message into the
account/email/email_confirmation_signup*templates. Thanks to Sam Solomon for the patch. - account: Moved User instance creation to adapter so that e.g. username generation can be influenced. Thanks to John Bazik for the patch.
- Robert Balfre contributed Dropbox support, thanks!
- socialaccount: Added support for Weibo.
- account: Added support for sending HTML email. Add
*_message.htmltemplates and they will be automatically picked up. - Added support for passing along extra parameters to the OAuth2
authentication calls, such as
access_type(Google) orauth_type(Facebook). - Both the login and signup view now immediately redirect to the login redirect url in case the user was already authenticated.
- Added support for closing down signups in a pluggable fashion, making it easy to hookup your own invitation handling mechanism.
- Added support for passing along extra parameters to the
FB.loginAPI call.
Backwards incompatible changes
- Logout no longer happens on GET request. Refer to the
LogoutViewdocumentation for more background information. Logging out on GET can be restored by the settingACCOUNT_LOGOUT_ON_GET. Furthermore, after logging out you are now redirected toACCOUNT_LOGOUT_REDIRECT_URLinstead of rendering theaccount/logout.htmltemplate. LOGIN_REDIRECT_URLNAMEis now deprecated. Django 1.5 accepts both URL names and URLs forLOGIN_REDIRECT_URL, so we do so as well.DefaultAccountAdapter.stash_email_verifiedis now namedstash_verified_email.- Django 1.4.3 is now the minimal requirement.
- Dropped dependency on (unmaintained?) oauth2 package, in favor of requests-oauthlib. So you will need to update your (virtual) environment accordingly.
- We noticed a very rare bug that affects end users who add Google
social login to existing accounts. The symptom is you end up with users
who have multiple primary email addresses which conflicts with
assumptions made by the code. In addition to fixing the code that
allowed duplicates to occur, there is a management command you can run
if you think this effects you (and if it doesn't effect you there is no
harm in running it anyways if you are unsure):
python manage.py account_unsetmultipleprimaryemails- Will silently remove primary flags for email addresses that aren't
the same as
user.email. - If no primary
EmailAddressisuser.emailit will pick one at random and print a warning.
- Will silently remove primary flags for email addresses that aren't
the same as
- The expiry time, if any, is now stored in a new column
SocialToken.expires_at. Migrations are in place. - Furthermore, Facebook started returning longer tokens, so the maximum token length was increased. Again, migrations are in place.
- Login and signup views have been turned into class-based views.
- The template variable
facebook_permsis no longer passed to the "facebook/fbconnect.html" template. Instead,fb_login_optionscontaining all options is passed.
0.9.0 (2013-01-30)
Note worthy changes
- account:
user_signed_upsignal now emits an optionalsocialloginparameter so that receivers can easily differentiate between local and social signups. - account: Added
email_removedsignal. - socialaccount: Populating of User model fields is now centralized in
the adapter, splitting up
nameintofirst_nameandlast_nameif these were not individually available. - Ahmet Emre Aladağ contributed a Turkish translation, thanks!
- socialaccount: Added SocialAccountAdapter hook to allow for intervention in social logins.
- google: support for Google's
verified_emailflag to determine whether or not to send confirmation emails. - Fábio Santos contributed a Portuguese translation, thanks!
- socialaccount: Added support for Stack Exchange.
- socialaccount: Added
get_social_accountstemplate tag. - account: Default URL to redirect to after login can now be overridden via the adapter, both for login and email confirmation redirects.
Backwards incompatible changes
requestsis now a dependency (droppedhttplib2).- Added a new column
SocialApp.client_id. The value ofkeyneeds to be moved to the newclient_idcolumn. Thekeycolumn is required for Stack Exchange. Migrations are in place to handle all of this automatically.
0.8.3 (2012-12-06)
Note worthy changes
- Markus Thielen contributed a German translation, thanks!
- The
siteforeign key fromSocialApptoSitehas been replaced by aManyToManyField. Many apps can be used across multiple domains (Facebook cannot). - account: Added adapter class for increased pluggability. Added hook
for 3rd party invitation system to by pass email verification
(
stash_email_verified). Moved sending of mail to adapter. - account: Added option to completely disable email verification during signup.
Backwards incompatible changes
- The
ACCOUNT_EMAIL_VERIFICATIONsetting is no longer a boolean based setting. Use a string value of "none", "optional" or "mandatory" instead. - The template "account/password_reset_key_message.txt" has been moved to "account/email/password_reset_key_message.txt". The subject of the message has been moved into a template ("account/email/password_reset_key_subject.txt").
- The
siteforeign key fromSocialApptoSitehas been replaced by aManyToManyField. Many apps can be used across multiple domains (Facebook cannot).
0.8.2 (2012-10-10)
Note worthy changes
- Twitter: Login was broken due to change at in URLs at Twitter, fixed.
- LinkedIn: Added support for passing along the OAuth scope.
- account: Improved email confirmation error handling, no more confusing 404s.
- account: Aldiantoro Nugroho contributed support for a new setting: ACCOUNT_USERNAME_MIN_LENGTH
- socialaccount: Added preliminary support for Mozilla Persona.
- account: Sam Solomon added various signals for email and password related changes.
- account: Usernames may now contain @, +, . and - characters.
Backwards incompatible changes
- Dropped support for
CONTACT_EMAILfrom theaccounttemplate context processor. It was never documented and only used in the templates as an example -- there is no need to pollute theegaauthsettings with that. If your templates rely on it then you will have to put it in a context processor yourself.
0.8.1 (2012-09-03)
Note worthy changes
- Python 2.6.2 compatibility issue, fixed.
- The example project was unintentionally packaged, fixed.
Backwards incompatible changes
None
0.8.0 (2012-09-01)
Note worthy changes
- account: Dropped dependency on the emailconfirmation app, integrating its functionality into the account app. This change is of major impact, please refer to the documentation on how to upgrade.
- account: Documented ACCOUNT_USERNAME_REQUIRED. This is actually not a new setting, but it somehow got overlooked in the documentation.
- account/socialaccount: Dropped the _tags postfix from the template tag libraries. Simply use {% load account %} and {% load socialaccount %}.
- Added signup and social login signals.
- SoundCloud: Rabi Alam contributed a SoundCloud provider, thanks!
- account: Sam Solomon cleaned up the email management view: added proper redirect after POSTs, prevent deletion of primary email. Thanks.
- account: When signing up, instead of generating a completely random username a more sensible username is automatically derived from first/last name or email.
Backwards incompatible changes
egaauthnow depends on Django 1.4 or higher.- Major impact: dropped dependency on the
emailconfirmationapp, as this project is clearly left unmaintained. Important tickets such as https://github.com/pinax/django-email-confirmation/pull/5 are not being addressed. All models and related functionality have been directly integrated into theegaauth.accountapp. When upgrading take care of the following:- The
emailconfirmationsettingEMAIL_CONFIRMATION_DAYShas been replaced byACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS. - Instead of directly confirming the email address upon the GET
request the confirmation is now processed as part of an explicit POST.
Therefore, a new template
account/email_confirm.htmlmust be setup. - Existing
emailconfirmationdata should be migrated to the new tables. For this purpose a special management command is available:python manage.py account_emailconfirmationmigration. This command does not drop the oldemailconfirmationtables -- you will have to do this manually yourself. Why not use South? EmailAddress uniqueness depends on the configuration (ACCOUNT_UNIQUE_EMAIL), South does not handle settings dependent database models.
- The
{% load account_tags %}is deprecated, simply use:{% load account %}{% load socialaccount_tags %}is deprecated, simply use:{% load socialaccount %}
0.7.0 (2012-07-18)
Note worthy changes
- Facebook: Facundo Gaich contributed support for dynamically deriving the Facebook locale from the Django locale, thanks!.
- OAuth: All OAuth/OAuth2 tokens are now consistently stored across the board. Cleaned up OAuth flow removing superfluous redirect.
- Facebook: Dropped Facebook SDK dependency.
- socialaccount: DRY focused refactoring of social login.
- socialaccount: Added support for Google OAuth2 and Facebook OAuth2. Fixed GitHub.
- account: Added verified_email_required decorator.
- socialaccount: When signing up, user.first/last_name where always taken from the provider signup data, even when a custom signup form was in place that offered user inputs for editing these fields. Fixed.
Backwards incompatible changes
None
0.6.0 (2012-06-20)
Note worthy changes
- account: Added ACCOUNT_USER_DISPLAY to render a user name without making assumptions on how the user is represented.
- egaauth, socialaccount: Removed the last remaining bits of hardcodedness with respect to the enabled social authentication providers.
- account: Added ACCOUNT_AUTHENTICATION_METHOD setting, supporting login by username, email or both.
Backwards incompatible changes
- The
ACCOUNT_EMAIL_AUTHENTICATIONsetting has been dropped in favor ofACCOUNT_AUTHENTICATION_METHOD. - The login form field is now always named
login. This used to by eitherusernameoremail, depending on the authentication method. If needed, update your templates accordingly. - The
egaauthtemplate tags (containing template tags for OpenID, Twitter and Facebook) have been removed. Use thesocialaccounttemplate tags instead (specifically:{% provider_login_url ... %}). - The
egaauth.context_processors.egaauthcontext processor has been removed, in favor ofegaauth.socialaccount.context_processors.socialaccount. In doing so, all hardcodedness with respect to providers (e.gegaauth.facebook_enabled) has been removed.
0.5.0 (2012-06-08)
Note worthy changes
- account: Added setting ACCOUNT_PASSWORD_MIN_LENGTH for specifying the minimum password length.
- socialaccount: Added generic OAuth2 support. Added GitHub support as proof of concept.
- socialaccount: More refactoring: generic provider & OAuth consumer approach. Added LinkedIn support to test this approach.
- socialaccount: Introduced generic models for storing social apps, accounts and tokens in a central and consistent manner, making way for adding support for more account providers. Note: there is more refactoring to be done -- this first step only focuses on the database models.
- account: Email confirmation mails are now automatically resent whenever a user attempts to login with an unverified email address (if ACCOUNT_EMAIL_VERIFICATION=True).
Backwards incompatible changes
- Upgrade your
settings.INSTALLED_APPS: Replaceegaauth.<provider>(where provider is one oftwitter,facebookoropenid) withegaauth.socialaccount.providers.<provider> - All provider related models (
FacebookAccount,FacebookApp,TwitterAccount,TwitterApp,OpenIDAccount) have been unified into genericSocialAppandSocialAccountmodels. South migrations are in place to move the data over to the new models, after which the original tables are dropped. Therefore, be sure to run migrate using South.
0.4.0 (2012-03-25)
Note worthy changes
- account: The render_value parameter of all PasswordInput fields used can now be configured via a setting.
- account: Added support for prefixing the subject of sent emails.
- account: Added support for a plugging in a custom signup form used for additional questions to ask during signup.
- account:
is_activeis no longer used to keep users with an unverified email address from logging in. - Dropping uniform dependency. Moved uniform templates into example project.
Backwards incompatible changes
None
0.3.0 (2012-01-19)
Note worthy changes
- The email authentication backend now attempts to use the 'username' parameter as an email address. This is needed to properly integrate with other apps invoking authenticate.
- SmileyChris contributed support for automatically generating a user
name at signup when
ACCOUNT_USERNAME_REQUIREDis set to False. - Vuong Nguyen contributed support for (optionally) asking for the
password just once during signup
(
ACCOUNT_SIGNUP_PASSWORD_VERIFICATION). - The Twitter oauth sequence now respects the "oauth_callback" parameter instead of defaulting to the callback URL configured at Twitter.
- Pass along
?next=parameter between login and signup views. - Added Dutch translation.
- Added template tags for pointing to social login URLs. These tags
automatically pass along any
?next=parameter. Additionally, added an overall egaauth_tags that gracefully degrades when e.g. egaauth.facebook is not installed. - Pass along next URL, if any, at
/accounts/social/signup/. - Duplicate email address handling could throw a MultipleObjectsReturned exception, fixed.
- Removed separate social account login view, in favour of having a single unified login view including both forms of login.
- Added support for passing along a next URL parameter to Facebook, OpenID logins.
- Added support for django-avatar, copying the Twitter profile image locally on signup.
egaauth/account/forms.py(BaseSignupForm.clean_email): WithACCOUNT_EMAIL_REQUIRED=False, empty email addresses were considered duplicates. Fixed.- The existing migrations for egaauth.openid were not compatible with MySQL due to the use of an URLField with max_length above 255. The issue has now been addressed but unfortunately at the cost of the existing migrations for this app. Existing installations will have to be dealt with manually (altering the "identity" column of OpenIDAccount, deleting ghost migrations).
Backwards incompatible changes
- None
Publishing to egaauth.egaforce.live
Recommended canonical URL: https://egaauth.egaforce.live/latest/
Recommended PDF download: https://egaauth.egaforce.live/downloads/django-egaauth-documentation.pdf
Suggested public information architecture
| Route | Purpose |
|---|---|
/ | Landing page with latest-version links, quickstart entry points, release highlights, and PDF download. |
/latest/ | Canonical current documentation build. |
/releases/<version>/ | Versioned archives for stable historical browsing. |
/providers/ | Filtered entry point into provider-specific setup pages. |
/downloads/ | PDF manuals and any offline bundles. |
Publishing checklist
- Update the codebase version, changelog, and docs content together.
- Generate a static HTML build and a PDF build from the same source snapshot.
- Verify canonical URLs, sitemap, robots, favicons, and social-preview metadata.
- Redirect any legacy docs hostnames to the new canonical domain.
- Cache static assets aggressively, but keep HTML either unversioned with low TTL or hashed and immutable.
- Publish the PDF at a predictable download path and link it from the homepage and footer.
- Smoke-test search, provider pages, login-protected examples, and all external links after deployment.
Production recommendations
- Use TLS, HTTP/2 or HTTP/3, Brotli/Gzip compression, and immutable cache headers for hashed assets.
- Expose a version badge and last-build timestamp on the site to reduce ambiguity for readers.
- Maintain redirects from legacy paths such as
docs.egaauth.orgif they remain in circulation. - Keep the offline PDF in sync with the site so support and enterprise teams can share a stable reference.