|  | 
| 89 | 89 | auth_manager_config.OAUTH_UPDATE_PICTURE_ON_LOGIN = OAUTH_UPDATE_PICTURE_ON_LOGIN | 
| 90 | 90 | 
 | 
| 91 | 91 | 
 | 
|  | 92 | +# PATCH OIDC | 
|  | 93 | +def set_aak_groups(user_data: UserInfo) -> UserInfo: | 
|  | 94 | +    """ | 
|  | 95 | +    Set AAK groups based on AAK claims. AAK groups need to be parsed from a collection of AAK claims, | 
|  | 96 | +    so we cannot rely on Open WebUI's claims mapping. Parses the relevant AAK claims and adds them | 
|  | 97 | +    to the "groups" list. This enables us to rely on Open WebUI's role management for user role assignment. | 
|  | 98 | +
 | 
|  | 99 | +    To ensure unique group names, they are constructed as "<aak_department_name> (<aak_department_id>)". | 
|  | 100 | +
 | 
|  | 101 | +    Example claims: | 
|  | 102 | +
 | 
|  | 103 | +    "companyname": [ | 
|  | 104 | +        "Aarhus Kommune" | 
|  | 105 | +    ], | 
|  | 106 | +    "division": [ | 
|  | 107 | +        "Kultur og Borgerservice" | 
|  | 108 | +    ], | 
|  | 109 | +    "department": [ | 
|  | 110 | +        "Borgerservice og Biblioteker" | 
|  | 111 | +    ], | 
|  | 112 | +    "extensionAttribute12": [ | 
|  | 113 | +        "ITK" | 
|  | 114 | +    ], | 
|  | 115 | +    "Office": [ | 
|  | 116 | +        "ITK Development" | 
|  | 117 | +    ], | 
|  | 118 | +    "extensionAttribute7": [ | 
|  | 119 | +        "1001;1004;1012;1103;6530" | 
|  | 120 | +    ] | 
|  | 121 | +
 | 
|  | 122 | +    The ID's for the departments are given sequentially in "extensionAttribute7". Users in management postitions will | 
|  | 123 | +    not have five levels of AAK groups. This will show in the length of "extensionAttribute7" but will not show in the | 
|  | 124 | +    other claims. In the above example a manager will still have the "Office" claim, but it will repeat the value from | 
|  | 125 | +    "extensionAttribute12" and "extensionAttribute7 will only contain "1001;1004;1012;1103" | 
|  | 126 | +
 | 
|  | 127 | +    Note: ENABLE_OAUTH_GROUP_MANAGEMENT and ENABLE_OAUTH_GROUP_CREATION must be set to 'true' | 
|  | 128 | +
 | 
|  | 129 | +    Args: | 
|  | 130 | +        user_data (dict): The decoded OIDC token | 
|  | 131 | +
 | 
|  | 132 | +    Returns: | 
|  | 133 | +        The decoded OIDC token with the AAK group names added to the "groups" list. | 
|  | 134 | +    """ | 
|  | 135 | + | 
|  | 136 | +    log.debug("Running AAK Group management") | 
|  | 137 | +    log.debug(user_data) | 
|  | 138 | + | 
|  | 139 | +    user_data['groups'] = [] | 
|  | 140 | + | 
|  | 141 | +    dept_ids = user_data.get("extensionAttribute7", "").split(";") | 
|  | 142 | +    dept_depth = len(dept_ids) | 
|  | 143 | + | 
|  | 144 | +    if "companyname" in user_data and dept_depth >= 1: | 
|  | 145 | +        user_data['groups'].append(user_data.get("companyname", "") + " (" + dept_ids[0] + ")") | 
|  | 146 | +    if "division" in user_data and dept_depth >= 2: | 
|  | 147 | +        user_data['groups'].append(user_data.get("division", "") + " (" + dept_ids[1] + ")") | 
|  | 148 | +    if "department" in user_data and dept_depth >= 3: | 
|  | 149 | +        user_data['groups'].append(user_data.get("department", "") + " (" + dept_ids[2] + ")") | 
|  | 150 | +    if "extensionAttribute12" in user_data and dept_depth >= 4: | 
|  | 151 | +        user_data['groups'].append(user_data.get("extensionAttribute12", "") + " (" + dept_ids[3] + ")") | 
|  | 152 | +    if "Office" in user_data and dept_depth >= 5: | 
|  | 153 | +        user_data['groups'].append(user_data.get("Office", "") + " (" + dept_ids[4] + ")") | 
|  | 154 | + | 
|  | 155 | +    log.debug(f"Using groups {user_data.get('groups', '')}.") | 
|  | 156 | + | 
|  | 157 | +    return user_data | 
|  | 158 | + | 
|  | 159 | + | 
|  | 160 | +def set_aak_role(user_data: UserInfo) -> UserInfo: | 
|  | 161 | +    """ | 
|  | 162 | +    Set the AAK role based on AAK claims. For "builders" we cannot map to a native Open WebUI role. | 
|  | 163 | +    Instead, we add the role "Builder" to the list of groups. | 
|  | 164 | +
 | 
|  | 165 | +    Note: ENABLE_OAUTH_GROUP_MANAGEMENT and ENABLE_OAUTH_GROUP_CREATION must be set to 'true' | 
|  | 166 | +
 | 
|  | 167 | +    Args: | 
|  | 168 | +        user_data (dict): The decoded OIDC token | 
|  | 169 | +
 | 
|  | 170 | +    Returns: | 
|  | 171 | +        The decoded OIDC token with the AAK role added to the "groups" list. | 
|  | 172 | +    """ | 
|  | 173 | + | 
|  | 174 | +    log.debug("Running AAK Role management") | 
|  | 175 | +    log.debug(user_data) | 
|  | 176 | + | 
|  | 177 | +    claims_roles = user_data.get("role", "") | 
|  | 178 | + | 
|  | 179 | +    log.debug(f"Using aak_claims_role {claims_roles}.") | 
|  | 180 | + | 
|  | 181 | +    if "builder" in claims_roles: | 
|  | 182 | +        user_data['groups'].append("Builder") | 
|  | 183 | + | 
|  | 184 | +    log.debug(f"Using role-groups {user_data.get('groups', '')}.") | 
|  | 185 | + | 
|  | 186 | +    return user_data | 
|  | 187 | +# //PATCH OIDC | 
|  | 188 | + | 
|  | 189 | + | 
| 92 | 190 | def is_in_blocked_groups(group_name: str, groups: list) -> bool: | 
| 93 | 191 |     """ | 
| 94 | 192 |     Check if a group name matches any blocked pattern. | 
| @@ -597,15 +695,21 @@ async def handle_callback(self, request, provider, response): | 
| 597 | 695 |             # Try to get userinfo from the token first, some providers include it there | 
| 598 | 696 |             user_data: UserInfo = token.get("userinfo") | 
| 599 | 697 |             if ( | 
| 600 |  | -                (not user_data) | 
| 601 |  | -                or (auth_manager_config.OAUTH_EMAIL_CLAIM not in user_data) | 
| 602 |  | -                or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data) | 
|  | 698 | +                    (not user_data) | 
|  | 699 | +                    or (auth_manager_config.OAUTH_EMAIL_CLAIM not in user_data) | 
|  | 700 | +                    or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data) | 
| 603 | 701 |             ): | 
| 604 | 702 |                 user_data: UserInfo = await client.userinfo(token=token) | 
| 605 | 703 |             if not user_data: | 
| 606 | 704 |                 log.warning(f"OAuth callback failed, user data is missing: {token}") | 
| 607 | 705 |                 raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) | 
| 608 | 706 | 
 | 
|  | 707 | +            # PATCH OIDC | 
|  | 708 | +            # Set AAK role and groups | 
|  | 709 | +            user_data = set_aak_groups(user_data=user_data) | 
|  | 710 | +            user_data = set_aak_role(user_data=user_data) | 
|  | 711 | +            # //PATCH OIDC | 
|  | 712 | + | 
| 609 | 713 |             # Extract the "sub" claim, using custom claim if configured | 
| 610 | 714 |             if auth_manager_config.OAUTH_SUB_CLAIM: | 
| 611 | 715 |                 sub = user_data.get(auth_manager_config.OAUTH_SUB_CLAIM) | 
|  | 
0 commit comments