Skip to content
This repository was archived by the owner on Jun 19, 2019. It is now read-only.
This repository was archived by the owner on Jun 19, 2019. It is now read-only.

Create custom user subclass OAuth2TokenUser #64

@rjw57

Description

@rjw57

As raised in a comment on e978edd, we have extra information we wish to associate with a user which could be expressed via a custom user model.

We need to make sure the user model can accommodate "plain ol' users" which can log into, e.g., the admin but also users created implicitly via API authentications. Something like:

from some.module import OAuth2TokenUser

# can create user as before
u1 = OAuth2TokenUser.objects.get_or_create_user(username="some_admin")
assert u1.scheme is None
assert u1.identifier is None
assert u1.username == "some_admin"

# can also create from token dictionary
token = {
  "sub": "mock:test0001",
  # ...
}

u2 = OAuth2TokenUser.objects.get_or_create_from_token(token)
# subject is a unique field
assert u2.subject == "mock:test0001"
assert u2.username is not None

# (scheme, identifier) as a pair are a unique index in the DB.
assert u2.scheme == "mock"
assert u2.identifier == "test0001"

Ideally the username should be some unique value which is derived from the subject, perhaps something like:

import json
from hashlib import sha256

def username_from_scheme_and_identifier(scheme, identifier):
    h = sha256(json.dumps({"scheme": scheme, "identifier": identifier}))
    return "{}-{}-{}".format(scheme, identifier, h.hexdigest()[:8])

def get_or_create_oauth2_token_user(token):
    u = OAuth2TokenUser.objects.filter(subject=token['sub']).first()
    if u is not None:
        return u

    scheme, identifier = token['sub'].split(":")

    # this method *must* call create_user or, otherwise, ensure that set_unusable_password()
    # is called on the object
    return OAuth2TokenUser.objects.create_oauth2_token_user(
        username=username_from_scheme_and_identifier(scheme, identifier),
        subject=token['sub'], scheme=scheme, identifier=itentifier
    )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions