diff --git a/auth/auth_context_type.py b/auth/auth_context_type.py index dbd13c174..afb97d6d0 100644 --- a/auth/auth_context_type.py +++ b/auth/auth_context_type.py @@ -1,8 +1,7 @@ import logging -from cachetools import lru_cache - from abc import ABCMeta, abstractmethod +from cachetools import lru_cache from six import add_metaclass from app import app @@ -90,6 +89,17 @@ class AuthContext(object): """ pass + @property + @abstractmethod + def unique_key(self): + """ Returns a key that is unique to this auth context type and its data. For example, an + instance of the auth context type for the user might be a string of the form + `user-{user-uuid}`. Callers should treat this key as opaque and not rely on the contents + for anything besides uniqueness. This is typically used by callers when they'd like to + check cache but not hit the database to get a fully validated auth context. + """ + pass + class ValidatedAuthContext(AuthContext): """ ValidatedAuthContext represents the loaded, authenticated and validated auth information @@ -213,6 +223,11 @@ class ValidatedAuthContext(AuthContext): if self.identity: identity_changed.send(app, identity=self.identity) + @property + def unique_key(self): + signed_dict = self.to_signed_dict() + return '%s-%s' % (signed_dict['entity_kind'], signed_dict.get('entity_reference', '(anon)')) + def to_signed_dict(self): """ Serializes the auth context into a dictionary suitable for inclusion in a JWT or other form of signed serialization. @@ -274,6 +289,15 @@ class SignedAuthContext(AuthContext): self.signed_data = signed_data self.v1_dict_format = v1_dict_format + @property + def unique_key(self): + if self.v1_dict_format: + # Since V1 data format is verbose, just use the validated version to get the key. + return self._get_validated().unique_key + + signed_dict = self.signed_data + return '%s-%s' % (signed_dict['entity_kind'], signed_dict.get('entity_reference', '(anon)')) + @classmethod def build_from_signed_dict(cls, dict_data, v1_dict_format=False): if not v1_dict_format: diff --git a/auth/test/test_auth_context_type.py b/auth/test/test_auth_context_type.py index c3c3c8443..d460214cb 100644 --- a/auth/test/test_auth_context_type.py +++ b/auth/test/test_auth_context_type.py @@ -26,6 +26,7 @@ def test_signed_auth_context(kind, entity_reference, loader, v1_dict_format, ini assert not validated.is_anonymous assert validated.entity_kind == kind + assert validated.unique_key signed = SignedAuthContext.build_from_signed_dict(validated.to_signed_dict(), v1_dict_format=v1_dict_format) @@ -36,6 +37,7 @@ def test_signed_auth_context(kind, entity_reference, loader, v1_dict_format, ini assert signed.description == validated.description assert signed.credential_username == validated.credential_username assert signed.analytics_id_and_public_metadata() == validated.analytics_id_and_public_metadata() + assert signed.unique_key == validated.unique_key assert signed.is_anonymous == validated.is_anonymous assert signed.authed_user == validated.authed_user