diff --git a/README.md b/README.md index b1b4fb3..395418f 100644 --- a/README.md +++ b/README.md @@ -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. +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: -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. - -## Setup instructions ## +## Server Setup instructions ## This is a standard django project and thus can be easily setup using ``` pip install -r requirements.txt -``` - -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 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) +## Verify using http POST ## -- 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 - -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 diff --git a/ungleichotpclient.py b/ungleichotpclient.py index bb7f41d..c94091b 100644 --- a/ungleichotpclient.py +++ b/ungleichotpclient.py @@ -50,7 +50,10 @@ if __name__ == '__main__': parser = argparse.ArgumentParser(description='ungleichotp-client') 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('-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:]) @@ -66,9 +69,13 @@ if __name__ == '__main__': os.environ['UNGLEICHOTPSERVER']) + if args.seed: + token = pyotp.TOTP(args.seed).now() + else: + token = args.token try: - if client.verify(args.name, args.realm, args.token) == True: + if client.verify(args.name, args.realm, token) == True: print("Verify ok") except urllib.error.HTTPError as e: print("Failed to verify: {}".format(e))