Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
6 changes: 6 additions & 0 deletions mozilla_django_oidc/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ def get_userinfo(self, access_token, id_token, payload):
proxies=self.get_settings("OIDC_PROXY", None),
)
user_response.raise_for_status()

if user_response.headers.get("content-type", "").startswith("application/jwt"):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIME types are case-insensitive you may want to be also?

MIME types are case-insensitive but are traditionally written in lowercase. The parameter values can be case-sensitive.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types

Suggested change
if user_response.headers.get("content-type", "").startswith("application/jwt"):
if user_response.headers.get("content-type", "").lower().startswith("application/jwt"):

# OIDC userinfo claims can be encoded as JWT
return self.verify_token(user_response.text)

# otherwise process as JSON payload
return user_response.json()

def authenticate(self, request, **kwargs):
Expand Down
25 changes: 25 additions & 0 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,31 @@ def update_user(user, claims):

self.assertEqual(User.objects.get().first_name, "a_username")

@patch("mozilla_django_oidc.auth.requests")
@patch("mozilla_django_oidc.auth.OIDCAuthenticationBackend.verify_token")
def test_get_userinfo_with_jwt_response(self, verify_token_mock, request_mock):
"""Test get_userinfo with a JWT response."""
auth_request = RequestFactory().get("/foo", {"code": "foo", "state": "bar"})
auth_request.session = {}

# Mock the response from the userinfo endpoint
jwt_response = Mock()
jwt_response.headers = {"content-type": "application/jwt"}
jwt_response.text = "mocked_jwt_token"
request_mock.get.return_value = jwt_response

# Mock the verify_token method to return a specific payload
verify_token_mock.return_value = {"email": "email@example.com", "name": "John Doe"}

# Call the get_userinfo method
user_info = self.backend.get_userinfo("access_token", "id_token", {})

# Assert that verify_token was called with the correct token
verify_token_mock.assert_called_once_with("mocked_jwt_token")

# Assert that the returned user info matches the expected payload
self.assertEqual(user_info, {"email": "email@example.com", "name": "John Doe"})


class OIDCAuthenticationBackendRS256WithKeyTestCase(TestCase):
"""Authentication tests with ALG RS256 and provided IdP Sign Key."""
Expand Down