auth improvements (JWT stuff, esp tests); new: storage.message (event store)
This commit is contained in:
parent
5eb9531997
commit
ee5a76a808
4 changed files with 38 additions and 25 deletions
20
scopes/storage/message.py
Normal file
20
scopes/storage/message.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# scopes.storage.message
|
||||
|
||||
"""Generic messages (or events) to be stored in SQL database."""
|
||||
|
||||
from scopes.storage.common import registerContainerClass
|
||||
from scopes.storage.tracking import Container, Track
|
||||
|
||||
class Message(Track):
|
||||
|
||||
headFields = ['domain', 'action', 'class', 'item']
|
||||
prefix = 'msg'
|
||||
|
||||
|
||||
@registerContainerClass
|
||||
class Messages(Container):
|
||||
|
||||
itemFactory = Message
|
||||
indexes = [('domain', 'action', 'class', 'item'), ('domain', 'class', 'item')]
|
||||
tableName = 'messages'
|
||||
insertOnChange = True
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
"""provide response data for testing (via dummy_requests)"""
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from scopes import util
|
||||
|
||||
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||
public_key = private_key.public_key()
|
||||
public_key_n = util.b64e(public_key.public_numbers().n.to_bytes(256)).decode('ASCII')
|
||||
|
||||
oidc_data = {
|
||||
'test://oidc/.well-known/openid-configuration': {
|
||||
"issuer": "test://oidc",
|
||||
|
@ -14,17 +21,11 @@ oidc_data = {
|
|||
"device_authorization_endpoint": "test://oidc/oauth/v2/device_authorization",
|
||||
"jwks_uri": "test://oidc/oauth/v2/keys"},
|
||||
'test://oidc/oauth/v2/keys': { "keys": [
|
||||
{"use": "sig",
|
||||
"kty": "RSA",
|
||||
"kid": "316638486247563085",
|
||||
"alg": "RS256",
|
||||
"n": "167qFCfRa0tRR0MZv-PQVwdiVFf0NtfN-zFAogRASm6437sbXfsfxkpbh1F77TwQdl4qlR5Na_Ecs8VTxOuyHmuhIJ4FyZV4M0h71KRw7LCTVuNw7mWLpbjKPBzidyhctbkJrkcKtJymnHELsct0CdT16Lb27phd_0cBJexGbwhVNQBs10VbkvUJHHOJe6A_JVS9Q3_3MEWyCyFoHPeMchlk_Gd6yMiH4aJ1ql3GZD6c2JB9crloTH_oPWWFQObGoXTKcFonEBdkrwuCQfRVOfGh8UIhIcTM0JNgqtQOCcIkf0emfI30SoWSc6Qz8lU70Vpmb3qQgsqATFICgzgABw",
|
||||
"e": "AQAB"},
|
||||
{"use": "sig",
|
||||
"kty": "RSA",
|
||||
"kid": "316766976250797901",
|
||||
"alg": "RS256",
|
||||
"n": "yZKIsrUWT2fEj4OtUUFYQbEe_Clodz464tn5vMAQ0q8zV07bqFaA7WKuBflowYctDNxoxdbiFNISpKEOx6yFnx7_g6Zd46DWsj5ggGZvNkgOa9SqTIsA7ho9nk7LDLQRpV0k5N1HkiG66GUqUCV2llJhstpTDQQLDvhI3qussG2HyylpTQSu-9b6gry0rb397yjAnXQu6tFOubEDteTN0fLNMblcdd2AvZKpGA2o_-M5U6AckezfmBCBdHWmrwxpjGGf7KWqGg8j6bJkV3sMg4XfD2x0KNog_3D-0pSx6k8dSWZGkNlDxB5AdWvNDYg1stkvjeNEbIJAhv0-awLs9Q",
|
||||
"n": public_key_n,
|
||||
"e": "AQAB"}]}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,3 +37,6 @@ def test_auth(self, config):
|
|||
headers = dict(response.getHeaders())
|
||||
logger.info('test_auth: response %s %s', response.getStatus(), headers)
|
||||
self.assertEqual(response.getStatus(), 302)
|
||||
uri = config.oidc_params['op_uris']['jwks_uri']
|
||||
keys = oidc.loadOidcKeys(uri)
|
||||
logger.info('test_auth keys: %s', keys)
|
||||
|
|
|
@ -104,8 +104,6 @@ class Authenticator(DummyFolder):
|
|||
return None
|
||||
|
||||
def login(self):
|
||||
req = self.request
|
||||
#print('***', dir(req))
|
||||
state = util.rndstr()
|
||||
nonce = util.rndstr()
|
||||
codeVerifier = util.rndstr2()
|
||||
|
@ -123,7 +121,7 @@ class Authenticator(DummyFolder):
|
|||
authUrl = self.params['op_uris']['authorization_endpoint']
|
||||
loginUrl = '?'.join((authUrl, urlencode(args)))
|
||||
logger.debug('login: URL %s', loginUrl)
|
||||
req.response.redirect(loginUrl, trusted=True)
|
||||
self.request.response.redirect(loginUrl, trusted=True)
|
||||
|
||||
def callback(self):
|
||||
req = self.request
|
||||
|
@ -142,24 +140,18 @@ class Authenticator(DummyFolder):
|
|||
tokenUrl = self.params['op_uris']['token_endpoint']
|
||||
tokenResponse = requests.post(tokenUrl, data=args)
|
||||
tdata = tokenResponse.json()
|
||||
#print('*** token response', tdata)
|
||||
userData = self.getIdTokenData(tdata['id_token'])
|
||||
#print('*** token id claims', userData)
|
||||
#headers = dict(Authorization='Bearer ' + tdata['access_token'])
|
||||
#userInfoUrl = self.params['op_uris']['userinfo_endpoint']
|
||||
#userData = requests.get(userInfoUrl, headers=headers).json()
|
||||
#print('*** user data', userData)
|
||||
groupInfo = userData.get('urn:zitadel:iam:org:project:roles', {})
|
||||
#print('*** group info', groupInfo)
|
||||
groupInfo = userData.get('urn:zitadel:iam:org:project:roles')
|
||||
ndata = dict(
|
||||
userid=userData['preferred_username'],
|
||||
name=userData['name'],
|
||||
email=userData['email'],
|
||||
groups=list(groupInfo.keys()),
|
||||
access_token=tdata['access_token'],
|
||||
session_id=userData['sid'],
|
||||
)
|
||||
self.storeSession(ndata)
|
||||
logger.debug('callback: session data: %s', ndata)
|
||||
req.response.redirect(self.reqUrl, trusted=True)
|
||||
|
||||
def logout(self):
|
||||
|
@ -173,7 +165,7 @@ class Authenticator(DummyFolder):
|
|||
options = dict(
|
||||
path='/',
|
||||
expires=formatdate(time() + lifetime, localtime=False, usegmt=True),
|
||||
#httponly=True,
|
||||
httponly=True,
|
||||
)
|
||||
options['max-age'] = lifetime
|
||||
domain = self.params['cookie_domain']
|
||||
|
@ -181,7 +173,6 @@ class Authenticator(DummyFolder):
|
|||
options['domain'] = domain
|
||||
name = self.params['cookie_name']
|
||||
value = json.dumps(data)
|
||||
#print('*** storeSession', name, value, options)
|
||||
if self.cookieCrypt:
|
||||
value = self.cookieCrypt.encrypt(value.encode('UTF-8')).decode('ASCII')
|
||||
self.request.response.setCookie(name, value, **options)
|
||||
|
@ -192,7 +183,6 @@ class Authenticator(DummyFolder):
|
|||
return {}
|
||||
if self.cookieCrypt:
|
||||
cookie = self.cookieCrypt.decrypt(cookie)
|
||||
#print('*** loadSession', self.params['cookie_name'], cookie)
|
||||
# !error check: return None - or raise error?
|
||||
data = json.loads(cookie)
|
||||
return data
|
||||
|
@ -205,10 +195,6 @@ class Authenticator(DummyFolder):
|
|||
return jwt.decode(token, key, audience=self.params['client_id'])
|
||||
|
||||
|
||||
def loadOidcKeys(uri):
|
||||
return dict((item['kid'], item) for item in requests.get(uri).json()['keys'])
|
||||
|
||||
|
||||
@register('auth')
|
||||
def authView(context, request):
|
||||
return Authenticator(request)
|
||||
|
@ -248,3 +234,6 @@ def loadOidcProviderData(force=False):
|
|||
uris[key] = opData[key]
|
||||
#if force or params.get('op_keys') is None:
|
||||
#params['op_keys'] = requests.get(uris['jwks_uri']).json()['keys']
|
||||
|
||||
def loadOidcKeys(uri):
|
||||
return dict((item['kid'], item) for item in requests.get(uri).json()['keys'])
|
||||
|
|
Loading…
Add table
Reference in a new issue