OIDC auth: directly use sub from JWT if appropriate; optionally add groups from calling application

This commit is contained in:
Helmut Merz 2025-08-06 17:51:15 +02:00
parent 775603046a
commit 94365602ca

View file

@ -60,8 +60,6 @@ authentication = OidcAuthentication(None)
@implementer(IGroupAwarePrincipal) @implementer(IGroupAwarePrincipal)
class Principal: class Principal:
group_prefix = 'gloops.'
def __init__(self, id, data): def __init__(self, id, data):
self.id = id self.id = id
self.data = data self.data = data
@ -72,8 +70,7 @@ class Principal:
@property @property
def groups(self): def groups(self):
groups = [self.group_prefix + g for g in self.data.get('groups', [])] return self.data.get('groups', [])
return groups
def asDict(self): def asDict(self):
data = self.data.copy() data = self.data.copy()
@ -85,6 +82,8 @@ class Authenticator(DummyFolder):
prefix = 'auth.oidc' prefix = 'auth.oidc'
group_prefix = 'gloops.'
def __init__(self, request): def __init__(self, request):
self.request = request self.request = request
self.params = config.oidc_params self.params = config.oidc_params
@ -98,7 +97,7 @@ class Authenticator(DummyFolder):
data = self.loadSession() data = self.loadSession()
logger.debug('authenticate: %s', data) logger.debug('authenticate: %s', data)
if data and 'userid' in data: if data and 'userid' in data:
id = self.params.get('principal_prefix', '') + data.pop('userid') id = data.pop('userid')
return Principal(id, data) return Principal(id, data)
return None return None
@ -123,7 +122,7 @@ class Authenticator(DummyFolder):
logger.debug('login: URL %s', loginUrl) logger.debug('login: URL %s', loginUrl)
self.request.response.redirect(loginUrl, trusted=True) self.request.response.redirect(loginUrl, trusted=True)
def callback(self): def callback(self, groupsProvider=None):
req = self.request req = self.request
logger.debug('callback: %s %s', self, req.form) logger.debug('callback: %s %s', self, req.form)
sdata = self.loadSession() sdata = self.loadSession()
@ -142,12 +141,19 @@ class Authenticator(DummyFolder):
tokenResponse = requests.post(tokenUrl, data=args) tokenResponse = requests.post(tokenUrl, data=args)
tdata = tokenResponse.json() tdata = tokenResponse.json()
userData = self.getIdTokenData(tdata['id_token']) userData = self.getIdTokenData(tdata['id_token'])
groupInfo = userData.get('urn:zitadel:iam:org:project:roles', {}) userId = userData['sub']
if not '.' in userId:
userId = (self.params.get('principal_prefix', '') +
userData['preferred_username'])
groups = userData.get('urn:zitadel:iam:org:project:roles', {})
groups = set(self.group_prefix + g for g in groups)
if groupsProvider is not None:
groups = groups.union(groupsProvider(userId))
ndata = dict( ndata = dict(
userid=userData['preferred_username'], userid=userId,
name=userData['name'], name=userData['name'],
email=userData['email'], email=userData['email'],
groups=list(groupInfo.keys()), groups=list(groups),
access_token=tdata['access_token'], access_token=tdata['access_token'],
session_id=userData['sid'], session_id=userData['sid'],
) )