auth, work in progress: decode id_token, + other improvements
This commit is contained in:
parent
87310b9798
commit
01fc7d2874
4 changed files with 30 additions and 10 deletions
|
@ -28,7 +28,7 @@ dbpassword = getenv('DBPASSWORD', 'secret')
|
||||||
dbschema = getenv('DBSCHEMA', 'demo')
|
dbschema = getenv('DBSCHEMA', 'demo')
|
||||||
|
|
||||||
# authentication settings
|
# authentication settings
|
||||||
oidc_provider = 'https://a1.cy7.de'
|
oidc_provider = getenv('OIDC_PROVIDER', 'https://a1.cy7.de')
|
||||||
oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525')
|
oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525')
|
||||||
oidc_params = dict(
|
oidc_params = dict(
|
||||||
op_config_url=oidc_provider + '/.well-known/openid-configuration',
|
op_config_url=oidc_provider + '/.well-known/openid-configuration',
|
||||||
|
|
|
@ -5,10 +5,10 @@ from scopes.storage import topic
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import waitress
|
import waitress
|
||||||
from wsgiref.simple_server import make_server
|
|
||||||
|
|
||||||
|
|
||||||
def run(app, config):
|
def run(app, config):
|
||||||
|
oidc.startup() # todo: use generic app.startServices()
|
||||||
port = int(config.server_port)
|
port = int(config.server_port)
|
||||||
print(f'Serving on port {port}.')
|
print(f'Serving on port {port}.')
|
||||||
waitress.serve(app, port=port)
|
waitress.serve(app, port=port)
|
||||||
|
|
|
@ -29,5 +29,5 @@ def test_app(self, config):
|
||||||
|
|
||||||
def test_auth(self, config):
|
def test_auth(self, config):
|
||||||
from scopes.web.auth import oidc
|
from scopes.web.auth import oidc
|
||||||
oidc.loadOidcProviderData()
|
oidc.startup() # todo: use generic app.startServices()
|
||||||
self.assertEqual(len(config.oidc_params['op_uris']), 8)
|
self.assertEqual(len(config.oidc_params['op_uris']), 8)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
from email.utils import formatdate
|
from email.utils import formatdate
|
||||||
import json
|
import json
|
||||||
|
import jwt
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
from time import time
|
from time import time
|
||||||
|
@ -103,7 +104,6 @@ class Authenticator(DummyFolder):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
loadOidcProviderData()
|
|
||||||
req = self.request
|
req = self.request
|
||||||
#print('***', dir(req))
|
#print('***', dir(req))
|
||||||
state = util.rndstr()
|
state = util.rndstr()
|
||||||
|
@ -142,7 +142,9 @@ class Authenticator(DummyFolder):
|
||||||
tokenUrl = self.params['op_uris']['token_endpoint']
|
tokenUrl = self.params['op_uris']['token_endpoint']
|
||||||
tokenResponse = requests.post(tokenUrl, data=args)
|
tokenResponse = requests.post(tokenUrl, data=args)
|
||||||
tdata = tokenResponse.json()
|
tdata = tokenResponse.json()
|
||||||
#print('*** token response', tdata)
|
print('*** token response', tdata)
|
||||||
|
claims = self.getIdTokenData(tdata['id_token'])
|
||||||
|
print('*** token id claims', claims)
|
||||||
headers = dict(Authorization='Bearer ' + tdata['access_token'])
|
headers = dict(Authorization='Bearer ' + tdata['access_token'])
|
||||||
userInfoUrl = self.params['op_uris']['userinfo_endpoint']
|
userInfoUrl = self.params['op_uris']['userinfo_endpoint']
|
||||||
userInfo = requests.get(userInfoUrl, headers=headers)
|
userInfo = requests.get(userInfoUrl, headers=headers)
|
||||||
|
@ -189,7 +191,6 @@ class Authenticator(DummyFolder):
|
||||||
cookie = self.request.getCookies().get(self.params['cookie_name'])
|
cookie = self.request.getCookies().get(self.params['cookie_name'])
|
||||||
if cookie is None:
|
if cookie is None:
|
||||||
return {}
|
return {}
|
||||||
#raise ValueError('Missing authentication cookie')
|
|
||||||
if self.cookieCrypt:
|
if self.cookieCrypt:
|
||||||
cookie = self.cookieCrypt.decrypt(cookie)
|
cookie = self.cookieCrypt.decrypt(cookie)
|
||||||
#print('*** loadSession', self.params['cookie_name'], cookie)
|
#print('*** loadSession', self.params['cookie_name'], cookie)
|
||||||
|
@ -197,6 +198,23 @@ class Authenticator(DummyFolder):
|
||||||
data = json.loads(cookie)
|
data = json.loads(cookie)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def getIdTokenData(self, token):
|
||||||
|
keyUri = self.params['op_uris']['jwks_uri']
|
||||||
|
jwksClient = jwt.PyJWKClient(keyUri)
|
||||||
|
key = jwksClient.get_signing_key_from_jwt(token)
|
||||||
|
return jwt.decode(token, key, options=dict(verify_aud=False))
|
||||||
|
header = jwt.get_unverified_header(token)
|
||||||
|
kid = header['kid']
|
||||||
|
key = self.loadOidcKeys()[kid]
|
||||||
|
return jwt.decode(token, key, audience=self.params.client_id)
|
||||||
|
|
||||||
|
def loadOidcKeys(self):
|
||||||
|
result = {}
|
||||||
|
keyUri = self.params['op_uris']['jwks_uri']
|
||||||
|
for k in requests.get(keyUri).json()['keys']:
|
||||||
|
result[k['kid']] = jwt.PyJWK(k)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@register('auth', Root)
|
@register('auth', Root)
|
||||||
def authView(context, request):
|
def authView(context, request):
|
||||||
|
@ -218,6 +236,11 @@ def logout(context, request):
|
||||||
return DefaultView(context, request)
|
return DefaultView(context, request)
|
||||||
|
|
||||||
|
|
||||||
|
def startup():
|
||||||
|
loadOidcProviderData()
|
||||||
|
#app.Publication.registerBeforeTraversal(
|
||||||
|
# lambda req: req.setPrincipal(authentication.authenticate(req))
|
||||||
|
|
||||||
oidcProviderUris = ['authorization_endpoint', 'token_endpoint',
|
oidcProviderUris = ['authorization_endpoint', 'token_endpoint',
|
||||||
'introspection_endpoint', 'userinfo_endpoint',
|
'introspection_endpoint', 'userinfo_endpoint',
|
||||||
'revocation_endpoint', 'end_session_endpoint',
|
'revocation_endpoint', 'end_session_endpoint',
|
||||||
|
@ -230,8 +253,5 @@ def loadOidcProviderData(force=False):
|
||||||
opData = requests.get(params['op_config_url']).json()
|
opData = requests.get(params['op_config_url']).json()
|
||||||
for key in oidcProviderUris:
|
for key in oidcProviderUris:
|
||||||
uris[key] = opData[key]
|
uris[key] = opData[key]
|
||||||
if force or params.get('op_keys') is None:
|
#if force or params.get('op_keys') is None:
|
||||||
params['op_keys'] = requests.get(uris['jwks_uri']).json()['keys']
|
params['op_keys'] = requests.get(uris['jwks_uri']).json()['keys']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue