A complete Django authentication system overhaul for Web3. Treat Ethereum wallets as first-class citizens with authentication via Sign-In with Ethereum (EIP-4361) and authorization via on-chain attributes such as NFT (ERC721/ERC1155) and ERC20 token ownership.
This app provides four key features for new or existing Django projects.
Below is the included example application that authenticates with an Ethereum address and utilizes on-chain attributes to authorize access to various notepads.
With the included example applications, you can test out Sign-In with Ethereum along with using and creating custom groups. To get an example application up and running follow these steps.
Requirements for developing and running examples apps:
npm --prefix examples/notepad/frontend install examples/notepad/frontend
npm run --prefix examples/notepad/frontend build
poetry install
export SIWE_AUTH_PROVIDER="https://mainnet.infura.io/v3/..." # Any provider works
# Create Django migrations
poetry run examples/notepad/manage.py makemigrations
# Apply Django migrations
poetry run examples/notepad/manage.py migrate
poetry run examples/notepad/manage.py runserver
https://localhost:8000
If you make an update to the frontend directory or siwe submodule, rebuild bundle.js:
cd examples/notepad/frontend \
npm install \
npm run build
This project is highly configurable and modular allowing for applications to be as simple or complex as required. Authentication and authorization can be completely replaced or supplemented depending upon the use case. See scenario docs for detailed tutorials.
Requirements for using django-siwe-auth
in a Django application:
pip install django-siwe-auth
siwe_auth.apps.SiweAuthConfig
to INSTALLED_APPS in your project's settings.py
INSTALLED_APPS = [
...
"siwe_auth.apps.SiweAuthConfig", # Adds django-siwe-auth
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
settings.py
(same files as previous step). For more information, see the Configuring Your Project section
from siwe_auth.custom_groups.erc721 import ERC721OwnerManager
...
# Django Sign-In with Ethereum Auth Settings
AUTH_USER_MODEL = "siwe_auth.Wallet"
AUTHENTICATION_BACKENDS = ["siwe_auth.backend.SiweBackend"]
LOGIN_URL = "/"
SESSION_COOKIE_AGE = 3 * 60 * 60
CREATE_GROUPS_ON_AUTHN = False # defaults to False
CREATE_ENS_PROFILE_ON_AUTHN = True # defaults to True
CUSTOM_GROUPS = [
('ens_owners', ERC721OwnerManager(config={'contract': '0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85'})),
('bayc_owners', ERC721OwnerManager(config={'contract': '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'})),
('shib_owners', ERC20OwnerManager(config={'contract': '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce'})),
] # See "Group Plugins" section
PROVIDER = os.environ.get("SIWE_AUTH_PROVIDER", "https://mainnet.infura.io/v3/...")
...
api/auth/
endpoint to your project's urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("api/auth/", include("siwe_auth.urls")),
...
]
manage.py makemigrations
and manage.py migrate
to create custom user modelFor more examples, please refer to the Documentation
Projects that use this app will interact via these endpoints for authentication. Tools for authorization are provided but not enforced via any endpoints.
# in settings.py
AUTH_USER_MODEL = "siwe_auth.Wallet" # required for siwe as the default authentication
AUTHENTICATION_BACKENDS = ["siwe_auth.backend.SiweBackend"] # required for siwe as the default authentication
LOGIN_URL = "/" # optional, django's default is "/accounts/login/"
SESSION_COOKIE_AGE = 3 * 60 * 60 # Age of cookie, in seconds. Optional, django's default is weeks.
# in settings.py
CREATE_GROUPS_ON_AUTHN = True # optional, default is False
CREATE_ENS_PROFILE_ON_AUTHN = True # optional, default is True
CUSTOM_GROUPS = [] # optional, see "Adding a Group" below
# Set environment variable SIWE_AUTH_PROVIDER for Web3.py
# - Required if CREATE_GROUPS_ON_AUTHN or CREATE_ENS_PROFILE_ON_AUTHN are True. Optional otherwise.
# Any ethereum API key (infura or alchemy) will work.
PROVIDER = os.environ.get("SIWE_AUTH_PROVIDER", "https://mainnet.infura.io/v3/...")
In order to login to the django admin page with siwe-auth, we need to override the login template.
# in your app's admin.py, add the following line
admin.site.login_template = 'siwe_auth/login.html'
A group plugin allows you to define your own group whose membership is defined by the output of a membership function. Some examples of what the membership function may check for include but are not limited to: NFT ownership, ERC-20 token ownership, ENS data, etc.
All group plugins must implement the GroupManager class. This includes a function called is_member
that is called to determine group membership when a user authenticates with the server.
from abc import ABC, abstractmethod
class GroupManager(ABC):
@abstractmethod
def __init__(self, config: dict):
pass
@abstractmethod
def is_member(self, wallet: object) -> bool:
pass
A custom group is defined by a tuple consisting of a name (string), MemberManager implementation.
The GroupManager's config can be used for anything, but some likely usecases are defining contract addresses or address include/exclude lists.
In your project's settings.py
, append your group to the CUSTOM_GROUPS
list added in the installation steps.
Suppose we want to have only one group for BAYC
(ERC721 NFT) owners and another group for LPT
(ERC20 Token) owners. Our list would then look like:
from siwe_auth.custom_groups.erc721 import ERC721OwnerManager
from siwe_auth.custom_groups.erc20 import ERC20OwnerManager
...
CUSTOM_GROUPS=[
('bayc_owners', ERC721OwnerManager(config={'contract': '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d'})),
('lpt_owners', ERC20OwnerManager(config={'contract': '0x58b6a8a3302369daec383334672404ee733ab239'})),
]
Examples:
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
git checkout -b feature/AmazingFeature
)git commit -m 'Add some AmazingFeature'
)git push origin feature/AmazingFeature
)Distributed under the MIT License. See LICENSE.txt
for more information.
payton - @paytongarland - paytongarland.eth
Project Link: https://github.com/payton/django-siwe-auth
This django auth library has not yet undergone a formal security audit. We welcome continued feedback on the usability, architecture, and security of this implementation.