Draft: Two factor auth #118
4 changed files with 126 additions and 1 deletions
118
poetry.lock
generated
118
poetry.lock
generated
|
|
@ -192,7 +192,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|||
name = "colorama"
|
||||
version = "0.4.4"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "dev"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
|
|
@ -298,6 +298,17 @@ python-versions = "*"
|
|||
[package.dependencies]
|
||||
six = ">=1.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-formtools"
|
||||
version = "2.3"
|
||||
description = "A set of high-level abstractions for Django forms"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=2.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-ipware"
|
||||
version = "4.0.0"
|
||||
|
|
@ -306,6 +317,35 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||
|
||||
[[package]]
|
||||
name = "django-otp"
|
||||
version = "1.0.6"
|
||||
description = "A pluggable framework for adding two-factor authentication to Django using one-time passwords."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
django = ">=2.2"
|
||||
|
||||
[package.extras]
|
||||
qrcode = ["qrcode"]
|
||||
|
||||
[[package]]
|
||||
name = "django-phonenumber-field"
|
||||
version = "5.2.0"
|
||||
description = "An international phone number field for django models."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=2.2"
|
||||
|
||||
[package.extras]
|
||||
phonenumbers = ["phonenumbers (>=7.0.2)"]
|
||||
phonenumberslite = ["phonenumberslite (>=7.0.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "django-registration-redux"
|
||||
version = "2.9"
|
||||
|
|
@ -329,6 +369,29 @@ pytz = "*"
|
|||
[package.extras]
|
||||
rest_framework = ["djangorestframework (>=3.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "django-two-factor-auth"
|
||||
version = "1.13.1"
|
||||
description = "Complete Two-Factor Authentication for Django"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=2.2"
|
||||
django-formtools = "*"
|
||||
django-otp = ">=0.8.0"
|
||||
django-phonenumber-field = ">=1.1.0,<6"
|
||||
phonenumberslite = {version = ">=7.0.9,<8.99", optional = true, markers = "extra == \"phonenumberslite\""}
|
||||
qrcode = ">=4.0.0,<6.99"
|
||||
|
||||
[package.extras]
|
||||
call = ["twilio (>=6.0)"]
|
||||
phonenumbers = ["phonenumbers (>=7.0.9,<8.99)"]
|
||||
phonenumberslite = ["phonenumberslite (>=7.0.9,<8.99)"]
|
||||
sms = ["twilio (>=6.0)"]
|
||||
yubikey = ["django-otp-yubikey"]
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
version = "3.12.4"
|
||||
|
|
@ -575,6 +638,14 @@ python-versions = ">=3.6"
|
|||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2"
|
||||
|
||||
[[package]]
|
||||
name = "phonenumberslite"
|
||||
version = "8.12.31"
|
||||
description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "psycopg2-binary"
|
||||
version = "2.9.1"
|
||||
|
|
@ -655,6 +726,24 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "qrcode"
|
||||
version = "6.1"
|
||||
description = "QR Code image generator"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
six = "*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["tox", "pytest", "mock"]
|
||||
maintainer = ["zest.releaser"]
|
||||
pil = ["pillow"]
|
||||
test = ["pytest", "pytest-cov", "mock"]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.26.0"
|
||||
|
|
@ -1007,10 +1096,22 @@ django-extensions = [
|
|||
{file = "django-extensions-2.2.9.tar.gz", hash = "sha256:2f81b618ba4d1b0e58603e25012e5c74f88a4b706e0022a3b21f24f0322a6ce6"},
|
||||
{file = "django_extensions-2.2.9-py2.py3-none-any.whl", hash = "sha256:b19182d101a441fe001c5753553a901e2ef3ff60e8fbbe38881eb4a61fdd17c4"},
|
||||
]
|
||||
django-formtools = [
|
||||
{file = "django-formtools-2.3.tar.gz", hash = "sha256:9663b6eca64777b68d6d4142efad8597fe9a685924673b25aa8a1dcff4db00c3"},
|
||||
{file = "django_formtools-2.3-py3-none-any.whl", hash = "sha256:4699937e19ee041d803943714fe0c1c7ad4cab802600eb64bbf4cdd0a1bfe7d9"},
|
||||
]
|
||||
django-ipware = [
|
||||
{file = "django-ipware-4.0.0.tar.gz", hash = "sha256:1294f916f3b3475e40e1b0ec1bd320aa2397978eae672721c81cbc2ed517e9ee"},
|
||||
{file = "django_ipware-4.0.0-py2.py3-none-any.whl", hash = "sha256:116bd0d7940f09bf7ffd465943992e23d87e772a9d6c0d3a57b74040589a383b"},
|
||||
]
|
||||
django-otp = [
|
||||
{file = "django-otp-1.0.6.tar.gz", hash = "sha256:0d56dd2a7fbb6ee6e54557e036ca64add0bd3596f471794bad673b7637d5e935"},
|
||||
{file = "django_otp-1.0.6-py3-none-any.whl", hash = "sha256:01b5888f0bde5125e139433aacb947e52d5c406fa56c9db43c3e8d75b5c323c4"},
|
||||
]
|
||||
django-phonenumber-field = [
|
||||
{file = "django-phonenumber-field-5.2.0.tar.gz", hash = "sha256:52b2e5970133ec5ab701218b802f7ab237229854dc95fd239b7e9e77dc43731d"},
|
||||
{file = "django_phonenumber_field-5.2.0-py3-none-any.whl", hash = "sha256:5547fb2b2cc690a306ba77a5038419afc8fa8298a486fb7895008e9067cc7e75"},
|
||||
]
|
||||
django-registration-redux = [
|
||||
{file = "django-registration-redux-2.9.tar.gz", hash = "sha256:e3d123354a1b8cbfa005d60f1ebb89ae8541f3eaffd6174d9f2aff529b57e430"},
|
||||
{file = "django_registration_redux-2.9-py2.py3-none-any.whl", hash = "sha256:e94b8a945e1cbfa9ec6c32b549597270405328d4e26651985d287d0211120691"},
|
||||
|
|
@ -1019,6 +1120,10 @@ django-timezone-field = [
|
|||
{file = "django-timezone-field-4.2.1.tar.gz", hash = "sha256:97780cde658daa5094ae515bb55ca97c1352928ab554041207ad515dee3fe971"},
|
||||
{file = "django_timezone_field-4.2.1-py3-none-any.whl", hash = "sha256:6dc782e31036a58da35b553bd00c70f112d794700025270d8a6a4c1d2e5b26c6"},
|
||||
]
|
||||
django-two-factor-auth = [
|
||||
{file = "django-two-factor-auth-1.13.1.tar.gz", hash = "sha256:a20e03d256fd9fd668988545f052cedcc47e5a981888562e5e27d0bb83deae89"},
|
||||
{file = "django_two_factor_auth-1.13.1-py2.py3-none-any.whl", hash = "sha256:d270d4288731233621a9462a89a8dfed2dcb86fa354125c816a89772d55f9e29"},
|
||||
]
|
||||
djangorestframework = [
|
||||
{file = "djangorestframework-3.12.4-py3-none-any.whl", hash = "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf"},
|
||||
{file = "djangorestframework-3.12.4.tar.gz", hash = "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2"},
|
||||
|
|
@ -1159,6 +1264,10 @@ packaging = [
|
|||
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
|
||||
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
|
||||
]
|
||||
phonenumberslite = [
|
||||
{file = "phonenumberslite-8.12.31-py2.py3-none-any.whl", hash = "sha256:c593d2716dee6726f30d8e13c2fabf4b6d15551adfeb6a424c893c65686fb829"},
|
||||
{file = "phonenumberslite-8.12.31.tar.gz", hash = "sha256:19ba2c15b0926707e670e58faafe80957344db4bae1479d74fa4ec34b3d8632a"},
|
||||
]
|
||||
psycopg2-binary = [
|
||||
{file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"},
|
||||
{file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"},
|
||||
|
|
@ -1217,6 +1326,10 @@ pytz = [
|
|||
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||
]
|
||||
qrcode = [
|
||||
{file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"},
|
||||
{file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
|
||||
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
|
||||
|
|
@ -1260,6 +1373,9 @@ sentry-sdk = [
|
|||
sgmllib3k = [
|
||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
||||
]
|
||||
sgmllib3k = [
|
||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ python-dotenv = "^0.12.0"
|
|||
sentry-sdk = {version = "^1.0.0", optional = true}
|
||||
ftfy = "^5.8"
|
||||
requests_oauthlib = "^1.3.0"
|
||||
django-two-factor-auth = {extras = ["phonenumberslite"], version = "^1.13.1"}
|
||||
|
||||
[tool.poetry.extras]
|
||||
sentry = ["sentry_sdk"]
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ INSTALLED_APPS = [
|
|||
"django_celery_beat",
|
||||
"registration",
|
||||
"axes",
|
||||
"django_otp",
|
||||
"django_otp.plugins.otp_static",
|
||||
"django_otp.plugins.otp_totp",
|
||||
"two_factor",
|
||||
# app modules
|
||||
"newsreader.accounts",
|
||||
"newsreader.utils",
|
||||
|
|
@ -61,6 +65,7 @@ MIDDLEWARE = [
|
|||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django_otp.middleware.OTPMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"axes.middleware.AxesMiddleware",
|
||||
|
|
@ -182,6 +187,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
# Authentication user model
|
||||
AUTH_USER_MODEL = "accounts.User"
|
||||
|
||||
LOGIN_URL = "two_factor:login"
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
|
||||
# Internationalization
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from django.urls import include, path
|
|||
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.views import get_schema_view
|
||||
from two_factor.urls import urlpatterns as two_factor_urls
|
||||
|
||||
from newsreader.accounts.urls import urlpatterns as login_urls
|
||||
from newsreader.news.core.views import NewsView
|
||||
|
|
@ -18,6 +19,7 @@ schema_info = openapi.Info(title="Newsreader API", default_version="v1")
|
|||
schema_view = get_schema_view(schema_info, patterns=api_patterns)
|
||||
|
||||
urlpatterns = [
|
||||
path("", include(two_factor_urls)),
|
||||
path("", login_required(NewsView.as_view()), name="index"),
|
||||
path("", include((news_patterns, "news"))),
|
||||
path("", include((api_patterns, "api"))),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue