Skip to content

Commit

Permalink
Allow claims-like attribute keys (#253)
Browse files Browse the repository at this point in the history
* added feature and tests
* added author
* cleanup
* cleanup and add .idea (intellij) to .gitignore
* remove nested .idea/
* cleanup debugging
* Remove unused file
* Reformat with ruff
  • Loading branch information
wrabit authored Aug 8, 2024
1 parent b272b06 commit dc1598c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ target/

# IDEs
.vscode/
.idea/
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ an issue.
- [Santiago Gandolfo](https://github.com/santigandolfo)
- [Greg Wong](https://github.com/gregorywong)
- [Michael V. Battista](https://github.com/mvbattista)
- [William Abbott](https://github.com/wrabit)
10 changes: 5 additions & 5 deletions django_saml2_auth/saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,15 @@ def extract_user_identity(user_identity: Dict[str, Any]) -> Dict[str, Optional[A
)

user = {}
user["email"] = dictor(user_identity, f"{email_field}/0", pathsep="/") # Path includes "."
user["username"] = dictor(user_identity, f"{username_field}/0", pathsep="/")
user["first_name"] = dictor(user_identity, f"{firstname_field}/0", pathsep="/")
user["last_name"] = dictor(user_identity, f"{lastname_field}/0", pathsep="/")
user["email"] = dictor(user_identity, f"{email_field}|0", pathsep="|") # Path includes "."
user["username"] = dictor(user_identity, f"{username_field}|0", pathsep="|")
user["first_name"] = dictor(user_identity, f"{firstname_field}|0", pathsep="|")
user["last_name"] = dictor(user_identity, f"{lastname_field}|0", pathsep="|")

token_required = dictor(saml2_auth_settings, "TOKEN_REQUIRED", default=True)
if token_required:
token_field = dictor(saml2_auth_settings, "ATTRIBUTES_MAP.token", default="token")
user["token"] = dictor(user_identity, f"{token_field}.0")
user["token"] = dictor(user_identity, f"{token_field}|0", pathsep="|")

if user["email"]:
user["email"] = user["email"].lower()
Expand Down
38 changes: 38 additions & 0 deletions django_saml2_auth/tests/test_saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ def get_user_identity() -> Mapping[str, List[str]]:
}


def get_user_identify_with_slashed_keys() -> Mapping[str, List[str]]:
"""Fixture for returning user identity produced by pysaml2 with slashed, claim-like keys.
Returns:
dict: keys are SAML attributes and values are lists of attribute values
"""
return {
"http://schemas.org/user/username": ["[email protected]"],
"http://schemas.org/user/claim2.0/email": ["[email protected]"],
"http://schemas.org/user/claim2.0/first_name": ["John"],
"http://schemas.org/user/claim2.0/last_name": ["Doe"],
"http://schemas.org/auth/server/token": ["TOKEN"],
}


def mock_parse_authn_request_response(
self: Saml2Client, response: AuthnResponse, binding: str
) -> "MockAuthnResponse": # type: ignore # noqa: F821
Expand Down Expand Up @@ -447,6 +462,29 @@ def test_extract_user_identity_success():
assert result["user_identity"] == get_user_identity()


def test_extract_user_identity_with_slashed_attribute_keys_success(settings: SettingsWrapper):
"""Test extract_user_identity function to verify if it correctly extracts user identity
information from a (pysaml2) parsed SAML response with slashed attribute keys."""
settings.SAML2_AUTH = {
"ATTRIBUTES_MAP": {
"email": "http://schemas.org/user/claim2.0/email",
"username": "http://schemas.org/user/username",
"first_name": "http://schemas.org/user/claim2.0/first_name",
"last_name": "http://schemas.org/user/claim2.0/last_name",
"token": "http://schemas.org/auth/server/token",
}
}

result = extract_user_identity(get_user_identify_with_slashed_keys()) # type: ignore

assert len(result) == 6
assert result["username"] == result["email"] == "[email protected]"
assert result["first_name"] == "John"
assert result["last_name"] == "Doe"
assert result["token"] == "TOKEN"
assert result["user_identity"] == get_user_identify_with_slashed_keys()


def test_extract_user_identity_token_not_required(settings: SettingsWrapper):
"""Test extract_user_identity function to verify if it correctly extracts user identity
information from a (pysaml2) parsed SAML response when token is not required."""
Expand Down

0 comments on commit dc1598c

Please sign in to comment.