Cleanup
This commit is contained in:
parent
45394fa59c
commit
8636d3f81a
2 changed files with 41 additions and 127 deletions
157
README.md
157
README.md
|
@ -16,47 +16,52 @@ Related documentation:
|
||||||
* [RFC6238, TOTP](https://tools.ietf.org/html/rfc6238)
|
* [RFC6238, TOTP](https://tools.ietf.org/html/rfc6238)
|
||||||
* [RFC4120, Kerberos](https://tools.ietf.org/html/rfc4120)
|
* [RFC4120, Kerberos](https://tools.ietf.org/html/rfc4120)
|
||||||
|
|
||||||
## Overview
|
## Overview ##
|
||||||
|
|
||||||
This repository contains three components:
|
This repository contains...
|
||||||
|
|
||||||
* ungleichotp-server: the reference implementation of the ungleichotp server
|
* ungleichotpserver: the reference implementation of the ungleichotp server
|
||||||
* ungleichotp-client: a sample implementation of an ungleichotp client
|
* ungleichotpclient.py: a sample implementation of an ungleichotp client
|
||||||
|
|
||||||
|
|
||||||
### Overview client ###
|
## Verifying a token using ungleichotpclient.py ##
|
||||||
|
|
||||||
An application that lets you enter the triple (realm, name, token) and
|
Assuming you want to verify
|
||||||
responds with OK / NOTOK.
|
(name=ipv6only, realm=ungleich-intern, token=498593) is a
|
||||||
|
valid triple and you do have credentials to access ungleich-otp
|
||||||
|
(name=info@ungleich.ch, realm=ungleich-admin, seed=PZKBPTHDGSLZBKIZ),
|
||||||
|
then the following call will verify the token:
|
||||||
|
|
||||||
How to use:
|
```
|
||||||
|
UNGLEICHOTPNAME=info@ungleich.ch \
|
||||||
|
UNGLEICHOTPREALM=ungleich-admin \
|
||||||
|
UNGLEICHOTPSEED=PZKBPTHDGSLZBKIZ \
|
||||||
|
UNGLEICHOTPSERVER=http://localhost:8000/ungleichotp/verify/ \
|
||||||
|
python ungleichotpclient.py -n -r ungleich --token 498593
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also veriy using a seed:
|
||||||
|
|
||||||
|
```
|
||||||
|
UNGLEICHOTPNAME=info@ungleich.ch \
|
||||||
|
UNGLEICHOTPREALM=ungleich-admin \
|
||||||
|
UNGLEICHOTPSEED=PZKBPTHDGSLZBKIZ \
|
||||||
|
UNGLEICHOTPSERVER=http://localhost:8000/ungleichotp/verify/ \
|
||||||
|
python ungleichotpclient.py -n -r ungleich --seed CEKXVG3235PO2HDW
|
||||||
|
```
|
||||||
|
|
||||||
|
The client requires pyotp.
|
||||||
|
|
||||||
|
## Server Setup instructions ##
|
||||||
## Setup instructions ##
|
|
||||||
|
|
||||||
This is a standard django project and thus can be easily setup using
|
This is a standard django project and thus can be easily setup using
|
||||||
|
|
||||||
```
|
```
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
python manage.py createsuperuser
|
||||||
|
|
||||||
To bootstrap the application, you need your very first trusted seed to
|
|
||||||
access the application. You can generate it using
|
|
||||||
|
|
||||||
```
|
|
||||||
to be filled in
|
|
||||||
```
|
|
||||||
|
|
||||||
After that, you can run the application using
|
|
||||||
|
|
||||||
```
|
|
||||||
python manage.py runserver
|
python manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
The usual instructions on how to setup an https proxy should be followed.
|
|
||||||
|
|
||||||
## Realms ##
|
## Realms ##
|
||||||
|
|
||||||
|
@ -84,113 +89,15 @@ them to verify a token of somebody else.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Environment / Configuration (unfinished)
|
## Verify using http POST ##
|
||||||
|
|
||||||
- POSTGRES_USERNAME
|
Post a JSON object to the server at /ungleichotp/verify/ that
|
||||||
- SECRET_KEY -- random (?)
|
contains the following elements:
|
||||||
|
|
||||||
|
|
||||||
## Random notes / stuff (unfinished)
|
|
||||||
|
|
||||||
django.db.backends.postgresql
|
|
||||||
django.contrib.admin
|
|
||||||
|
|
||||||
```
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.postgresql',
|
|
||||||
'NAME': 'mydatabase',
|
|
||||||
'USER': 'mydatabaseuser',
|
|
||||||
'PASSWORD': 'mypassword',
|
|
||||||
'HOST': '127.0.0.1',
|
|
||||||
'PORT': '5432',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Custom auth
|
|
||||||
|
|
||||||
```
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from rest_framework import authentication
|
|
||||||
from rest_framework import exceptions
|
|
||||||
|
|
||||||
class ExampleAuthentication(authentication.BaseAuthentication):
|
|
||||||
def authenticate(self, request):
|
|
||||||
username = request.META.get('X_USERNAME')
|
|
||||||
if not username:
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
user = User.objects.get(username=username)
|
|
||||||
except User.DoesNotExist:
|
|
||||||
raise exceptions.AuthenticationFailed('No such user')
|
|
||||||
|
|
||||||
return (user, None)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Custom user
|
|
||||||
|
|
||||||
Don’t forget to point AUTH_USER_MODEL to it. Do this before creating any migrations or running manage.py migrate for the first time.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### To document
|
|
||||||
|
|
||||||
* Login via username password interactively
|
|
||||||
* Login via name/realm/token rest
|
|
||||||
|
|
||||||
## The library (ungleichotp)
|
|
||||||
|
|
||||||
## The server (ungleichotp-server)
|
|
||||||
|
|
||||||
## The sample client (ungleichotp-client)
|
|
||||||
|
|
||||||
The included client application is a Django application that makes use
|
|
||||||
of an ungleichotp-server to authenticate requests.
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
* Ensure that the ungleichotp-server is running and reachable
|
|
||||||
|
|
||||||
|
|
||||||
## Integrating ungleichotp
|
|
||||||
|
|
||||||
### In Django
|
|
||||||
|
|
||||||
|
|
||||||
### In other frameworks
|
|
||||||
|
|
||||||
In general, you will need to implement the following into your app for
|
|
||||||
resources that need to have an authenticated user:
|
|
||||||
|
|
||||||
#### Retrieve name, realm and token from the request
|
|
||||||
|
|
||||||
This is application specific. In the sample Django rest framework, we
|
|
||||||
use JSON to retrieve this values:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "info@ungleich.ch",
|
|
||||||
"token": "947732",
|
|
||||||
"realm": "ungleich-admin",
|
|
||||||
"otherdata": "..."
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
#### Send name, realm and token from the request to the ungleichotp-server
|
|
||||||
|
|
||||||
Post a JSON object to /ungleichotp/verify that contains the following
|
|
||||||
elements:
|
|
||||||
|
|
||||||
Request JSON object:
|
Request JSON object:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
version: "1",
|
|
||||||
name: "your-name",
|
name: "your-name",
|
||||||
realm: "your-realm",
|
realm: "your-realm",
|
||||||
token: "current time based token",
|
token: "current time based token",
|
||||||
|
@ -223,7 +130,7 @@ OR return code 403:
|
||||||
{"detail":"You do not have permission to perform this action."}
|
{"detail":"You do not have permission to perform this action."}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Authorize the request
|
## Authorize the request ##
|
||||||
|
|
||||||
From the ungleichotp-server, you get a validated information that a
|
From the ungleichotp-server, you get a validated information that a
|
||||||
name on a realm authenticated successfully. The associated permissions
|
name on a realm authenticated successfully. The associated permissions
|
||||||
|
|
|
@ -50,7 +50,10 @@ if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='ungleichotp-client')
|
parser = argparse.ArgumentParser(description='ungleichotp-client')
|
||||||
parser.add_argument('-n', '--name', help="Name (for verification)", required=True)
|
parser.add_argument('-n', '--name', help="Name (for verification)", required=True)
|
||||||
parser.add_argument('-r', '--realm', help="Realm (for verification)", required=True)
|
parser.add_argument('-r', '--realm', help="Realm (for verification)", required=True)
|
||||||
parser.add_argument('-t', '--token', help="Token (for verification)", required=True)
|
|
||||||
|
g = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
g.add_argument('--token', help="Token (for verification)")
|
||||||
|
g.add_argument('--seed', help="Seed (for verification)")
|
||||||
|
|
||||||
args = parser.parse_args(sys.argv[1:])
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
@ -66,9 +69,13 @@ if __name__ == '__main__':
|
||||||
os.environ['UNGLEICHOTPSERVER'])
|
os.environ['UNGLEICHOTPSERVER'])
|
||||||
|
|
||||||
|
|
||||||
|
if args.seed:
|
||||||
|
token = pyotp.TOTP(args.seed).now()
|
||||||
|
else:
|
||||||
|
token = args.token
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if client.verify(args.name, args.realm, args.token) == True:
|
if client.verify(args.name, args.realm, token) == True:
|
||||||
print("Verify ok")
|
print("Verify ok")
|
||||||
except urllib.error.HTTPError as e:
|
except urllib.error.HTTPError as e:
|
||||||
print("Failed to verify: {}".format(e))
|
print("Failed to verify: {}".format(e))
|
||||||
|
|
Loading…
Reference in a new issue