From 89a717d26756b17ee1f7d439ee51699af0dc6816 Mon Sep 17 00:00:00 2001 From: cpisunyer Date: Thu, 6 Jun 2024 12:08:38 -0700 Subject: [PATCH] feat: Enable webauthn plugin for security keys Fix broken test and add test clauses to bring coverage to 100%. --- google/oauth2/challenges.py | 4 +-- tests/oauth2/test_challenges.py | 44 ++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/google/oauth2/challenges.py b/google/oauth2/challenges.py index 8d4355168..6468498bc 100644 --- a/google/oauth2/challenges.py +++ b/google/oauth2/challenges.py @@ -193,11 +193,11 @@ def obtain_challenge_input(self, metadata): def _obtain_challenge_input_webauthn(self, metadata, webauthn_handler): sk = metadata.get("securityKey") + if sk is None: + raise exceptions.InvalidValue("securityKey is None") challenges = sk.get("challenges") application_id = sk.get("applicationId") relying_party_id = sk.get("relyingPartyId") - if sk is None: - raise exceptions.InvalidValue("securityKey is None") if challenges is None or len(challenges) < 1: raise exceptions.InvalidValue("challenges is None or empty") if application_id is None: diff --git a/tests/oauth2/test_challenges.py b/tests/oauth2/test_challenges.py index 6406d3eb4..4116b913a 100644 --- a/tests/oauth2/test_challenges.py +++ b/tests/oauth2/test_challenges.py @@ -233,7 +233,7 @@ def test_security_key_webauthn(): get_request = GetRequest( origin=challenges.REAUTH_ORIGIN, rpid=application_id, - challenge=challenge._urlsafe_b64recode(sk_challenge["challenge"]), + challenge=challenge._unpadded_urlsafe_b64recode(sk_challenge["challenge"]), timeout_ms=challenges.WEBAUTHN_TIMEOUT_MS, allow_credentials=allow_credentials, user_verification="required", @@ -271,6 +271,48 @@ def test_security_key_webauthn(): mock_handler.get.assert_called_with(get_request) # Test exceptions + + # Missing Values + sk = metadata["securityKey"] + metadata["securityKey"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"] = sk + + c = metadata["securityKey"]["challenges"] + metadata["securityKey"]["challenges"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["challenges"] = [] + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["challenges"] = c + + aid = metadata["securityKey"]["applicationId"] + metadata["securityKey"]["applicationId"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["applicationId"] = aid + + rpi = metadata["securityKey"]["relyingPartyId"] + metadata["securityKey"]["relyingPartyId"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["relyingPartyId"] = rpi + + kh = metadata["securityKey"]["challenges"][0]["keyHandle"] + metadata["securityKey"]["challenges"][0]["keyHandle"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["challenges"][0]["keyHandle"] = kh + + ch = metadata["securityKey"]["challenges"][0]["challenge"] + metadata["securityKey"]["challenges"][0]["challenge"] = None + with pytest.raises(exceptions.InvalidValue): + challenge._obtain_challenge_input_webauthn(metadata, mock_handler) + metadata["securityKey"]["challenges"][0]["challenge"] = ch + + # Handler Exceptions mock_handler.get.side_effect = exceptions.MalformedError with pytest.raises(exceptions.MalformedError): challenge._obtain_challenge_input_webauthn(metadata, mock_handler)