From ec37d94ff54b6f706d123196610ff8c2ea59f682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=85berg?= Date: Mon, 8 Dec 2025 19:43:37 +0100 Subject: [PATCH 1/2] Closes #638. Make sure residentKey services roundtrip --- Src/Fido2.Models/CredentialCreateOptions.cs | 9 ++++- Tests/Fido2.Tests/Fido2Tests.cs | 44 +++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Src/Fido2.Models/CredentialCreateOptions.cs b/Src/Fido2.Models/CredentialCreateOptions.cs index 94e41c54..0295f202 100644 --- a/Src/Fido2.Models/CredentialCreateOptions.cs +++ b/Src/Fido2.Models/CredentialCreateOptions.cs @@ -283,7 +283,14 @@ public bool RequireResidentKey set { _requireResidentKey = value; - _residentKey = value ? ResidentKeyRequirement.Required : ResidentKeyRequirement.Discouraged; + if (value) + { + _residentKey = ResidentKeyRequirement.Required; + } + else if (_residentKey is not ResidentKeyRequirement.Preferred) + { + _residentKey = ResidentKeyRequirement.Discouraged; + } } } diff --git a/Tests/Fido2.Tests/Fido2Tests.cs b/Tests/Fido2.Tests/Fido2Tests.cs index e9b9b250..bac6cf94 100644 --- a/Tests/Fido2.Tests/Fido2Tests.cs +++ b/Tests/Fido2.Tests/Fido2Tests.cs @@ -417,6 +417,50 @@ public void TestStringIsSerializable() Assert.Equal(z1, z2); } + [Fact] + public void AuthenticatorSelection_ResidentKeyPreferred_SurvivesJsonRoundTrip() + { + // Arrange: Create AuthenticatorSelection with ResidentKey = Preferred + var original = new AuthenticatorSelection + { + ResidentKey = ResidentKeyRequirement.Preferred, + UserVerification = UserVerificationRequirement.Preferred + }; + + // Act: Serialize to JSON and deserialize back + var json = JsonSerializer.Serialize(original); + var deserialized = JsonSerializer.Deserialize(json); + + // Assert: ResidentKey should still be Preferred after round-trip + Assert.Equal(ResidentKeyRequirement.Preferred, deserialized.ResidentKey); + } + + [Fact] + public void CredentialCreateOptions_ResidentKeyPreferred_SurvivesJsonRoundTrip() + { + // Arrange: This JSON has residentKey: "preferred" which should be preserved + const string json = """ + { + "rp": { "id": "some.rp.id", "name": "Some name" }, + "user": { "name": "someuserid", "id": "NjVmZGNiOTJiZjQyZjZmZDE0YzViODVk", "displayName": "The User 1234" }, + "challenge": "kauVQPwQtf4BlhOFObDfTQ", + "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], + "timeout": 60000, + "attestation": "none", + "attestationFormats": [], + "authenticatorSelection": { "residentKey": "preferred", "requireResidentKey": false, "userVerification": "preferred" }, + "hints": [], + "excludeCredentials": [] + } + """; + + // Act: Deserialize the JSON + var options = CredentialCreateOptions.FromJson(json); + + // Assert: ResidentKey should be Preferred, not Discouraged + Assert.Equal(ResidentKeyRequirement.Preferred, options.AuthenticatorSelection.ResidentKey); + } + [Fact] public async Task TestFido2AssertionAsync() { From 3f158c772b1563ed56b6c6f39d4060fb2e275360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=85berg?= Date: Tue, 9 Dec 2025 14:05:53 +0100 Subject: [PATCH 2/2] Add test --- Tests/Fido2.Tests/Fido2Tests.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Tests/Fido2.Tests/Fido2Tests.cs b/Tests/Fido2.Tests/Fido2Tests.cs index bac6cf94..ea9c35e3 100644 --- a/Tests/Fido2.Tests/Fido2Tests.cs +++ b/Tests/Fido2.Tests/Fido2Tests.cs @@ -435,6 +435,22 @@ public void AuthenticatorSelection_ResidentKeyPreferred_SurvivesJsonRoundTrip() Assert.Equal(ResidentKeyRequirement.Preferred, deserialized.ResidentKey); } + [Fact] + public void AuthenticatorSelection_RequireResidentKeyTrue_SetsResidentKeyToRequired() + { + // Arrange & Act: Create AuthenticatorSelection with RequireResidentKey = true +#pragma warning disable CS0618 // RequireResidentKey is obsolete + var selection = new AuthenticatorSelection + { + RequireResidentKey = true + }; + + // Assert: ResidentKey should be Required when RequireResidentKey is true + Assert.Equal(ResidentKeyRequirement.Required, selection.ResidentKey); + Assert.True(selection.RequireResidentKey); +#pragma warning restore CS0618 + } + [Fact] public void CredentialCreateOptions_ResidentKeyPreferred_SurvivesJsonRoundTrip() {