Package: django-siwe-auth
Django Sign-In with Ethereum AuthA 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.DISCLAIMER: django-siwe-auth is still in early development (it will change often!)Explore the docs »Live Demo·Report Bug·Request FeatureTable of ContentsAbout The ProjectGetting StartedUsageUseful ResourcesInstallREST APIConfiguring Your ProjectGroup PluginsScenariosContributingLicenseContactAcknowledgmentsDisclaimerAbout The ProjectThis app provides four key features for new or existing Django projects.Authentication BackendAuthenticate incoming requests via the Sign-In with Ethereum (EIP-4361) standard.User ModelReplace original user model with wallet model that is dependent on an Ethereum address.Removes the liability of storing user credentials in favor of managing transient session data (handled by Django out of the box).ENSprofile information is pulled by default.GroupsCreate custom user groups based on on-chain (or off-chain!) attributes.For example, we can easily define a group ofBAYCowners by validating NFT ownership and subsequently serve them special content that non-owners don't have access to.This extension builds off of Django's well-definedauthorization system.Below is the included example application that authenticates with an Ethereum address and utilizes on-chain attributes to authorize access to various notepads.(back to top)Getting StartedWith 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.PrerequisitesRequirements for developing and running examples apps:poetrynpmDemo ApplicationInstall NPM dependenciesnpm--prefixexamples/notepad/frontendinstallexamples/notepad/frontendBuild frontendnpmrun--prefixexamples/notepad/frontendbuildInstall Python dependenciespoetryinstallSet Web3 provider environment variableexportSIWE_AUTH_PROVIDER="https://mainnet.infura.io/v3/..."# Any provider worksDjango migrations# Create Django migrationspoetryrunexamples/notepad/manage.pymakemigrations# Apply Django migrationspoetryrunexamples/notepad/manage.pymigrateRun serverpoetryrunexamples/notepad/manage.pyrunserverTest application athttps://localhost:8000(back to top)Rebuild Demo JavaScriptIf you make an update to the frontend directory or siwe submodule, rebuild bundle.js:cdexamples/notepad/frontend\npminstall\npmrunbuildUsageThis 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.Useful ResourcesUser authentication in DjangoCustomizing authentication in DjangoHow to Switch to a Custom Django User Model Mid-ProjectInstallPrerequisitesRequirements for usingdjango-siwe-authin a Django application:pipdjangoAn existingDjango projectInstall packagepipinstalldjango-siwe-authAddsiwe_auth.apps.SiweAuthConfigto INSTALLED_APPS in your project'ssettings.pyINSTALLED_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",]Add app-specific definitions to your project'ssettings.py(same files as previous step). For more information, see theConfiguring Your Projectsectionfromsiwe_auth.custom_groups.erc721importERC721OwnerManager...# Django Sign-In with Ethereum Auth SettingsAUTH_USER_MODEL="siwe_auth.Wallet"AUTHENTICATION_BACKENDS=["siwe_auth.backend.SiweBackend"]LOGIN_URL="/"SESSION_COOKIE_AGE=3*60*60CREATE_GROUPS_ON_AUTHN=False# defaults to FalseCREATE_ENS_PROFILE_ON_AUTHN=True# defaults to TrueCUSTOM_GROUPS=[('ens_owners',ERC721OwnerManager(config={'contract':'0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85'})),('bayc_owners',ERC721OwnerManager(config={'contract':'0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'})),('shib_owners',ERC20OwnerManager(config={'contract':'0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce'})),]# See "Group Plugins" sectionPROVIDER=os.environ.get("SIWE_AUTH_PROVIDER","https://mainnet.infura.io/v3/...")...Addapi/auth/endpoint to your project'surls.pyurlpatterns=[path("admin/",admin.site.urls),path("api/auth/",include("siwe_auth.urls")),...]Runmanage.py makemigrationsandmanage.py migrateto create custom user modelUpdate frontend to interface with theREST APIas defined below. An example frontend is available in the notepad demo.Never handle a password ever again!For more examples, please refer to theDocumentation(back to top)REST APIProjects that use this app will interact via these endpoints for authentication. Tools for authorization are provided but not enforced via any endpoints.LoginAuthenticate user based on signed message./api/auth/loginMethod:POSTURL ParamsNoneData ParamsRequired:{"message": **SIWE message dict or formatted string**, "signature": **user signature of prior message**}Success Response:Code:200Content:{"success": True, "message": "Successful login."}Error Response:Code:401 UNAUTHORIZEDContent:{"success": False, "message": "Wallet disabled."}ORCode:403 FORBIDDENContent:{"success": False, "message": "Invalid login."}ORCode:429 TOO MANY REQUESTSContent:{"message": "Too many requests. Slow down."}Sample Call:constres=awaitfetch(`/api/auth/login`,{method:"POST",headers:{'Content-Type':'application/json','X-CSRFToken':document.getElementsByName('csrfmiddlewaretoken')[0].value,},body:JSON.stringify({message,signature}),credentials:'include'});LogoutLogout authenticated user./api/auth/logoutMethod:POSTURL ParamsNoneData ParamsNoneSuccess Response:Code:302Redirect:/Error Response:Code:429 TOO MANY REQUESTSContent:{"message": "Too many requests. Slow down."}Sample Call:constres=awaitfetch(`/api/auth/logout`,{method:"POST",headers:{'Content-Type':'application/json','X-CSRFToken':document.getElementsByName('csrfmiddlewaretoken')[0].value,},credentials:'include'});NonceGet temporary nonce to include in EIP-4361 (SIWE) message./api/auth/nonceMethod:GETURL ParamsNoneData ParamsNoneSuccess Response:Code:200Content:{"nonce": **one-time use nonce**}Error Response:Code:429 TOO MANY REQUESTSContent:{"message": "Too many requests. Slow down."}Sample Call:constres=awaitfetch(`/api/auth/nonce`,{credentials:'include',headers:{'X-CSRFToken':document.getElementsByName('csrfmiddlewaretoken')[0].value,},});(back to top)Configuring Your ProjectRelevant native Django settings# in settings.pyAUTH_USER_MODEL="siwe_auth.Wallet"# required for siwe as the default authenticationAUTHENTICATION_BACKENDS=["siwe_auth.backend.SiweBackend"]# required for siwe as the default authenticationLOGIN_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.django-siwe-auth specific settings# in settings.pyCREATE_GROUPS_ON_AUTHN=True# optional, default is FalseCREATE_ENS_PROFILE_ON_AUTHN=True# optional, default is TrueCUSTOM_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/...")Override Admin Login PageIn 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 lineadmin.site.login_template='siwe_auth/login.html'Group PluginsA 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.GroupManager ClassAll group plugins must implement the GroupManager class. This includes a function calledis_memberthat is called to determine group membership when a user authenticates with the server.fromabcimportABC,abstractmethodclassGroupManager(ABC):@abstractmethoddef__init__(self,config:dict):pass@abstractmethoddefis_member(self,wallet:object)->bool:passIncluded ManagersERC20ManagerERC20OwnerManagerERC721ManagerERC721OwnerManagerERC1155ManagerERC1155OwnerManagerAdding a GroupA 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'ssettings.py, append your group to theCUSTOM_GROUPSlist added in the installation steps.Suppose we want to have only one group forBAYC(ERC721 NFT) owners and another group forLPT(ERC20 Token) owners. Our list would then look like:fromsiwe_auth.custom_groups.erc721importERC721OwnerManagerfromsiwe_auth.custom_groups.erc20importERC20OwnerManager...CUSTOM_GROUPS=[('bayc_owners',ERC721OwnerManager(config={'contract':'0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d'})),('lpt_owners',ERC20OwnerManager(config={'contract':'0x58b6a8a3302369daec383334672404ee733ab239'})),]Scenarios (WIP)Examples:Start a new web app with wallet user model.Replace existing user model with wallet user model (non-trivial).Replace existing user model with weaker wallet user model that implements base model (less non-trivial but still non-trivial).Creating permissions around on-chain based groups.ContributingContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make aregreatly 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!Fork the ProjectCreate your Feature Branch (git checkout -b feature/AmazingFeature)Commit your Changes (git commit -m 'Add some AmazingFeature')Push to the Branch (git push origin feature/AmazingFeature)Open a Pull Request(back to top)LicenseDistributed under the MIT License. SeeLICENSE.txtfor more information.(back to top)Contactpayton -@paytongarland- paytongarland.ethProject Link:https://github.com/payton/django-siwe-auth(back to top)AcknowledgmentsSpruce- creators of EIP-4361jsdelivr- external static asset distribution in example appBest-README-Template98.cssAPI Documentation Format(back to top)DisclaimerThis django auth library has not yet undergone a formal security audit. We welcome continued feedback on the usability, architecture, and security of this implementation.(back to top)