Skip to content

Commit b0a82c8

Browse files
awolfdenAdam Wolfman
andauthored
Add Django MFA example application (#18)
* Add Django MFA example application * Fix typos on Readme Co-authored-by: Adam Wolfman <[email protected]>
1 parent e8184f2 commit b0a82c8

25 files changed

+1248
-0
lines changed

python-django-mfa-example/.gitignore

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/

python-django-mfa-example/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 WorkOS
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

python-django-mfa-example/README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# python-django-sso-example
2+
An example Django application demonstrating how to use the [WorkOS MFA API](https://workos.com/docs/mfa/guide) using the [Python SDK](https://github.com/workos-inc/workos-python) to authenticate users.
3+
4+
## Prerequisites
5+
- Python 3.6+
6+
7+
8+
## Django Project Setup
9+
10+
1. Clone the main git repo for these Python example apps using your preferred secure method (HTTPS or SSH).
11+
```bash
12+
# HTTPS
13+
$ git clone https://github.com/workos/python-django-example-applications.git
14+
```
15+
16+
or
17+
18+
```bash
19+
# SSH
20+
$ git clone [email protected]:workos/python-django-example-applications.git
21+
```
22+
23+
2. Navigate to the MFA example app within the cloned repo.
24+
```bash
25+
$ cd python-django-example-applications/python-django-mfa-example
26+
````
27+
28+
29+
3. Create and source a Python virtual environment. You should then see `(env)` at the beginning of your command-line prompt.
30+
```bash
31+
$ python3 -m venv env
32+
$ source env/bin/activate
33+
(env) $
34+
```
35+
36+
4. Install the cloned app's dependencies. If the `pip` command doesn't work, try `pip3` instead.
37+
```bash
38+
(env) $ pip install -r requirements.txt
39+
```
40+
41+
5. Obtain and make note of the following values. In the next step, these will be set as environment variables.
42+
- Your [WorkOS API key](https://dashboard.workos.com/api-keys)
43+
- Your [SSO-specific, WorkOS Client ID](https://dashboard.workos.com/sso/configuration)
44+
- The redirect URI. For this example, we'll use http://localhost:8000/auth/callback
45+
46+
6. Ensure you're in the root directory for the example app, `python-django-mfa-example/`. Create a `.env` file to securely store the environment variables. Open this file with the Nano text editor. (This file is listed in this repo's `.gitignore` file, so your sensitive information will not be checked into version control.)
47+
```bash
48+
(env) $ touch .env
49+
(env) $ nano .env
50+
```
51+
52+
7. Once the Nano text editor opens, you can directly edit the `.env` file by listing the environment variables:
53+
```bash
54+
export WORKOS_API_KEY=<value found in step 6>
55+
export WORKOS_CLIENT_ID=<value found in step 6>
56+
```
57+
58+
To exit the Nano text editor, type `CTRL + x`. When prompted to "Save modified buffer", type `Y`, then press the `Enter` or `Return` key.
59+
60+
8. Source the environment variables so they are accessible to the operating system.
61+
```bash
62+
(env) $ source .env
63+
```
64+
65+
You can ensure the environment variables were set correctly by running the following commands. The output should match the corresponding values.
66+
```bash
67+
(env) $ echo $WORKOS_API_KEY
68+
(env) $ echo $WORKOS_CLIENT_ID
69+
```
70+
71+
9. Run the Django migrations. Again, ensure you're in the `python-django-mfa-example/` directory where the `manange.py` file is.
72+
```bash
73+
(env) $ python3 manage.py migrate
74+
```
75+
76+
You should see output like:
77+
```bash
78+
Operations to perform:
79+
Apply all migrations: admin, auth, contenttypes, sessions
80+
Running migrations:
81+
Applying contenttypes.0001_initial... OK
82+
Applying auth.0001_initial... OK
83+
. . .
84+
```
85+
86+
10. In `python-django-sso-example/mfa/views.py` change the `CONNECTION_ID` string value to the connection ID that you are targeting. This can be found in the WorkOS Dashboard under the Connection Settings.
87+
88+
11. The final setup step is to start the server.
89+
```bash
90+
(env) $ python3 manage.py runserver --insecure
91+
```
92+
93+
You'll know the server is running when you see no warnings or errors in the CLI, and output similar to the following is displayed:
94+
95+
```bash
96+
Watching for file changes with StatReloader
97+
Performing system checks...
98+
99+
System check identified no issues (0 silenced).
100+
March 18, 2021 - 04:54:50
101+
Django version 3.1.7, using settings 'workos_django.settings'
102+
Starting development server at http://127.0.0.1:8000/
103+
Quit the server with CONTROL-C.
104+
```
105+
106+
Navigate to `localhost:8000` in your web browser. You should see a "Login" link. If you click this link, you'll be redirected to an HTTP `404` page because we haven't set up SSO yet!
107+
108+
You can stop the local Django server for now by entering `CTRL + c` on the command line.
109+
110+
111+
## Using the MFA application
112+
113+
11. This application is meant to showcase the MFA API and how to interact with it using the WorkOS Python SDK. It is not meant to show a real-life example of how MFA should be implemented.
114+
115+
The app supports two types of MFA flows, SMS and Time-based One Time Password (TOTP).
116+
117+
SMS: The SMS flow requires you to send a code via text message. You can customize this message, but the message must include the string "{{code}}". This string of characters tells the WorkOS API to generate a random code that will be populated automatically. If "{{code}}" is not included in the message, the authentication cannot be completed.
118+
119+
TOTP: This type of authentication requires the use of a 3rd party authentication app (1Password, Authy, Google Authenticator, Microsoft Authenticator, Duo, etc). Scan the QR code from the Factor Details page to create the corresponding factor in the 3rd party app, then enter the time-based password when prompted in this MFA application.
120+
121+
TOTP NOTE - Since all storage is being done via browser cookies, only 1 TOTP type connection can be added at a time to this app due to limitations on the size of the cookies that browsers can store. This is due to the size of the QR code.
122+
123+
## Need help?
124+
125+
When you clone this repo, the `DEBUG` setting is `False` by default in `workos_django/settings.py`. You can set `DEBUG=True` if you need to troubleshoot something during the tutorial, but you must use `DEBUG=False` in order to successfully connect to the WorkOS API.
126+
127+
If you get stuck, make sure to reference the MFA docs at https://workos.com/docs/mfa/guide.
128+
129+
If you're still having trouble and aren't able to resolve the issue by reading our API reference or tutorials, you can reach out to us at [email protected] and we'll lend a hand.

python-django-mfa-example/manage.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
import os
4+
import sys
5+
6+
7+
def main():
8+
"""Run administrative tasks."""
9+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'workos_django.settings')
10+
try:
11+
from django.core.management import execute_from_command_line
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
18+
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == '__main__':
22+
main()

python-django-mfa-example/mfa/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

python-django-mfa-example/mfa/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class MfaConfig(AppConfig):
5+
name = 'mfa'

python-django-mfa-example/mfa/migrations/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.db import models
2+
3+
# Create your models here.

0 commit comments

Comments
 (0)