diff --git a/docs/sections/settings.rst b/docs/sections/settings.rst index 984d2df2..057c38e5 100644 --- a/docs/sections/settings.rst +++ b/docs/sections/settings.rst @@ -244,4 +244,13 @@ A flag which toggles whether the scope is returned with successful response on i Must be ``True`` to include ``scope`` into the successful response -Default is ``False``. \ No newline at end of file +Default is ``False``. + +OIDC_CLAIMS_SUPPORTED +===================== + +RECOMMENDED. ``list``. List containing a list of the Claim Names of the Claims that the OpenID Provider MAY be able to supply values for. Note that for privacy or other reasons, this might not be an exhaustive list. + +https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata + +Default is an empty list as this application will not make assumptions about what the provider will support. diff --git a/oidc_provider/settings.py b/oidc_provider/settings.py index 90750fda..d88e76bd 100644 --- a/oidc_provider/settings.py +++ b/oidc_provider/settings.py @@ -161,6 +161,16 @@ def OIDC_GRANT_TYPE_PASSWORD_ENABLE(self): """ return False + @property + def OIDC_CLAIMS_SUPPORTED(self): + """ + RECOMMENDED. A list of Claims names that you may support. Does not need + to be exhaustive for security reasons. + + https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata + """ + return [] + @property def OIDC_TEMPLATES(self): return { diff --git a/oidc_provider/tests/cases/test_provider_info_endpoint.py b/oidc_provider/tests/cases/test_provider_info_endpoint.py index 2265ef66..79a6b9a7 100644 --- a/oidc_provider/tests/cases/test_provider_info_endpoint.py +++ b/oidc_provider/tests/cases/test_provider_info_endpoint.py @@ -1,15 +1,21 @@ +import json + try: from django.urls import reverse except ImportError: from django.core.urlresolvers import reverse -from django.test import RequestFactory -from django.test import TestCase +from django.test import RequestFactory, TestCase, override_settings from oidc_provider.views import ProviderInfoView class ProviderInfoTestCase(TestCase): + @classmethod + def setUpClass(cls): + super(ProviderInfoTestCase, cls).setUpClass() + cls.url = reverse('oidc_provider:provider-info') + def setUp(self): self.factory = RequestFactory() @@ -18,12 +24,61 @@ def test_response(self): See if the endpoint is returning the corresponding server information by checking status, content type, etc. """ - url = reverse('oidc_provider:provider-info') - request = self.factory.get(url) + request = self.factory.get(self.url) response = ProviderInfoView.as_view()(request) self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-Type'] == 'application/json', True) self.assertEqual(bool(response.content), True) + + def test_expected_keys_in_response(self): + """ + Test that response contains all ncecessary keys + """ + required_keys = { + 'issuer', + 'authorization_endpoint', + 'token_endpoint', + 'userinfo_endpoint', + 'end_session_endpoint', + 'introspection_endpoint', + 'response_types_supported', + 'jwks_uri', + 'id_token_signing_alg_values_supported', + 'subject_types_supported', + 'token_endpoint_auth_methods_supported', + 'claims_supported', + } + + request = self.factory.get(self.url) + + response = ProviderInfoView.as_view()(request) + resp_keys = set(json.loads(response.content.decode('utf-8')).keys()) + self.assertEqual(required_keys, resp_keys) + + def test_claims_supported_not_set(self): + """ + If OIDC_CLAIMS_SUPPORTED is not set in settings.py, the claims_supported + entry is an empty list + """ + request = self.factory.get(self.url) + + response = ProviderInfoView.as_view()(request) + dic = json.loads(response.content.decode('utf-8')) + self.assertEqual(dic['claims_supported'], []) + + @override_settings(OIDC_CLAIMS_SUPPORTED=['openid', 'email']) + def test_claims_supported_set(self): + """ + If OIDC_CLAIMS_SUPPORTED is not set in settings.py, the claims_supported + entry is an empty list + """ + expected_claims = ['openid', 'email'] + + request = self.factory.get(self.url) + + response = ProviderInfoView.as_view()(request) + dic = json.loads(response.content.decode('utf-8')) + self.assertEqual(dic['claims_supported'], expected_claims) diff --git a/oidc_provider/views.py b/oidc_provider/views.py index 06501d5d..7f574e4d 100644 --- a/oidc_provider/views.py +++ b/oidc_provider/views.py @@ -285,6 +285,8 @@ def get(self, request, *args, **kwargs): dic['token_endpoint_auth_methods_supported'] = ['client_secret_post', 'client_secret_basic'] + dic['claims_supported'] = settings.get('OIDC_CLAIMS_SUPPORTED', []) + if settings.get('OIDC_SESSION_MANAGEMENT_ENABLE'): dic['check_session_iframe'] = site_url + reverse('oidc_provider:check-session-iframe')