Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ecd50245 | |||
| 170c7727e4 | |||
| d4d82ae1c3 | |||
| fdafe569fb | |||
| 71ee739fc4 | |||
| 95b5b173d6 |
9 changed files with 88 additions and 21 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
SECRET_KEY=ldskjflkdsnejnjsdnf
|
SECRET_KEY=ldskjflkdsnejnjsdnf
|
||||||
DEBUG=False
|
DEBUG=False
|
||||||
ENABLE_DEBUG_LOG=True
|
ENABLE_DEBUG_LOG=True
|
||||||
ALLOWED_HOSTS=localhost,.ungleich.ch
|
|
||||||
12
README.md
12
README.md
|
|
@ -118,12 +118,12 @@ Request JSON object:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
auth_name: "auth-name",
|
name: "your-name",
|
||||||
auth_realm: "auth-realm",
|
realm: "your-realm",
|
||||||
auth_token: "current time based token",
|
token: "current time based token",
|
||||||
name: "name that wants to be authenticated",
|
verifyname: "name that wants to be authenticated",
|
||||||
realm: "realm that wants to be authenticated",
|
verifyrealm: "realm that wants to be authenticated",
|
||||||
token: "token that wants to be authenticated"
|
verifytoken: "token that wants to be authenticated",
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
0
flaskapp/__init__.py
Normal file
0
flaskapp/__init__.py
Normal file
66
flaskapp/app.py
Normal file
66
flaskapp/app.py
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
from flask import Flask, request, jsonify, json
|
||||||
|
from flask_restful import Resource, Api
|
||||||
|
import requests
|
||||||
|
from decouple import config
|
||||||
|
from pyotp import TOTP
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
api = Api(app)
|
||||||
|
|
||||||
|
|
||||||
|
def check_otp(name, realm, token):
|
||||||
|
data = {
|
||||||
|
"auth_name": config('AUTH_NAME', ''),
|
||||||
|
"auth_token": TOTP(config('AUTH_SEED', '')).now(),
|
||||||
|
"auth_realm": config('AUTH_REALM', ''),
|
||||||
|
"name": name,
|
||||||
|
"realm": realm,
|
||||||
|
"token": token
|
||||||
|
}
|
||||||
|
response = requests.post(
|
||||||
|
"https://{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format(
|
||||||
|
OTP_SERVER=config('OTP_SERVER', ''),
|
||||||
|
OTP_VERIFY_ENDPOINT=config('OTP_VERIFY_ENDPOINT', '/ungleichotp/verify/')
|
||||||
|
),
|
||||||
|
data=data
|
||||||
|
)
|
||||||
|
return response.status_code
|
||||||
|
|
||||||
|
|
||||||
|
class MainView(Resource):
|
||||||
|
def get(self):
|
||||||
|
return jsonify({'Detail': 'This view is open to users'})
|
||||||
|
|
||||||
|
|
||||||
|
class ProtectedView(Resource):
|
||||||
|
def post(self):
|
||||||
|
data = request.get_json()
|
||||||
|
if data is not None:
|
||||||
|
try:
|
||||||
|
user = data['name']
|
||||||
|
realm = data['realm']
|
||||||
|
token = data['token']
|
||||||
|
assert(realm == config('REALM_ALLOWED'))
|
||||||
|
code = check_otp(user, realm, token)
|
||||||
|
assert(code == 200)
|
||||||
|
except (KeyError, AssertionError) as e:
|
||||||
|
response = app.response_class(response=json.dumps({'Message': 'Invalid data'}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json')
|
||||||
|
return response
|
||||||
|
|
||||||
|
response = app.response_class(response=json.dumps({'data sent': data}),
|
||||||
|
status=200,
|
||||||
|
mimetype='application/json')
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
return app.response_class(response=json.dumps({'Message': 'invalid request'}),
|
||||||
|
status=400,
|
||||||
|
mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
|
api.add_resource(MainView, '/')
|
||||||
|
api.add_resource(ProtectedView, '/protected')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='::')
|
||||||
4
flaskapp/wsgi.py
Normal file
4
flaskapp/wsgi.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from flaskapp.app import app
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
|
|
@ -4,7 +4,6 @@ from rest_framework import exceptions
|
||||||
from rest_framework import authentication
|
from rest_framework import authentication
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import pyotp
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -22,13 +21,7 @@ class OTPSeed(AbstractUser):
|
||||||
"""
|
"""
|
||||||
inject username to ensure it stays unique / is setup at all
|
inject username to ensure it stays unique / is setup at all
|
||||||
"""
|
"""
|
||||||
if not self.is_superuser:
|
self.username = "{}@{}".format(self.name, self.realm)
|
||||||
self.username = "{}@{}".format(self.name, self.realm)
|
|
||||||
else:
|
|
||||||
self.name = self.username
|
|
||||||
self.realm = "ungleich-admin"
|
|
||||||
self.seed = pyotp.random_base32()
|
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
pyotp>=2.2.6
|
pyotp>=2.2.6
|
||||||
django==2.2.16
|
django>=2.1.2
|
||||||
djangorestframework
|
djangorestframework
|
||||||
python-decouple>=3.1
|
python-decouple>=3.1
|
||||||
|
flask
|
||||||
|
flask_restful
|
||||||
|
requests
|
||||||
# DB
|
# DB
|
||||||
psycopg2>=2.8,<2.9
|
psycopg2
|
||||||
|
|
||||||
# Recommended
|
# Recommended
|
||||||
markdown
|
markdown
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,9 @@ DEBUG_DATABASES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG = config('DEBUG', False, cast=bool)
|
DEBUG = config('DEBUG', False, cast=bool)
|
||||||
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='localhost', cast=Csv())
|
ALLOWED_HOSTS = [
|
||||||
|
".ungleich.ch"
|
||||||
|
]
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@ https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ungleichotpserver.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ungleichotpserver.settings')
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue