diff --git a/fastapi_sso/sso/base.py b/fastapi_sso/sso/base.py index 8085074..243bdc7 100644 --- a/fastapi_sso/sso/base.py +++ b/fastapi_sso/sso/base.py @@ -71,7 +71,7 @@ class OpenID(pydantic.BaseModel): display_name: Optional[str] = None picture: Optional[str] = None provider: Optional[str] = None - + roles: Optional[list[str]] = None class SecurityWarning(UserWarning): """Raised when insecure usage is detected""" diff --git a/fastapi_sso/sso/microsoft.py b/fastapi_sso/sso/microsoft.py index ec6acea..ccfc0ce 100644 --- a/fastapi_sso/sso/microsoft.py +++ b/fastapi_sso/sso/microsoft.py @@ -4,7 +4,7 @@ import pydantic -from fastapi_sso.sso.base import DiscoveryDocument, OpenID, SSOBase +from fastapi_sso.sso.base import DiscoveryDocument, OpenID, SSOBase, _decode_id_token if TYPE_CHECKING: import httpx # pragma: no cover @@ -45,7 +45,13 @@ async def get_discovery_document(self) -> DiscoveryDocument: "userinfo_endpoint": f"https://graph.microsoft.com/{self.version}/me", } + async def get_user_roles(self) -> list[str]: + """Get user roles from Microsoft ID token.""" + token_info = _decode_id_token(self._id_token) + return token_info.get("roles") + async def openid_from_response(self, response: dict, session: Optional["httpx.AsyncClient"] = None) -> OpenID: + token_info = _decode_id_token(self._id_token) return OpenID( email=response.get("mail"), display_name=response.get("displayName"), @@ -53,4 +59,5 @@ async def openid_from_response(self, response: dict, session: Optional["httpx.As id=response.get("id"), first_name=response.get("givenName"), last_name=response.get("surname"), + roles=token_info.get("roles"), )