Skip to content

Commit

Permalink
Update branch from master
Browse files Browse the repository at this point in the history
  • Loading branch information
aseigler committed Oct 15, 2022
2 parents e1e5373 + dd727b1 commit 45af0e4
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 46 deletions.
4 changes: 2 additions & 2 deletions Demo/Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public JsonResult MakeCredentialOptions([FromForm] string username,
[FromForm] string displayName,
[FromForm] string attType,
[FromForm] string authType,
[FromForm] bool requireResidentKey,
[FromForm] string residentKey,
[FromForm] string userVerification)
{
try
Expand All @@ -63,7 +63,7 @@ public JsonResult MakeCredentialOptions([FromForm] string username,
// 3. Create options
var authenticatorSelection = new AuthenticatorSelection
{
RequireResidentKey = requireResidentKey,
ResidentKey = residentKey.ToEnum<ResidentKeyRequirement>(),
UserVerification = userVerification.ToEnum<UserVerificationRequirement>()
};

Expand Down
23 changes: 6 additions & 17 deletions Demo/Pages/_options.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,18 @@

</div>
<div class="field">
<label class="label">Require Resident Key</label>
<label class="label">Resident Key</label>
<div class="control">
<label class="select">
<select id="option-requireresidentkey">
<option value="undefined" selected>Undefined</option>
<option value="false">False</option>
<option value="true">True</option>
</select>
</label>
</div>
</div>
<div class="field">
<label class="label">Resident Key (L2)</label>
<div class="control">
<label class="select">
<div class="select">
<select id="option-residentkey">
<option value="undefined" selected>Undefined</option>
<option value="discouraged">Discouraged</option>
<option value="preferred">Preferred</option>
<option value="required">Required</option>
<option value="preferred">Preferred</option>
<option value="discouraged">Discouraged</option>
</select>
</label>
</div>
</div>
<p class="help">For register the client will guide the user through setting up user verification if needed to create a discoverable credential. This takes precedence over the setting of userVerification.</p>
</div>
<div class="field">
<label class="label">RP Info</label>
Expand Down
7 changes: 5 additions & 2 deletions Demo/wwwroot/js/custom.register.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ async function handleRegisterSubmit(event) {
user_verification = value("#option-userverification");
}

let require_resident_key = value("#option-residentkey");
let residentKey = "";
if (value("#option-residentkey") !== "undefined") {
residentKey = value("#option-residentkey");
}

// prepare form post data
var data = new FormData();
Expand All @@ -33,7 +36,7 @@ async function handleRegisterSubmit(event) {
data.append('attType', attestation_type);
data.append('authType', authenticator_attachment);
data.append('userVerification', user_verification);
data.append('requireResidentKey', require_resident_key);
data.append('residentKey', residentKey);

try {
makeCredentialOptions = await fetchMakeCredentialOptions(data);
Expand Down
6 changes: 3 additions & 3 deletions Demo/wwwroot/js/mfa.register.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ async function handleRegisterSubmit(event) {
// possible values: preferred, required, discouraged
let user_verification = "discouraged";

// possible values: true,false
let require_resident_key = false;
// possible values: discouraged, preferred, required
let residentKey = "discouraged";



Expand All @@ -29,7 +29,7 @@ async function handleRegisterSubmit(event) {
data.append('attType', attestation_type);
data.append('authType', authenticator_attachment);
data.append('userVerification', user_verification);
data.append('requireResidentKey', require_resident_key);
data.append('residentKey', residentKey);

// send to server for registering
let makeCredentialOptions;
Expand Down
6 changes: 3 additions & 3 deletions Demo/wwwroot/js/passwordless.register.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ async function handleRegisterSubmit(event) {
// possible values: preferred, required, discouraged
let user_verification = "discouraged";

// possible values: true,false
let require_resident_key = "false";
// possible values: discouraged, preferred, required
let residentKey = "discouraged";

// prepare form post data
var data = new FormData();
Expand All @@ -25,7 +25,7 @@ async function handleRegisterSubmit(event) {
data.append('attType', attestation_type);
data.append('authType', authenticator_attachment);
data.append('userVerification', user_verification);
data.append('requireResidentKey', require_resident_key);
data.append('residentKey', residentKey);

// send to server for registering
let makeCredentialOptions;
Expand Down
6 changes: 3 additions & 3 deletions Demo/wwwroot/js/usernameless.register.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ async function handleRegisterSubmit(event) {
// possible values: preferred, required, discouraged
let user_verification = "discouraged";

// possible values: true,false
// possible values: discouraged, preferred, required
// NOTE: For usernameless scenarios, resident key must be set to true.
let require_resident_key = "true";
let residentKey = "required";

// prepare form post data
var data = new FormData();
Expand All @@ -25,7 +25,7 @@ async function handleRegisterSubmit(event) {
data.append('attType', attestation_type);
data.append('authType', authenticator_attachment);
data.append('userVerification', user_verification);
data.append('requireResidentKey', require_resident_key);
data.append('residentKey', residentKey);

// send to server for registering
let makeCredentialOptions;
Expand Down
38 changes: 35 additions & 3 deletions Src/Fido2.Models/CredentialCreateOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand Down Expand Up @@ -182,6 +183,7 @@ public PublicKeyCredentialRpEntity(string id, string name, string? icon = null)

/// <summary>
/// WebAuthn Relying Parties may use the AuthenticatorSelectionCriteria dictionary to specify their requirements regarding authenticator attributes.
/// https://w3c.github.io/webauthn/#dictionary-authenticatorSelection
/// </summary>
public class AuthenticatorSelection
{
Expand All @@ -192,11 +194,41 @@ public class AuthenticatorSelection
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AuthenticatorAttachment? AuthenticatorAttachment { get; set; }

private ResidentKeyRequirement _residentKey;
/// <summary>
/// Specifies the extent to which the Relying Party desires to create a client-side discoverable credential. For historical reasons the naming retains the deprecated “resident” terminology. The value SHOULD be a member of ResidentKeyRequirement but client platforms MUST ignore unknown values, treating an unknown value as if the member does not exist. If no value is given then the effective value is required if requireResidentKey is true or discouraged if it is false or absent.
/// </summary>
[JsonPropertyName("residentKey")]
public ResidentKeyRequirement ResidentKey
{
get => _residentKey;
set
{
_residentKey = value;
_requireResidentKey = value switch
{
ResidentKeyRequirement.Required => true,
ResidentKeyRequirement.Preferred or ResidentKeyRequirement.Discouraged => false,
_ => throw new NotImplementedException(),
};
}
}

private bool _requireResidentKey;
/// <summary>
/// This member describes the Relying Parties' requirements regarding resident credentials. If the parameter is set to true, the authenticator MUST create a client-side-resident public key credential source when creating a public key credential.
/// </summary>
[Obsolete("Use property ResidentKey.")]
[JsonPropertyName("requireResidentKey")]
public bool RequireResidentKey { get; set; }
public bool RequireResidentKey
{
get => _requireResidentKey;
set
{
_requireResidentKey = value;
_residentKey = value ? ResidentKeyRequirement.Required : ResidentKeyRequirement.Discouraged;
}
}

/// <summary>
/// This member describes the Relying Party's requirements regarding user verification for the create() operation. Eligible authenticators are filtered to only those capable of satisfying this requirement.
Expand All @@ -207,7 +239,7 @@ public class AuthenticatorSelection
public static AuthenticatorSelection Default => new AuthenticatorSelection
{
AuthenticatorAttachment = null,
RequireResidentKey = false,
ResidentKey = ResidentKeyRequirement.Discouraged,
UserVerification = UserVerificationRequirement.Preferred
};
}
Expand Down
31 changes: 31 additions & 0 deletions Src/Fido2.Models/Objects/ResidentKeyRequirement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace Fido2NetLib.Objects
{
/// <summary>
/// This enumeration’s values describe the Relying Party's requirements for client-side discoverable credentials (formerly known as resident credentials or resident keys).
/// https://w3c.github.io/webauthn/#enum-residentKeyRequirement
/// </summary>
[JsonConverter(typeof(FidoEnumConverter<ResidentKeyRequirement>))]
public enum ResidentKeyRequirement
{
/// <summary>
/// The Relying Party requires a client-side discoverable credential. The client MUST return an error if a client-side discoverable credential cannot be created.
/// </summary>
[EnumMember(Value = "required")]
Required,

/// <summary>
/// The Relying Party strongly prefers creating a client-side discoverable credential, but will accept a server-side credential. The client and authenticator SHOULD create a discoverable credential if possible. For example, the client SHOULD guide the user through setting up user verification if needed to create a discoverable credential. This takes precedence over the setting of userVerification.
/// </summary>
[EnumMember(Value = "preferred")]
Preferred,

/// <summary>
/// The Relying Party prefers creating a server-side credential, but will accept a client-side discoverable credential. The client and authenticator SHOULD create a server-side credential if possible.
/// </summary>
[EnumMember(Value = "discouraged")]
Discouraged
}
}
2 changes: 1 addition & 1 deletion Test/Attestation/Apple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public async Task TestApplePublicKeyMismatch()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = _challenge,
Expand Down
22 changes: 11 additions & 11 deletions Test/AuthenticatorResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public async Task TestAuthenticatorOrigins(string origin, string expectedOrigin)
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -184,7 +184,7 @@ public void TestAuthenticatorOriginsFail(string origin, string expectedOrigin)
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -383,7 +383,7 @@ public void TestAuthenticatorAttestationResponseInvalidType()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -454,7 +454,7 @@ public void TestAuthenticatorAttestationResponseInvalidRawId(byte[] value)
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -523,7 +523,7 @@ public void TestAuthenticatorAttestationResponseInvalidRawType()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -600,7 +600,7 @@ public void TestAuthenticatorAttestationResponseRpidMismatch()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -679,7 +679,7 @@ public async Task TestAuthenticatorAttestationResponseNotUserPresent()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -758,7 +758,7 @@ public void TestAuthenticatorAttestationResponseNoAttestedCredentialData()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -836,7 +836,7 @@ public void TestAuthenticatorAttestationResponseUnknownAttestationType()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -914,7 +914,7 @@ public void TestAuthenticatorAttestationResponseNotUniqueCredId()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = challenge,
Expand Down Expand Up @@ -991,7 +991,7 @@ public void TestAuthenticatorAttestationResponseUVRequired()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Required,
},
Challenge = challenge,
Expand Down
2 changes: 1 addition & 1 deletion Test/Fido2Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public Attestation()
AuthenticatorSelection = new AuthenticatorSelection
{
AuthenticatorAttachment = AuthenticatorAttachment.CrossPlatform,
RequireResidentKey = true,
ResidentKey = ResidentKeyRequirement.Required,
UserVerification = UserVerificationRequirement.Discouraged,
},
Challenge = _challenge,
Expand Down

0 comments on commit 45af0e4

Please sign in to comment.