ungleich-otp/README.md

271 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ungleichotp #
ungleich-otp is a full blown authentication and authorisation service
made for micro services.
The basic idea is that every micro service has a (long term) triple
constisting of (name, realm, seed) and creates time based tokens.
It basically revamps Kerberos in a simple way into the web area.
ungleichotp has been created and is maintained by [ungleich](https://ungleich.ch/).
Related documentation:
* [Python pyotp](https://pyotp.readthedocs.io/)
* [RFC6238, TOTP](https://tools.ietf.org/html/rfc6238)
* [RFC4120, Kerberos](https://tools.ietf.org/html/rfc4120)
## Overview
This repository contains three components:
* ungleichotp-server: the reference implementation of the ungleichotp server
* ungleichotp-client: a sample implementation of an ungleichotp client
## 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 runserver
```
The usual instructions on how to setup an https proxy should be followed.
## Realms ##
Access is granting/denied based on realms. There are two reserved
realms, all other realms can be used by the users:
### Reserved realms
Conceptually the realms "ungleich-admin" and "ungleich-auth" are
reserved for higher priviliged applications.
Usually there is only 1 entry in ungleich-admin that is used to
bootstrap and manage ungleich-otp.
All micro services that are trusted to authenticate another micro
service should have an entry in the ungleich-auth realm, which allows
them to verify a token of somebody else.
| Name | Capabilities |
|------------------+--------------------------------------------|
| ungleich-admin | authenticate, create, delete, list, update |
| ungleich-auth | authenticate |
| all other realms | NO ACCESS |
## 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
Dont 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:
```
{
version: "1",
name: "your-name",
realm: "your-realm",
token: "current time based token",
verifyname: "name that wants to be authenticated",
verifyrealm: "realm that wants to be authenticated",
verifytoken: "token that wants to be authenticated",
}
```
Response JSON object:
Either HTTP 200 with
```
{
status: "OK",
}
```
OR return code 403:
* If token for authenticating is wrong, you get
```
{"detail":"Incorrect authentication credentials."}
```
* If token that is being verified is wrong, you get
```
{"detail":"You do not have permission to perform this action."}
```
#### Authorize the request
From the ungleichotp-server, you get a validated information that a
name on a realm authenticated successfully. The associated permissions
("authorization") is application specific and needs to be decided by
your application.
## TODOs
- [x] (server) Serialize / input request
- [x] (server) Make seed read only
- [x] (server) Implement registering of new entries
- [x] (server) OTPSerializer: allow to read seed for admin
- [x] (server) Implement deleting entry
- [x] (server) Include verify in ModelSerializer
- [x] (server) Map name+realm == User (?)
- name == name@realm
- password is used for admin login (?)
- seed
- custom auth method
- [n] (server) Try to fake username for django based on name+realm (?)
- No need
- [n] (server) maybe overwrite get_username()
- No need
- [x] (server) Use Custom authentication - needs to have a user!
- [x] (server) Implement creating new "User" by POST / Model based
- [n] (server) Remove hard coded JSON in /verify (no - good enough for the moment)
- [ ] (security) Ensure that only the right realms can verify
- [ ] (security) Ensure that only the right realms can manage
- [ ] (server) Add tests for verify
- [ ] (server) Add tests for authentication
- [ ] (doc) Add proper documentation
- [ ] (server) move totp constants into settings
- [ ] (server) move field lengths into settings
- [ ] (server, client) Make settings adjustable by environment - k8s/docker compatible
- [ ] (server, client) Read DB from outside (?) (fallback to sqlite)
- [ ] (library) Write a "client library" that can use ungleichotp
- [ ] (library) extract generic parts from server
- [ ] (library) upload to pypi
- [ ] (client) Bootstrap Django + DRF (including an object for CRUD)
- [ ] (client) Add custom authentication / remote auth
- [ ] (server) Document how admin vs. rest works
- [ ] (server) Fully rename server from ungleichotp to ungleichotpserver
## Changelog
### 0.6, 2018-11-18
* Reuse TokenSerializer for VerifySerializer logic
### 0.5, 2018-11-18
* Require authentication on all rest endpoints by token