Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sources/oauth: add group sync for azure_ad #12894

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions authentik/sources/oauth/types/azure_ad.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import Any

from requests import RequestException
from structlog.stdlib import get_logger

from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
Expand All @@ -17,14 +18,41 @@

def get_additional_parameters(self, source): # pragma: no cover
return {
"scope": ["openid", "https://graph.microsoft.com/User.Read"],
"scope": [
"openid",
"https://graph.microsoft.com/User.Read",
"https://graph.microsoft.com/GroupMember.Read.All",
],
}


class AzureADClient(UserprofileHeaderAuthClient):
"""Fetch AzureAD group information"""

def get_profile_info(self, token):
profile_data = super().get_profile_info(token)
group_response = self.session.request(

Check warning on line 34 in authentik/sources/oauth/types/azure_ad.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/oauth/types/azure_ad.py#L33-L34

Added lines #L33 - L34 were not covered by tests
"get",
"https://graph.microsoft.com/v1.0/me/memberOf",
headers={"Authorization": f"{token['token_type']} {token['access_token']}"},
)
try:
group_response.raise_for_status()
except RequestException as exc:
LOGGER.warning(

Check warning on line 42 in authentik/sources/oauth/types/azure_ad.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/oauth/types/azure_ad.py#L39-L42

Added lines #L39 - L42 were not covered by tests
"Unable to fetch user profile",
exc=exc,
response=exc.response.text if exc.response else str(exc),
)
return None
profile_data["raw_groups"] = group_response.json()
return profile_data

Check warning on line 49 in authentik/sources/oauth/types/azure_ad.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/oauth/types/azure_ad.py#L47-L49

Added lines #L47 - L49 were not covered by tests


class AzureADOAuthCallback(OpenIDConnectOAuth2Callback):
"""AzureAD OAuth2 Callback"""

client_class = UserprofileHeaderAuthClient
client_class = AzureADClient

def get_user_id(self, info: dict[str, str]) -> str:
# Default try to get `id` for the Graph API endpoint
Expand Down Expand Up @@ -53,8 +81,24 @@

def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
mail = info.get("mail", None) or info.get("otherMails", [None])[0]
# Format group info
groups = []
group_id_dict = {}
for group in info.get("raw_groups", {}).get("value", []):
if group["@odata.type"] != "#microsoft.graph.group":
continue
groups.append(group["id"])
group_id_dict[group["id"]] = group

Check warning on line 91 in authentik/sources/oauth/types/azure_ad.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/oauth/types/azure_ad.py#L88-L91

Added lines #L88 - L91 were not covered by tests
info["raw_groups"] = group_id_dict
return {
"username": info.get("userPrincipalName"),
"email": mail,
"name": info.get("displayName"),
"groups": groups,
}

def get_base_group_properties(self, source, group_id, **kwargs):
raw_group = kwargs["info"]["raw_groups"][group_id]
return {

Check warning on line 102 in authentik/sources/oauth/types/azure_ad.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/oauth/types/azure_ad.py#L101-L102

Added lines #L101 - L102 were not covered by tests
"name": raw_group["displayName"],
}
Loading