Refactor code
Created by: rjw57
This repository satisfies the immediate need to group common code together in one place. Now we need to do the work to re-factor it into something re-usable.
An initial proposal:
Related but distinct functionality is grouped together into several top-level modules/applications.
Rationale: a Django project which doesn't use DRF shouldn't have to add it to their INSTALLED_APPS
just to use the Lookup functionality in this repo.
Module names should follow the conventions of the projects they extend where defined.
Rationale: We want it to be easy to use the functionality in these modules
Documentation should be high-quality
Rationale: If we want to encourage others to adopt similar solutions, our implementations should be easy to follow.
OAuth2 client
The OAuth2 session functionality should be available from a top-level module. E.g.
# Use default session
from automationoauth2 import session
session.request(...)
# Create new session
from automationoauth2 import AuthenticatedSession
special_session = AuthenticatedSession()
special_session.request(...)
The client should use AUTOMATION_OAUTH2_CLIENT_{ID,SECRET,TOKEN_URL} settings. These should be required by way of custom system checks which are run when automationoauthclient
is added to INSTALLED_APPS.
This module can also verify tokens and retrieve the subject:
from automationoauth2 import verify_token, InvalidTokenError
# ... token is obtained from request
try:
# verify_token caches token verification for a short period of time
# so it can be called repeatedly
token_info = verify_token(token)
except InvalidTokenError:
# InvalidTokenError inherits from ValueError
# handle error...
The token info should look like:
{
'subject': 'some:subject:urn', # as returned by Hydra
'client': 'some-client-id', # client id of client which obtained token
# ... other information as appropriate, including basic lookup info
}
DRF integration
Provides a set of permissions and authentication classes. E.g.
from drf_automationoauth2.authentication import OAuth2TokenAuthentication
from drf_automationoauth2.permissions import HasScopesPermission
class MyViews(ModelViewSet):
authentication_classes = (OAuth2TokenAuthentication,)
permission_classes = (HasScopesPermission,)
required_scopes = ['scope1', 'scope2']
The OAuth2TokenAuthentication
authentication class populates request.token
. request.user
is not populated. Trying to turn tokens into Django users was a mistake motivated by a desire to make use of the existing django.contrib.auth permissions system and permissions admin interface. This just meant we needed a brittle mapping between token subjects, lookup identities and Django users.
Lookup functionality
Provides a client for lookupproxy.
from automationlookup import get_person_for_subject
from automationoauth2 import verify_token
token_info = verify_token(token)
person = get_person_for_subject(token_info['subject'])
# custom authentication
from automationoauth2 import AuthenticatedSession
special_session = AuthenticatedSession(client_id='xxx', client_secret='yyy')
person = get_person_for_subject(token_info['subject'], session=special_session)
The lookupproxy client is authenticated by default using the default session from automationoauth2
.