from datetime import datetime, timedelta, timezone import jwt from flask import current_app class BaseBearerToken: ENCODING_ALGORITHM = "RS256" DEFAULT_TIME_TO_LIVE = 60 * 5 def __init__(self, ttl): self._ttl = ttl def claimset_at(self, now): claimset = self.durable_claims.copy() ts_now = now.timestamp() ts_exp = (now + timedelta(seconds=self.ttl)).timestamp() claimset["iss"] = current_app.config["JWT_TOKEN_ISS"] claimset["iat"] = int(ts_now) claimset["exp"] = int(ts_exp) claimset["nbf"] = int(ts_now) return claimset def encode_at(self, datetime): private_key = current_app.config["DNA_IDENTITY_PRIVATE_KEY"] headers = {} kid = current_app.config.get("JWT_TOKEN_KID") if kid: headers["kid"] = kid return jwt.encode( self.claimset_at(datetime), private_key, self.ENCODING_ALGORITHM, headers=headers, ) def encode(self): return self.encode_at(datetime.now(timezone.utc)) @property def ttl(self): return self._ttl or self.DEFAULT_TIME_TO_LIVE @property def durable_claims(self): return {} class DNABearerToken(BaseBearerToken): def __init__(self, dna_account, resource_group=None, ttl=None): self._dna_account = dna_account self._resource_group = resource_group super().__init__(ttl) @property def dna_account(self): return self._dna_account @property def durable_claims(self): return self._dna_account.serialize_claims(self._resource_group) @property def token_length(self): return len(self.encode().encode("utf-8")) class M2MBearerToken(BaseBearerToken): DEFAULT_TIME_TO_LIVE = 60 * 60 * 24 def __init__(self, application, ttl=None): self._application = application super().__init__(ttl) @property def application(self): return self._application @property def durable_claims(self): return self._application.serialize_claims() @property def ttl(self): return self._ttl or self._application.ttl or self.DEFAULT_TIME_TO_LIVE