Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Src/Fido2.Models/CredentialCreateOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand Down
60 changes: 60 additions & 0 deletions Tests/Fido2.Tests/Fido2Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,66 @@ 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<AuthenticatorSelection>(json);

// Assert: ResidentKey should still be Preferred after round-trip
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()
{
// 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()
{
Expand Down