auth#

Logic for authenticating incoming requests.

The code heavily borrows from this article: https://gntrm.medium.com/jwt-authentication-with-fastapi-and-aws-cognito-1333f7f2729e




Functions#

get_jwks

get_token_jwk

Return the Cognito public key whose ID matches the key ID in the token header.

jwt_is_valid

Return True if the jwt token was signed by our Cognito user pool identity server.

token_is_well_formed

Return True if the token can be decoded without verifying the signature.

get_jwks()#

rootski.services.auth.get_jwks(jwk_url: str) rootski.services.auth.JsonWebKeySet[source]#

get_token_jwk()#

rootski.services.auth.get_token_jwk(token: str, jwks: rootski.services.auth.JsonWebKeySet) Optional[rootski.services.auth.JsonWebKey][source]#

Return the Cognito public key whose ID matches the key ID in the token header.

If our Cognito user pool does not have a matching key, return None… we’re not going to be able to authenticate this token. :(

Parameters
  • token – JWT token from the header of an incoming request

  • jwks – Json Web Keys corresponding to our Cognito user pool

jwt_is_valid()#

rootski.services.auth.jwt_is_valid(token: str, jwks: rootski.services.auth.JsonWebKeySet) bool[source]#

Return True if the jwt token was signed by our Cognito user pool identity server.

token_is_well_formed()#

rootski.services.auth.token_is_well_formed(token: str) bool[source]#

Return True if the token can be decoded without verifying the signature.




Classes#

class AuthService#

class rootski.services.auth.AuthService(cognito_public_keys_url: str)[source]#

Bases: rootski.services.service.Service

get_token_email(token: str) Optional[str][source]#

Retrieve the email from the token, or return the anonymous user.

class JsonWebKey#

class rootski.services.auth.JsonWebKey(*, kid: str, kty: str, **extra_data: Any)[source]#

Bases: pydantic.main.BaseModel

Learn about Cognito JWKs here: https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html

classmethod construct(_fields_set: Optional[SetStr] = None, **values: Any) Model#

Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data. Default values are respected, but no other validation is performed. Behaves as if Config.extra = ‘allow’ was set since it adds all passed values

copy(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, update: Optional[DictStrAny] = None, deep: bool = False) Model#

Duplicate a model, optionally choose which fields to include, exclude and change.

Parameters
  • include – fields to include in new model

  • exclude – fields to exclude from new model, as with values this takes precedence over include

  • update – values to change/add in the new model. Note: the data is not validated before creating the new model: you should trust this data

  • deep – set to True to make a deep copy of the model

Returns

new model instance

dict(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False) DictStrAny#

Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.

json(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, encoder: Optional[Callable[[Any], Any]] = None, models_as_dict: bool = True, **dumps_kwargs: Any) unicode#

Generate a JSON representation of the model, include and exclude arguments as per dict().

encoder is an optional function to supply as default to json.dumps(), other arguments as per json.dumps().

classmethod update_forward_refs(**localns: Any) None#

Try to update ForwardRefs on fields based on this Model, globalns and localns.

class JsonWebKeySet#

class rootski.services.auth.JsonWebKeySet(*, keys: List[rootski.services.auth.JsonWebKey], **extra_data: Any)[source]#

Bases: pydantic.main.BaseModel

classmethod construct(_fields_set: Optional[SetStr] = None, **values: Any) Model#

Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data. Default values are respected, but no other validation is performed. Behaves as if Config.extra = ‘allow’ was set since it adds all passed values

copy(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, update: Optional[DictStrAny] = None, deep: bool = False) Model#

Duplicate a model, optionally choose which fields to include, exclude and change.

Parameters
  • include – fields to include in new model

  • exclude – fields to exclude from new model, as with values this takes precedence over include

  • update – values to change/add in the new model. Note: the data is not validated before creating the new model: you should trust this data

  • deep – set to True to make a deep copy of the model

Returns

new model instance

dict(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False) DictStrAny#

Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.

json(*, include: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, exclude: Optional[Union[AbstractSetIntStr, MappingIntStrAny]] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, encoder: Optional[Callable[[Any], Any]] = None, models_as_dict: bool = True, **dumps_kwargs: Any) unicode#

Generate a JSON representation of the model, include and exclude arguments as per dict().

encoder is an optional function to supply as default to json.dumps(), other arguments as per json.dumps().

classmethod update_forward_refs(**localns: Any) None#

Try to update ForwardRefs on fields based on this Model, globalns and localns.