annotate get_agent.py @ 0:4365c72c59f6

start
author drewp@bigasterisk.com
date Sun, 27 Aug 2023 11:12:20 -0700
parents
children 76cec592435c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
drewp@bigasterisk.com
parents:
diff changeset
1 import datetime
drewp@bigasterisk.com
parents:
diff changeset
2 import json
drewp@bigasterisk.com
parents:
diff changeset
3 import logging
drewp@bigasterisk.com
parents:
diff changeset
4 from typing import Any, Dict
drewp@bigasterisk.com
parents:
diff changeset
5
drewp@bigasterisk.com
parents:
diff changeset
6 import aiohttp
drewp@bigasterisk.com
parents:
diff changeset
7 from attr import dataclass
drewp@bigasterisk.com
parents:
diff changeset
8 from jwskate import JwkSet, Jwt
drewp@bigasterisk.com
parents:
diff changeset
9 from rdflib import URIRef
drewp@bigasterisk.com
parents:
diff changeset
10 from starlette.requests import Request
drewp@bigasterisk.com
parents:
diff changeset
11
drewp@bigasterisk.com
parents:
diff changeset
12 log = logging.getLogger(__name__)
drewp@bigasterisk.com
parents:
diff changeset
13 tzlocal = datetime.datetime.now().astimezone().tzinfo
drewp@bigasterisk.com
parents:
diff changeset
14
drewp@bigasterisk.com
parents:
diff changeset
15 @dataclass
drewp@bigasterisk.com
parents:
diff changeset
16 class Agent:
drewp@bigasterisk.com
parents:
diff changeset
17 email: str
drewp@bigasterisk.com
parents:
diff changeset
18 agent: URIRef
drewp@bigasterisk.com
parents:
diff changeset
19 name: str
drewp@bigasterisk.com
parents:
diff changeset
20 issuedAt: datetime.datetime
drewp@bigasterisk.com
parents:
diff changeset
21 expiration: datetime.datetime
drewp@bigasterisk.com
parents:
diff changeset
22
drewp@bigasterisk.com
parents:
diff changeset
23 def asDict(self):
drewp@bigasterisk.com
parents:
diff changeset
24 now = datetime.datetime.now(tzlocal)
drewp@bigasterisk.com
parents:
diff changeset
25 return {
drewp@bigasterisk.com
parents:
diff changeset
26 'email': self.email,
drewp@bigasterisk.com
parents:
diff changeset
27 'agent': str(self.agent),
drewp@bigasterisk.com
parents:
diff changeset
28 'name': self.name,
drewp@bigasterisk.com
parents:
diff changeset
29 'issuedAt': {
drewp@bigasterisk.com
parents:
diff changeset
30 't': self.issuedAt.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
31 'secAgo': (now - self.issuedAt).total_seconds(),
drewp@bigasterisk.com
parents:
diff changeset
32 },
drewp@bigasterisk.com
parents:
diff changeset
33 'expiration': {
drewp@bigasterisk.com
parents:
diff changeset
34 't': self.expiration.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
35 'inSec': (self.expiration - now).total_seconds(),
drewp@bigasterisk.com
parents:
diff changeset
36 },
drewp@bigasterisk.com
parents:
diff changeset
37 'now': now.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
38 }
drewp@bigasterisk.com
parents:
diff changeset
39
drewp@bigasterisk.com
parents:
diff changeset
40
drewp@bigasterisk.com
parents:
diff changeset
41 def foafAgentFromAuthEmail(email: str) -> URIRef:
drewp@bigasterisk.com
parents:
diff changeset
42 return URIRef({
drewp@bigasterisk.com
parents:
diff changeset
43 'drewpca@gmail.com': 'http://bigasterisk.com/foaf.rdf#drewp',
drewp@bigasterisk.com
parents:
diff changeset
44 'kelsimp@gmail.com': 'http://bigasterisk.com/kelsi/foaf.rdf#kelsi',
drewp@bigasterisk.com
parents:
diff changeset
45 }[email])
drewp@bigasterisk.com
parents:
diff changeset
46
drewp@bigasterisk.com
parents:
diff changeset
47
drewp@bigasterisk.com
parents:
diff changeset
48 _jwkset: JwkSet | None = None
drewp@bigasterisk.com
parents:
diff changeset
49
drewp@bigasterisk.com
parents:
diff changeset
50
drewp@bigasterisk.com
parents:
diff changeset
51 async def loadJwkset() -> JwkSet:
drewp@bigasterisk.com
parents:
diff changeset
52 global _jwkset
drewp@bigasterisk.com
parents:
diff changeset
53 if _jwkset is None:
drewp@bigasterisk.com
parents:
diff changeset
54 log.info("loading jwks.json")
drewp@bigasterisk.com
parents:
diff changeset
55 async with aiohttp.ClientSession() as session:
drewp@bigasterisk.com
parents:
diff changeset
56 async with session.get('https://authenticate2.bigasterisk.com/.well-known/pomerium/jwks.json') as response:
drewp@bigasterisk.com
parents:
diff changeset
57 if response.status != 200:
drewp@bigasterisk.com
parents:
diff changeset
58 raise ValueError(f'{response.status=}')
drewp@bigasterisk.com
parents:
diff changeset
59
drewp@bigasterisk.com
parents:
diff changeset
60 ct = json.loads(await response.text())
drewp@bigasterisk.com
parents:
diff changeset
61 _jwkset = JwkSet(ct)
drewp@bigasterisk.com
parents:
diff changeset
62 return _jwkset
drewp@bigasterisk.com
parents:
diff changeset
63
drewp@bigasterisk.com
parents:
diff changeset
64
drewp@bigasterisk.com
parents:
diff changeset
65 async def getAgent(req: Request) -> Agent | None:
drewp@bigasterisk.com
parents:
diff changeset
66 jwkset = await loadJwkset()
drewp@bigasterisk.com
parents:
diff changeset
67 pomAssertion = req.headers.get('X-Pomerium-Jwt-Assertion', None)
drewp@bigasterisk.com
parents:
diff changeset
68 if pomAssertion is None:
drewp@bigasterisk.com
parents:
diff changeset
69 raise ValueError("missing X-Pomerium-Jwt-Assertion")
drewp@bigasterisk.com
parents:
diff changeset
70 jwt = Jwt(pomAssertion)
drewp@bigasterisk.com
parents:
diff changeset
71 jwt.validate(
drewp@bigasterisk.com
parents:
diff changeset
72 jwkset['keys'][0], #??
drewp@bigasterisk.com
parents:
diff changeset
73 algs=['ES256'],
drewp@bigasterisk.com
parents:
diff changeset
74 issuer='authenticate2.bigasterisk.com',
drewp@bigasterisk.com
parents:
diff changeset
75 audience='bigasterisk.com')
drewp@bigasterisk.com
parents:
diff changeset
76 claims: Dict[str, Any] = jwt.claims
drewp@bigasterisk.com
parents:
diff changeset
77 log.debug('claims=%r', claims)
drewp@bigasterisk.com
parents:
diff changeset
78 if not claims['email']:
drewp@bigasterisk.com
parents:
diff changeset
79 return None
drewp@bigasterisk.com
parents:
diff changeset
80
drewp@bigasterisk.com
parents:
diff changeset
81 return Agent(
drewp@bigasterisk.com
parents:
diff changeset
82 email=claims['email'],
drewp@bigasterisk.com
parents:
diff changeset
83 agent=foafAgentFromAuthEmail(claims['email']),
drewp@bigasterisk.com
parents:
diff changeset
84 expiration=datetime.datetime.fromtimestamp(claims['exp']).astimezone(tzlocal),
drewp@bigasterisk.com
parents:
diff changeset
85 issuedAt=datetime.datetime.fromtimestamp(claims['iat']).astimezone(tzlocal),
drewp@bigasterisk.com
parents:
diff changeset
86 name=claims['name'],
drewp@bigasterisk.com
parents:
diff changeset
87 )