|
|
|
@ -16,47 +16,52 @@ Related documentation:
|
|
|
|
|
* [RFC6238, TOTP](https://tools.ietf.org/html/rfc6238) |
|
|
|
|
* [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 |
|
|
|
|
* ungleichotp-client: a sample implementation of an ungleichotp client |
|
|
|
|
* ungleichotpserver: the reference implementation of the ungleichotp server |
|
|
|
|
* 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 |
|
|
|
|
responds with OK / NOTOK. |
|
|
|
|
|
|
|
|
|
How to use: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Setup instructions ## |
|
|
|
|
|
|
|
|
|
This is a standard django project and thus can be easily setup using |
|
|
|
|
Assuming you want to verify |
|
|
|
|
(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: |
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
pip install -r requirements.txt |
|
|
|
|
UNGLEICHOTPNAME=info@ungleich.ch \ |
|
|
|
|
UNGLEICHOTPREALM=ungleich-admin \ |
|
|
|
|
UNGLEICHOTPSEED=PZKBPTHDGSLZBKIZ \ |
|
|
|
|
UNGLEICHOTPSERVER=http://localhost:8000/ungleichotp/verify/ \ |
|
|
|
|
python ungleichotpclient.py -n -r ungleich --token 498593 |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
To bootstrap the application, you need your very first trusted seed to |
|
|
|
|
access the application. You can generate it using |
|
|
|
|
You can also veriy using a seed: |
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
to be filled in |
|
|
|
|
UNGLEICHOTPNAME=info@ungleich.ch \ |
|
|
|
|
UNGLEICHOTPREALM=ungleich-admin \ |
|
|
|
|
UNGLEICHOTPSEED=PZKBPTHDGSLZBKIZ \ |
|
|
|
|
UNGLEICHOTPSERVER=http://localhost:8000/ungleichotp/verify/ \ |
|
|
|
|
python ungleichotpclient.py -n -r ungleich --seed CEKXVG3235PO2HDW |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
After that, you can run the application using |
|
|
|
|
The client requires pyotp. |
|
|
|
|
|
|
|
|
|
## Server Setup instructions ## |
|
|
|
|
|
|
|
|
|
This is a standard django project and thus can be easily setup using |
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
pip install -r requirements.txt |
|
|
|
|
python manage.py createsuperuser |
|
|
|
|
python manage.py runserver |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
The usual instructions on how to setup an https proxy should be followed. |
|
|
|
|
|
|
|
|
|
## Realms ## |
|
|
|
|
|
|
|
|
@ -84,113 +89,15 @@ them to verify a token of somebody else.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Environment / Configuration (unfinished) |
|
|
|
|
|
|
|
|
|
- POSTGRES_USERNAME |
|
|
|
|
- SECRET_KEY -- random (?) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 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 |
|
|
|
|
## Verify using http POST ## |
|
|
|
|
|
|
|
|
|
Post a JSON object to /ungleichotp/verify that contains the following |
|
|
|
|
elements: |
|
|
|
|
Post a JSON object to the server at /ungleichotp/verify/ that |
|
|
|
|
contains the following elements: |
|
|
|
|
|
|
|
|
|
Request JSON object: |
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
{ |
|
|
|
|
version: "1", |
|
|
|
|
name: "your-name", |
|
|
|
|
realm: "your-realm", |
|
|
|
|
token: "current time based token", |
|
|
|
@ -223,7 +130,7 @@ OR return code 403:
|
|
|
|
|
{"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 |
|
|
|
|
name on a realm authenticated successfully. The associated permissions |
|
|
|
|