@@ -45,13 +45,15 @@ def test_security_key():
4545 ).decode ("ascii" ),
4646 }
4747 ],
48+ "relyingPartyId" : "security_key_application_id" ,
4849 },
4950 }
5051 mock_key = mock .Mock ()
5152
5253 challenge = challenges .SecurityKeyChallenge ()
5354
54- # Test the case that security key challenge is passed.
55+ # Test the case that security key challenge is passed with applicationId and
56+ # relyingPartyId the same.
5557 with mock .patch ("pyu2f.model.RegisteredKey" , return_value = mock_key ):
5658 with mock .patch (
5759 "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate"
@@ -68,6 +70,56 @@ def test_security_key():
6870 print_callback = sys .stderr .write ,
6971 )
7072
73+ # Test the case that security key challenge is passed with applicationId and
74+ # relyingPartyId different, first call works.
75+ metadata ["securityKey" ]["relyingPartyId" ] = "security_key_relying_party_id"
76+ sys .stderr .write ("metadata=" + str (metadata ) + "\n " )
77+ with mock .patch ("pyu2f.model.RegisteredKey" , return_value = mock_key ):
78+ with mock .patch (
79+ "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate"
80+ ) as mock_authenticate :
81+ mock_authenticate .return_value = "security key response"
82+ assert challenge .name == "SECURITY_KEY"
83+ assert challenge .is_locally_eligible
84+ assert challenge .obtain_challenge_input (metadata ) == {
85+ "securityKey" : "security key response"
86+ }
87+ mock_authenticate .assert_called_with (
88+ "security_key_relying_party_id" ,
89+ [{"key" : mock_key , "challenge" : b"some_challenge" }],
90+ print_callback = sys .stderr .write ,
91+ )
92+
93+ # Test the case that security key challenge is passed with applicationId and
94+ # relyingPartyId different, first call fails, requires retry.
95+ metadata ["securityKey" ]["relyingPartyId" ] = "security_key_relying_party_id"
96+ with mock .patch ("pyu2f.model.RegisteredKey" , return_value = mock_key ):
97+ with mock .patch (
98+ "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate"
99+ ) as mock_authenticate :
100+ assert challenge .name == "SECURITY_KEY"
101+ assert challenge .is_locally_eligible
102+ mock_authenticate .side_effect = [
103+ pyu2f .errors .U2FError (pyu2f .errors .U2FError .DEVICE_INELIGIBLE ),
104+ "security key response" ,
105+ ]
106+ assert challenge .obtain_challenge_input (metadata ) == {
107+ "securityKey" : "security key response"
108+ }
109+ calls = [
110+ mock .call (
111+ "security_key_relying_party_id" ,
112+ [{"key" : mock_key , "challenge" : b"some_challenge" }],
113+ print_callback = sys .stderr .write ,
114+ ),
115+ mock .call (
116+ "security_key_application_id" ,
117+ [{"key" : mock_key , "challenge" : b"some_challenge" }],
118+ print_callback = sys .stderr .write ,
119+ ),
120+ ]
121+ mock_authenticate .assert_has_calls (calls )
122+
71123 # Test various types of exceptions.
72124 with mock .patch ("pyu2f.model.RegisteredKey" , return_value = mock_key ):
73125 with mock .patch (
@@ -86,6 +138,12 @@ def test_security_key():
86138 )
87139 assert challenge .obtain_challenge_input (metadata ) is None
88140
141+ with mock .patch (
142+ "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate"
143+ ) as mock_authenticate :
144+ mock_authenticate .side_effect = pyu2f .errors .PluginError ()
145+ assert challenge .obtain_challenge_input (metadata ) is None
146+
89147 with mock .patch (
90148 "pyu2f.convenience.authenticator.CompositeAuthenticator.Authenticate"
91149 ) as mock_authenticate :
0 commit comments