auth ist im kasten
This commit is contained in:
1 parent
8498781c85
commit
7f81932fa5
14 files changed
+843
-443
No files matched your search
+38
-13
@@ -87,7 +87,6 @@ class AuthService:
|
||||
"""
|
||||
config = current_app.config
|
||||
|
||||
# Use configured dev user settings or defaults
|
||||
dev_user = {
|
||||
'id': config.get('DEV_USER_ID', 'user_dev_admin_001'),
|
||||
'email': config.get('DEV_USER_EMAIL', 'dev@formeleon.local'),
|
||||
@@ -110,7 +109,6 @@ class AuthService:
|
||||
"""
|
||||
config = current_app.config
|
||||
|
||||
# Use configured mock user settings or defaults
|
||||
mock_user = {
|
||||
'id': config.get('MOCK_USER_ID', 'mock_user_001'),
|
||||
'email': config.get('MOCK_USER_EMAIL', 'mock@formeleon.local'),
|
||||
@@ -180,7 +178,8 @@ class AuthService:
|
||||
@staticmethod
|
||||
def process_oidc_callback(user_info: dict) -> Tuple[Optional[User], Optional[str]]:
|
||||
"""
|
||||
Process user information from OIDC callback and create/update user.
|
||||
Process user information from OIDC callback, evaluate Zitadel roles,
|
||||
and create/update the local user record.
|
||||
|
||||
:param user_info: User information dictionary from OIDC provider
|
||||
:return: Tuple of (User object or None, error message or None)
|
||||
@@ -189,11 +188,35 @@ class AuthService:
|
||||
email = user_info.get('email')
|
||||
name = user_info.get('name', user_info.get('preferred_username', 'Unknown'))
|
||||
|
||||
if not email:
|
||||
return None, 'No email in user info'
|
||||
if not email or not sub:
|
||||
return None, 'Incomplete user info from OIDC provider (missing sub or email).'
|
||||
|
||||
# Create or update user
|
||||
user = User.query.filter_by(sub=sub).first()
|
||||
# 1. Zitadel-Rollen extrahieren
|
||||
# Zitadel liefert Projektrollen im Claim 'urn:zitadel:iam:org:project:roles'
|
||||
raw_roles = user_info.get('urn:zitadel:iam:org:project:roles', {})
|
||||
|
||||
if isinstance(raw_roles, dict):
|
||||
user_roles = list(raw_roles.keys())
|
||||
elif isinstance(raw_roles, list):
|
||||
user_roles = raw_roles
|
||||
else:
|
||||
user_roles = []
|
||||
|
||||
logger.debug(f"Extracted OIDC roles for {email}: {user_roles}")
|
||||
|
||||
# 2. Hard Gate: Zugriff verweigern, wenn keine der erlaubt Formeleon-Rollen zugewiesen ist
|
||||
has_admin_role = 'form-admins' in user_roles
|
||||
has_user_role = 'form-users' in user_roles
|
||||
|
||||
if not (has_admin_role or has_user_role):
|
||||
logger.warning(f"Access denied for {email}. Missing required roles ('form-admins' or 'form-users'). Roles present: {user_roles}")
|
||||
return None, 'Access denied: You do not have permission to access Formeleon.'
|
||||
|
||||
# 3. Formeleon-Rolle festlegen (Admin schlägt User)
|
||||
assigned_role = UserRole.ADMIN if has_admin_role else UserRole.USER
|
||||
|
||||
# 4. User suchen oder neu anlegen
|
||||
user = User.query.filter((User.sub == sub) | (User.email == email)).first()
|
||||
|
||||
if not user:
|
||||
user_id = f'user_{email.split("@")[0]}_{str(uuid.uuid4())[:8]}'
|
||||
@@ -201,16 +224,18 @@ class AuthService:
|
||||
id=user_id,
|
||||
email=email,
|
||||
name=name,
|
||||
role=UserRole.USER, # Default role for new OIDC users
|
||||
role=assigned_role,
|
||||
sub=sub
|
||||
)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
logger.info(f'Created new user from OIDC: {user.id}')
|
||||
logger.info(f'Created new user from OIDC: {user.id} with role {assigned_role.value}')
|
||||
else:
|
||||
# Update existing user
|
||||
# Re-sync Name, Sub und Rolle bei jedem Login
|
||||
user.name = name
|
||||
user.sub = sub
|
||||
user.email = email
|
||||
db.session.commit()
|
||||
user.role = assigned_role
|
||||
logger.info(f'Updated existing user from OIDC: {user.id} (Role: {assigned_role.value})')
|
||||
|
||||
return user, None
|
||||
db.session.commit()
|
||||
return user, None
|
||||
Reference in new issue
Block a user