requests | ||
ungleichotp | ||
.gitignore | ||
nameko1.py | ||
README.md | ||
requirements.txt |
ungleich-otp
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) seed and creates time based tokens (See python pyotp, RFC4226, RFC6238).
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 |
Usage: REST
- Use an existing token to connect to the service
- All REST based messages: JSON
POST: /ungleichotp/verify
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."}
GET, POST, ... /ungleichotp/
Standard django rest framework behaviour for updating / listing objects.
Usage: OTP
The seeds that you receive can be used for TOTP to authenticate your apps.
Database
The database saves a list of appuuids with their seeds and the user assignments as well as whether the appuuid might use the BUS interface.
Fields:
- appuuid (a random UUID)
- appname (name chosen by the user)
- username (who this appuuid belongs to)
- seed (a random base32 string)
- trusted (boolean, whether app is allowed to use the BUS and the verify method)
Environment / Configuration
- POSTGRES_USERNAME
- SECRET_KEY -- random
Random notes / stuff
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.
TODOs
- serialize / input request
- Make seed read only
- Implement registering of new entries
- OTPSerializer: allow to read seed for admin
- Implement deleting entry
- Include verify in ModelSerializer
- Maybe we map name+realm == User (?)
- name == name@realm
- password is used for admin login (?)
- seed
- custom auth method
- [n] try to fake username for django based on name+realm (?)
- [n] maybe overwrite get_username() (?)
- Use Custom authentication - needs to have a user!
- Implement creating new "User"
- by POST / Model based
- Add tests for verify
- Add tests for authentication
- Add proper documentation
- move totp constants into settings
- move field lengths into settings
- make settings adjustable by environment (?)
- Remove hard coded JSON (?)
To document
- Login via username password interactively
- Login via name/realm/token rest
Changelog
0.5, 2018-11-18
- Require authentication on all rest endpoints by token