oidc auth: improvements, store info in cookie

This commit is contained in:
Helmut Merz 2025-03-26 15:43:50 +01:00
parent 0207d12b46
commit c1f07effee
2 changed files with 64 additions and 24 deletions

View file

@ -7,6 +7,7 @@ from scopes.server.app import zope_app_factory
load_dotenv()
server_port = getenv('SERVER_PORT', '8099')
base_url = getenv('BASE_URL', 'https://demo.cy7.de')
app_factory = zope_app_factory
@ -19,8 +20,14 @@ dbpassword = getenv('DBPASSWORD', 'secret')
dbschema = getenv('DBSCHEMA', 'demo')
# authentication settings
oidc_provider = 'https://a1.cy7.de'
oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525')
oidc_params = dict(
provider_url=getenv('OIDC_PROVIDER_URL', 'https://a1.cy7.de/oauth/v2/authorize'),
client_id=getenv('OIDC_CLIENT_ID', '311613119816392525'),
callback_url=getenv('OIDC_CALLBACK_URL', 'https://demo.cy7.de/auth/callback'),
auth_url=getenv('OIDC_PROVIDER_URL', oidc_provider + '/oauth/v2/authorize'),
callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'),
client_id = oidc_client_id,
cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id),
cookie_domain=getenv('OIDC_COOKIE_DOMAIN', 'cy7.de'),
cookie_lifetime=getenv('OIDC_COOKIE_LIFETIME', '86400'),
)

View file

@ -1,8 +1,10 @@
# scopes.server.auth
from oic import oic, rndstr
from email.utils import formatdate
import json
from oic import oic, rndstr, unreserved
from oic.oic.message import AuthorizationResponse
from time import time
from zope.authentication.interfaces import IAuthentication
from zope.interface import implementer
from zope.publisher.interfaces import Unauthorized
@ -53,48 +55,79 @@ class Authenticator(DummyFolder):
prefix = 'auth'
def __init__(self, request):
self.request = request
self.params = config.oidc_params
def authenticate(request):
return None
def login(self, request):
params = config.oidc_params
print('*** login', self, request.getTraversalStack(), request['PATH_INFO'])
#print('***', dir(request))
def login(self):
req = self.request
print('*** login', self, req.getTraversalStack(), req['PATH_INFO'])
#print('***', dir(req))
client = oic.Client()
#providerInfo = client.provider_config(params['provider_url'])
#print('***', providerInfo)
#client.register(providerInfo['registration_endpoint'], application_type='web')
requestArgs = dict(
client_id=params['client_id'],
state = rndstr()
nonce = rndstr()
args = dict(
client_id=self.params['client_id'],
response_type='code', # 'code id_token token',
state=rndstr(), nonce=rndstr(),
state=state, nonce=nonce,
scope=['openid', 'profile'],
redirect_uri=params['callback_url'],
redirect_uri=self.params['callback_url'],
)
authReq = client.construct_AuthorizationRequest(request_args=requestArgs)
#loginUrl = authReq.request(client.authorization_endpoint)
loginUrl = authReq.request(params['provider_url'])
addArgs, codeVerifyer = client.add_code_challenge()
args.update(addArgs)
self.storeSession(dict(state=state, nonce=nonce, codeVerifyer=codeVerifyer))
authReq = client.construct_AuthorizationRequest(request_args=args)
loginUrl = authReq.request(self.params['auth_url'])
print('***', loginUrl)
request.response.redirect(loginUrl, trusted=True)
req.response.redirect(loginUrl, trusted=True)
def callback(self, request):
print('*** callback', self, request.form)
code = request.form['code']
def callback(self):
req = self.request
print('*** callback', self, req.form)
data = self.loadSession()
code = req.form['code']
client = oic.Client()
print('***', data, code, client)
def storeSession(self, data):
options = {}
lifetime = int(self.params['cookie_lifetime'])
options['expires'] = formatdate(time() + lifetime, localtime=False, usegmt=True)
options['max-age'] = lifetime
domain = self.params['cookie_domain']
if domain:
options['domain'] = domain
#options['httponly'] = True
name = self.params['cookie_name']
value = json.dumps(data)
self.request.response.setCookie(name, value, **options)
def loadSession(self):
cookie = self.request.getCookies().get(self.params['cookie_name'])
if cookie is None:
raise ValueError('Missing authentication cookie')
data = json.loads(cookie)
return data
@register('auth', Root)
def authView(context, request):
print('*** auth', context, request['PATH_INFO'])
return Authenticator()
return Authenticator(request)
@register('login', Authenticator)
def login(context, request):
context.login(request)
context.login()
return DefaultView(context, request)
@register('callback', Authenticator)
def callback(context, request):
context.callback(request)
context.callback()
return DefaultView(context, request)
@register('logout', Authenticator)