Skip to content

Commit

Permalink
Merge pull request #103 from maykinmedia/feature/99-check-idp-availab…
Browse files Browse the repository at this point in the history
…ility

Check idp availability
  • Loading branch information
stevenbal authored May 23, 2024
2 parents e48d55a + ddddcc2 commit d4471a8
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
30 changes: 27 additions & 3 deletions mozilla_django_oidc_db/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
from django.utils.http import url_has_allowed_host_and_scheme
from django.views.generic import TemplateView

import requests
from mozilla_django_oidc.views import (
OIDCAuthenticationCallbackView,
OIDCAuthenticationRequestView as _OIDCAuthenticationRequestView,
)

from .config import get_setting_from_config, store_config
from .exceptions import OIDCProviderOutage
from .models import OpenIDConnectConfig, OpenIDConnectConfigBase

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -181,7 +183,8 @@ def get(
if not self.allow_next_from_query:
self._validate_return_url(request, return_url=return_url)

self.check_idp_availability()
if self.get_settings("OIDCDB_CHECK_IDP_AVAILABILITY", False):
self.check_idp_availability()

response = super().get(request, *args, **kwargs)

Expand Down Expand Up @@ -241,9 +244,30 @@ def check_idp_availability(self) -> None:
"""
Hook for subclasses.
Raise :class:`OIDCProviderOutage` if the Identity Provider is not available.
Raise :class:`OIDCProviderOutage` if the Identity Provider is not available,
which your application code needs to handle.
The default implementation checks if the endpoint has a status code < 401.
"""
pass
endpoint = self.OIDC_OP_AUTH_ENDPOINT
try:
# Verify that the identity provider endpoint can be reached. This is where
# the user ultimately gets redirected to.
#
# 5 seconds wait time is probably already too long for a good user
# experience, but we don't want to be *too* aggressive.
response = requests.get(endpoint, timeout=5.0)
# some IDPs have been observed to return HTTP 400 because of the missing
# query params
if response.status_code > 400:
response.raise_for_status()
except requests.RequestException as exc:
logger.info(
"OIDC provider endpoint '%s' could not be retrieved",
endpoint,
exc_info=exc,
)
raise OIDCProviderOutage("Identity provider appears to be down.") from exc

def get_extra_params(self, request: HttpRequest) -> dict[str, str]:
"""
Expand Down
25 changes: 25 additions & 0 deletions tests/test_init_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import pytest

from mozilla_django_oidc_db.exceptions import OIDCProviderOutage


@pytest.mark.oidcconfig(
oidc_op_authorization_endpoint="http://localhost:8080/openid-connect/auth"
Expand Down Expand Up @@ -46,3 +48,26 @@ def test_keycloak_idp_hint_via_settings(dummy_config, settings, client):

query = parse_qs(parsed_url.query)
assert query["kc_idp_hint"] == ["keycloak-idp1"]


def test_check_idp_availability_not_available(
dummy_config, settings, client, requests_mock
):
settings.OIDCDB_CHECK_IDP_AVAILABILITY = True
requests_mock.get("https://mock-oidc-provider:9999/oidc/auth", status_code=503)
start_url = reverse("oidc_authentication_init")

with pytest.raises(OIDCProviderOutage):
client.get(start_url)


def test_check_idp_availability_available(
dummy_config, settings, client, requests_mock
):
settings.OIDCDB_CHECK_IDP_AVAILABILITY = True
requests_mock.get("https://mock-oidc-provider:9999/oidc/auth", status_code=400)
start_url = reverse("oidc_authentication_init")

response = client.get(start_url)

assert response.status_code == 302
4 changes: 3 additions & 1 deletion tests/test_init_flow_custom_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def check_idp_availability(self) -> None:
)


def test_idp_check_mechanism(auth_request):
def test_idp_check_mechanism(auth_request, settings):
settings.OIDCDB_CHECK_IDP_AVAILABILITY = True

with pytest.raises(OIDCProviderOutage):
oidc_init_with_idp_check(auth_request)

0 comments on commit d4471a8

Please sign in to comment.