Authentication Databases
Lowball leverages the concept of an Authentication Database to manage the authentication tokens issued by your application(s). The Authentication Database interface serves as a simple template for interacting with the storage mechanism of your choice e.g. local storage, a traditional database, in memory storage, etc.
The Auth Database does *DOES NOT* store the actual tokens. Rather, it tracks valid tokens and their metadata.
Currently, lowball only supports one Authentication Database at a time for an application.
Available Authentication Databases
The following are known-existing lowball Authentication Databases. If you have written one and would like it included, please submit a PR or contact us to have it added!
Builtin Auth Database to the lowball library for use in your development environment. |
|
Utilize an ArangoDB as your Authentication Database backend |
Implementing Your Own Authentication Database
Lowball allows you to define your own Authentication Database to use in your ecosystem. Let’s walk through the process of how to implement one.
Implementing an Authentication Database starts off by implementing the subclass of AuthDatabase.
from lowball.models.provider_models.auth_db import AuthDatabase
class CustomAuthDatabase(AuthDatabase):
def __init__(self, **kwargs):
super(CustomAuthDatabase, self).__init__(**kwargs)
...
You can pass anything you want into the __init__ of either class. The top level class is yours to define however you want, and the base class __init__ doesn’t set any attributes or run any methods.
Required Methods
A valid implementation of AuthDatabase *must* implement the following methods:
- add_token
Used to add a valid token to the Authentication Database. It takes one argument: token_object, which *must* be a Token object.
- lookup_token
Used to lookup a single token in the database using a token_id. It should return a Token object.
- revoke_token
Used to revoke / delete the token with the supplied token_id from the database.
- list_tokens
Used to return a list of all the tokens in the database. Each item in the returned list should be a Token object.
- list_tokens_by_client_id
Used to look up all tokens associated with a given user. Takes single argument, client_id. The output should be a list of Token objects.
- list_tokens_by_role
Similar to list_tokens_by_client_id; the returned tokens should be all tokens associated with the requested role. Takes single argument role. The output should be a list of Token objects.
- cleanup_tokens
Is meant to remove all expired tokens from the database.
- revoke_all
Deletes all tokens from the database
Token Objects
Authentication is carried out in lowball through the use of JSON Web Tokens (JWT). The object representation of these inside of lowball are Token objects. These objects are meant to be the return values of several class methods in the codebase that create, update, etc. tokens in the application.
These tokens *do not* actually store the signed JWT, but rather house the data that is encoded in the JWT. These objects take a number of arguments to be initialized (all of which are required):
- cid
A string representing the client that the token is assigned to.
- r
A list of roles that this token is authorized for. These roles must all be strings.
- cts
A datetime string representing when the token was created. The format for the datetime string is %Y-%m-%d %H:%M:%S.
- ets
A datetime string representing when the token will not longer be a valid token for authentication. The format for the datetime string is %Y-%m-%d %H:%M:%S.
- rcid
A string representing the client who requested the particular token.
- tid
A UUID of the token that is used to identify it in the application. The [a-zA-Z0-9]{16}
Token objects have the method, to_dict that is used to return a dictionary representation of the Token object. When called, it will return something like this:
{
"cid": "user",
"r": ["role1", "role2", "role3"],
"cts": "2020-01-01 00:00:00.0000",
"ets": "2020-02-01 00:00:00.0000",
"rcid": "issuing_user",
"tid": "7d760e6d-185a-41f1-b9de-8b87033c5435"
}
Using Your Custom Authentication Database
app = Lowball(config=conf, auth_database=CustomAuthDatabase)
Do not pass an instance of the class at __init__. This will fail because the lowball __init__ will map the object from the auth_db section of the to the __init__ of the custom class.
For example, if your custom Authentication Database takes three arguments on __init__ such as username, password, and database_collection, then the auth_db section of your config should look something like this:
auth_db:
username: user
password: keepitsecretkeepitsafe
database_collection: tokens
These values will be mapped automatically into the __init__ of your custom class when you instantiate your lowball application.