Skip to content

Commit 4e01ba0

Browse files
authored
Closes #638. Make sure residentKey services roundtrip (#640)
* Closes #638. Make sure residentKey services roundtrip * Add test
1 parent 2a19063 commit 4e01ba0

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

Src/Fido2.Models/CredentialCreateOptions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,14 @@ public bool RequireResidentKey
283283
set
284284
{
285285
_requireResidentKey = value;
286-
_residentKey = value ? ResidentKeyRequirement.Required : ResidentKeyRequirement.Discouraged;
286+
if (value)
287+
{
288+
_residentKey = ResidentKeyRequirement.Required;
289+
}
290+
else if (_residentKey is not ResidentKeyRequirement.Preferred)
291+
{
292+
_residentKey = ResidentKeyRequirement.Discouraged;
293+
}
287294
}
288295
}
289296

Tests/Fido2.Tests/Fido2Tests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,66 @@ public void TestStringIsSerializable()
417417
Assert.Equal(z1, z2);
418418
}
419419

420+
[Fact]
421+
public void AuthenticatorSelection_ResidentKeyPreferred_SurvivesJsonRoundTrip()
422+
{
423+
// Arrange: Create AuthenticatorSelection with ResidentKey = Preferred
424+
var original = new AuthenticatorSelection
425+
{
426+
ResidentKey = ResidentKeyRequirement.Preferred,
427+
UserVerification = UserVerificationRequirement.Preferred
428+
};
429+
430+
// Act: Serialize to JSON and deserialize back
431+
var json = JsonSerializer.Serialize(original);
432+
var deserialized = JsonSerializer.Deserialize<AuthenticatorSelection>(json);
433+
434+
// Assert: ResidentKey should still be Preferred after round-trip
435+
Assert.Equal(ResidentKeyRequirement.Preferred, deserialized.ResidentKey);
436+
}
437+
438+
[Fact]
439+
public void AuthenticatorSelection_RequireResidentKeyTrue_SetsResidentKeyToRequired()
440+
{
441+
// Arrange & Act: Create AuthenticatorSelection with RequireResidentKey = true
442+
#pragma warning disable CS0618 // RequireResidentKey is obsolete
443+
var selection = new AuthenticatorSelection
444+
{
445+
RequireResidentKey = true
446+
};
447+
448+
// Assert: ResidentKey should be Required when RequireResidentKey is true
449+
Assert.Equal(ResidentKeyRequirement.Required, selection.ResidentKey);
450+
Assert.True(selection.RequireResidentKey);
451+
#pragma warning restore CS0618
452+
}
453+
454+
[Fact]
455+
public void CredentialCreateOptions_ResidentKeyPreferred_SurvivesJsonRoundTrip()
456+
{
457+
// Arrange: This JSON has residentKey: "preferred" which should be preserved
458+
const string json = """
459+
{
460+
"rp": { "id": "some.rp.id", "name": "Some name" },
461+
"user": { "name": "someuserid", "id": "NjVmZGNiOTJiZjQyZjZmZDE0YzViODVk", "displayName": "The User 1234" },
462+
"challenge": "kauVQPwQtf4BlhOFObDfTQ",
463+
"pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ],
464+
"timeout": 60000,
465+
"attestation": "none",
466+
"attestationFormats": [],
467+
"authenticatorSelection": { "residentKey": "preferred", "requireResidentKey": false, "userVerification": "preferred" },
468+
"hints": [],
469+
"excludeCredentials": []
470+
}
471+
""";
472+
473+
// Act: Deserialize the JSON
474+
var options = CredentialCreateOptions.FromJson(json);
475+
476+
// Assert: ResidentKey should be Preferred, not Discouraged
477+
Assert.Equal(ResidentKeyRequirement.Preferred, options.AuthenticatorSelection.ResidentKey);
478+
}
479+
420480
[Fact]
421481
public async Task TestFido2AssertionAsync()
422482
{

0 commit comments

Comments
 (0)