Skip to content

Commit 1c003bf

Browse files
authored
Introduce wrapping objects for Options-methods (#562)
* RequestNewCredentialParams * Create wrapper objects for GetAssertionOptinos * format * remove empty comment
1 parent 3c6808e commit 1c003bf

File tree

7 files changed

+123
-71
lines changed

7 files changed

+123
-71
lines changed

BlazorWasmDemo/Server/Controllers/UserController.cs

+14-11
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,19 @@ public CredentialCreateOptions GetCredentialOptions(
103103
}
104104

105105
// 4. Create options
106-
var options = _fido2.RequestNewCredential(
107-
user,
108-
existingKeys,
109-
authenticatorSelection,
110-
attestationType ?? AttestationConveyancePreference.None,
111-
new AuthenticationExtensionsClientInputs
106+
var options = _fido2.RequestNewCredential(new RequestNewCredentialParams
107+
{
108+
User = user,
109+
ExcludeCredentials = existingKeys,
110+
AuthenticatorSelection = authenticatorSelection,
111+
AttestationPreference = attestationType ?? AttestationConveyancePreference.None,
112+
Extensions = new AuthenticationExtensionsClientInputs
112113
{
113114
Extensions = true,
114115
UserVerificationMethod = true,
115116
CredProps = true
116117
}
117-
);
118+
});
118119

119120
// 5. Temporarily store options, session/in-memory cache/redis/db
120121
_pendingCredentials[key] = options;
@@ -212,10 +213,12 @@ public AssertionOptions MakeAssertionOptions([FromRoute] string? username, [From
212213
};
213214

214215
// 2. Create options (usernameless users will be prompted by their device to select a credential from their own list)
215-
var options = _fido2.GetAssertionOptions(
216-
existingKeys,
217-
userVerification ?? UserVerificationRequirement.Discouraged,
218-
exts);
216+
var options = _fido2.GetAssertionOptions(new GetAssertionOptionsParams
217+
{
218+
AllowedCredentials = existingKeys,
219+
UserVerification = userVerification ?? UserVerificationRequirement.Discouraged,
220+
Extensions = exts
221+
});
219222

220223
// 4. Temporarily store options, session/in-memory cache/redis/db
221224
_pendingAssertions[new string(options.Challenge.Select(b => (char)b).ToArray())] = options;

Demo/Controller.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public JsonResult MakeCredentialOptions([FromForm] string username,
7070
CredProps = true
7171
};
7272

73-
var options = _fido2.RequestNewCredential(user, existingKeys, authenticatorSelection, attType.ToEnum<AttestationConveyancePreference>(), exts);
73+
var options = _fido2.RequestNewCredential(new RequestNewCredentialParams { User = user, ExcludeCredentials = existingKeys, AuthenticatorSelection = authenticatorSelection, AttestationPreference = attType.ToEnum<AttestationConveyancePreference>(), Extensions = exts });
7474

7575
// 4. Temporarily store options, session/in-memory cache/redis/db
7676
HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson());
@@ -163,11 +163,12 @@ public ActionResult AssertionOptionsPost([FromForm] string username, [FromForm]
163163

164164
// 3. Create options
165165
var uv = string.IsNullOrEmpty(userVerification) ? UserVerificationRequirement.Discouraged : userVerification.ToEnum<UserVerificationRequirement>();
166-
var options = _fido2.GetAssertionOptions(
167-
existingCredentials,
168-
uv,
169-
exts
170-
);
166+
var options = _fido2.GetAssertionOptions(new GetAssertionOptionsParams()
167+
{
168+
AllowedCredentials = existingCredentials,
169+
UserVerification = uv,
170+
Extensions = exts
171+
});
171172

172173
// 4. Temporarily store options, session/in-memory cache/redis/db
173174
HttpContext.Session.SetString("fido2.assertionOptions", options.ToJson());

Demo/TestController.cs

+16-8
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,16 @@ public OkObjectResult MakeCredentialOptionsTest([FromBody] TEST_MakeCredentialPa
6868
exts.Example = opts.Extensions.Example;
6969

7070
// 3. Create options
71-
var options = _fido2.RequestNewCredential(user, existingKeys, opts.AuthenticatorSelection, opts.Attestation, exts);
72-
73-
// 4. Temporarily store options, session/in-memory cache/redis/db
71+
var options = _fido2.RequestNewCredential(new RequestNewCredentialParams
72+
{
73+
User = user,
74+
ExcludeCredentials = existingKeys,
75+
AuthenticatorSelection = opts.AuthenticatorSelection,
76+
AttestationPreference = opts.Attestation,
77+
Extensions = exts
78+
});
79+
80+
// 4. Temporarily store options, session/in-memory cache/redis/db
7481
HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson());
7582

7683
// 5. return options to client
@@ -146,11 +153,12 @@ public IActionResult AssertionOptionsTest([FromBody] TEST_AssertionClientParams
146153
exts.Example = assertionClientParams.Extensions.Example;
147154

148155
// 3. Create options
149-
var options = _fido2.GetAssertionOptions(
150-
existingCredentials,
151-
uv,
152-
exts
153-
);
156+
var options = _fido2.GetAssertionOptions(new GetAssertionOptionsParams
157+
{
158+
AllowedCredentials = existingCredentials,
159+
UserVerification = uv,
160+
Extensions = exts
161+
});
154162

155163
// 4. Temporarily store options, session/in-memory cache/redis/db
156164
HttpContext.Session.SetString("fido2.assertionOptions", options.ToJson());

Src/Fido2/Fido2.cs

+12-31
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,13 @@ public Fido2(
2626
/// <summary>
2727
/// Returns CredentialCreateOptions including a challenge to be sent to the browser/authenticator to create new credentials.
2828
/// </summary>
29-
/// <param name="user"></param>
30-
/// <param name="excludeCredentials">Recommended. This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator. The client is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter.</param>
31-
/// <param name="extensions"></param>
29+
/// <param name="requestNewCredentialParams">The input arguments for generating CredentialCreateOptions</param>
3230
/// <returns></returns>
33-
public CredentialCreateOptions RequestNewCredential(
34-
Fido2User user,
35-
IReadOnlyList<PublicKeyCredentialDescriptor> excludeCredentials,
36-
AuthenticationExtensionsClientInputs? extensions = null)
31+
public CredentialCreateOptions RequestNewCredential(RequestNewCredentialParams requestNewCredentialParams)
3732
{
38-
return RequestNewCredential(user, excludeCredentials, AuthenticatorSelection.Default, AttestationConveyancePreference.None, extensions);
39-
}
33+
var challenge = RandomNumberGenerator.GetBytes(_config.ChallengeSize);
34+
return CredentialCreateOptions.Create(_config, challenge, requestNewCredentialParams.User, requestNewCredentialParams.AuthenticatorSelection, requestNewCredentialParams.AttestationPreference, requestNewCredentialParams.ExcludeCredentials, requestNewCredentialParams.Extensions);
4035

41-
/// <summary>
42-
/// Returns CredentialCreateOptions including a challenge to be sent to the browser/authenticator to create new credentials.
43-
/// </summary>
44-
/// <param name="user"></param>
45-
/// <param name="excludeCredentials">Recommended. This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator. The client is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter.</param>
46-
/// <param name="authenticatorSelection"></param>
47-
/// <param name="attestationPreference">This member is intended for use by Relying Parties that wish to express their preference for attestation conveyance. The default is none.</param>
48-
/// <param name="extensions"></param>
49-
/// <returns></returns>
50-
public CredentialCreateOptions RequestNewCredential(
51-
Fido2User user,
52-
IReadOnlyList<PublicKeyCredentialDescriptor> excludeCredentials,
53-
AuthenticatorSelection authenticatorSelection,
54-
AttestationConveyancePreference attestationPreference,
55-
AuthenticationExtensionsClientInputs? extensions = null)
56-
{
57-
byte[] challenge = RandomNumberGenerator.GetBytes(_config.ChallengeSize);
58-
59-
return CredentialCreateOptions.Create(_config, challenge, user, authenticatorSelection, attestationPreference, excludeCredentials, extensions);
6036
}
6137

6238
/// <summary>
@@ -77,10 +53,15 @@ public async Task<RegisteredPublicKeyCredential> MakeNewCredentialAsync(MakeNewC
7753
/// <summary>
7854
/// Returns AssertionOptions including a challenge to the browser/authenticator to assert existing credentials and authenticate a user.
7955
/// </summary>
80-
/// <param name="allowedCredentials"></param>
81-
/// <param name="userVerification"></param>
82-
/// <param name="extensions"></param>
56+
/// <param name="getAssertionOptionsParams">The input arguments for generating AssertionOptions</param>
8357
/// <returns></returns>
58+
public AssertionOptions GetAssertionOptions(GetAssertionOptionsParams getAssertionOptionsParams)
59+
{
60+
byte[] challenge = RandomNumberGenerator.GetBytes(_config.ChallengeSize);
61+
62+
return AssertionOptions.Create(_config, challenge, getAssertionOptionsParams.AllowedCredentials, getAssertionOptionsParams.UserVerification, getAssertionOptionsParams.Extensions);
63+
}
64+
8465
public AssertionOptions GetAssertionOptions(
8566
IReadOnlyList<PublicKeyCredentialDescriptor> allowedCredentials,
8667
UserVerificationRequirement? userVerification,
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Fido2NetLib.Objects;
4+
5+
namespace Fido2NetLib;
6+
7+
/// <summary>
8+
/// The input arguments for generating AssertionOptions
9+
/// </summary>
10+
public sealed class GetAssertionOptionsParams
11+
{
12+
/// <summary>
13+
/// This OPTIONAL member is used by the client to find authenticators eligible for this authentication ceremony. It can be used in two ways:
14+
///
15+
/// * If the user account to authenticate is already identified (e.g., if the user has entered a username), then the Relying Party SHOULD use this member to list credential descriptors for credential records in the user account. This SHOULD usually include all credential records in the user account.
16+
/// The items SHOULD specify transports whenever possible. This helps the client optimize the user experience for any given situation. Also note that the Relying Party does not need to filter the list when requesting user verification — the client will automatically ignore non-eligible credentials if userVerification is set to required.
17+
/// See also the § 14.6.3 Privacy leak via credential IDs privacy consideration.
18+
/// * If the user account to authenticate is not already identified, then the Relying Party MAY leave this member empty or unspecified. In this case, only discoverable credentials will be utilized in this authentication ceremony, and the user account MAY be identified by the userHandle of the resulting AuthenticatorAssertionResponse. If the available authenticators contain more than one discoverable credential scoped to the Relying Party, the credentials are displayed by the client platform or authenticator for the user to select from (see step 7 of § 6.3.3 The authenticatorGetAssertion Operation).
19+
///
20+
/// If not empty, the client MUST return an error if none of the listed credentials can be used.
21+
///
22+
/// The list is ordered in descending order of preference: the first item in the list is the most preferred credential, and the last is the least preferred.
23+
/// </summary>
24+
public IReadOnlyList<PublicKeyCredentialDescriptor> AllowedCredentials { get; init; } = Array.Empty<PublicKeyCredentialDescriptor>();
25+
26+
/// <summary>
27+
/// This OPTIONAL member specifies the Relying Party's requirements regarding user verification for the get() operation. The value SHOULD be a member of UserVerificationRequirement but client platforms MUST ignore unknown values, treating an unknown value as if the member does not exist. Eligible authenticators are filtered to only those capable of satisfying this requirement.
28+
/// </summary>
29+
public UserVerificationRequirement? UserVerification { get; init; }
30+
31+
/// <summary>
32+
/// The Relying Party MAY use this OPTIONAL member to provide client extension inputs requesting additional processing by the client and authenticator.
33+
/// </summary>
34+
public AuthenticationExtensionsClientInputs? Extensions { get; init; }
35+
}

Src/Fido2/IFido2.cs

+2-15
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,13 @@ namespace Fido2NetLib;
88

99
public interface IFido2
1010
{
11-
AssertionOptions GetAssertionOptions(
12-
IReadOnlyList<PublicKeyCredentialDescriptor> allowedCredentials,
13-
UserVerificationRequirement? userVerification,
14-
AuthenticationExtensionsClientInputs? extensions = null);
11+
AssertionOptions GetAssertionOptions(GetAssertionOptionsParams getAssertionOptionsParams);
1512

1613
Task<VerifyAssertionResult> MakeAssertionAsync(MakeAssertionParams makeAssertionParams,
1714
CancellationToken cancellationToken = default);
1815

1916
Task<RegisteredPublicKeyCredential> MakeNewCredentialAsync(MakeNewCredentialParams makeNewCredentialParams,
2017
CancellationToken cancellationToken = default);
2118

22-
CredentialCreateOptions RequestNewCredential(
23-
Fido2User user,
24-
IReadOnlyList<PublicKeyCredentialDescriptor> excludeCredentials,
25-
AuthenticationExtensionsClientInputs? extensions = null);
26-
27-
CredentialCreateOptions RequestNewCredential(
28-
Fido2User user,
29-
IReadOnlyList<PublicKeyCredentialDescriptor> excludeCredentials,
30-
AuthenticatorSelection authenticatorSelection,
31-
AttestationConveyancePreference attestationPreference,
32-
AuthenticationExtensionsClientInputs? extensions = null);
19+
CredentialCreateOptions RequestNewCredential(RequestNewCredentialParams requestNewCredentialParams);
3320
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Fido2NetLib.Objects;
4+
5+
namespace Fido2NetLib;
6+
7+
/// <summary>
8+
/// The input arguments for generating CredentialCreateOptions
9+
/// </summary>
10+
public sealed class RequestNewCredentialParams
11+
{
12+
/// <summary>
13+
/// This member contains names and an identifier for the user account performing the registration. Its value’s name, displayName and id members are REQUIRED. id can be returned as the userHandle in some future authentication ceremonies, and is used to overwrite existing discoverable credentials that have the same rp.id and user.id on the same authenticator. name and displayName MAY be used by the authenticator and client in future authentication ceremonies to help the user select a credential, but are not returned to the Relying Party as a result of future authentication ceremonies
14+
/// </summary>
15+
public required Fido2User User { get; init; }
16+
17+
/// <summary>
18+
/// The Relying Party SHOULD use this OPTIONAL member to list any existing credentials mapped to this user account (as identified by user.id). This ensures that the new credential is not created on an authenticator that already contains a credential mapped to this user account. If it would be, the client is requested to instead guide the user to use a different authenticator, or return an error if that fails.
19+
/// </summary>
20+
public IReadOnlyList<PublicKeyCredentialDescriptor> ExcludeCredentials { get; init; } =
21+
Array.Empty<PublicKeyCredentialDescriptor>();
22+
23+
/// <summary>
24+
/// The Relying Party MAY use this OPTIONAL member to specify capabilities and settings that the authenticator MUST or SHOULD satisfy to participate in the create() operation. See § 5.4.4 Authenticator Selection Criteria (dictionary AuthenticatorSelectionCriteria).
25+
/// </summary>
26+
public AuthenticatorSelection AuthenticatorSelection { get; init; } = AuthenticatorSelection.Default;
27+
28+
/// <summary>
29+
/// The Relying Party MAY use this OPTIONAL member to specify a preference regarding attestation conveyance. Its value SHOULD be a member of AttestationConveyancePreference. Client platforms MUST ignore unknown values, treating an unknown value as if the member does not exist.
30+
/// </summary>
31+
public AttestationConveyancePreference AttestationPreference { get; init; } = AttestationConveyancePreference.None;
32+
33+
/// <summary>
34+
/// The Relying Party MAY use this OPTIONAL member to provide client extension inputs requesting additional processing by the client and authenticator. For example, the Relying Party may request that the client returns additional information about the credential that was created.
35+
/// </summary>
36+
public AuthenticationExtensionsClientInputs? Extensions { get; init; }
37+
}

0 commit comments

Comments
 (0)