From cb71a15c6df0e9d5230b7266502cd8bb26f656cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=85berg?= Date: Tue, 16 Jul 2024 15:32:04 +0200 Subject: [PATCH] Remove base-class, Status and ErrorMessage (#529) * Remove base-class * Removed usage of Status/ErrorMessage in tests * Rename MakeNewCredentialResult.Result to .Credential * format * Removed MakeNewCredentialResult * fixed after rebase * Passes conformance tests * undo local changes * small fix * small fix --- BlazorWasmDemo/Client/Shared/UserService.cs | 5 -- .../Server/Controllers/UserController.cs | 54 ++++++------- Demo/Controller.cs | 36 ++++----- Demo/TestController.cs | 33 +++++--- Src/Fido2.Models/AssertionOptions.cs | 4 +- Src/Fido2.Models/CredentialCreateOptions.cs | 4 +- Src/Fido2.Models/Fido2ResponseBase.cs | 14 ---- .../Objects/MakeNewCredentialResult.cs | 20 ----- .../Objects/RegisteredPublicKeyCredential.cs | 2 +- .../Objects/VerifyAssertionResult.cs | 2 +- Src/Fido2/AuthenticatorAssertionResponse.cs | 1 - Src/Fido2/Fido2.cs | 13 +--- Src/Fido2/IFido2.cs | 2 +- Test/Attestation/AndroidKey.cs | 24 +++--- Test/Attestation/AndroidSafetyNet.cs | 46 +++++------ Test/Attestation/Apple.cs | 2 - Test/Attestation/FidoU2f.cs | 24 +++--- Test/Attestation/None.cs | 28 +++---- Test/Attestation/Packed.cs | 59 ++++++-------- Test/Attestation/Tpm.cs | 78 ++++++++----------- Test/AuthenticatorResponse.cs | 26 ------- Test/ExistingU2fRegistrationDataTests.cs | 4 +- Test/Fido2Tests.cs | 6 +- 23 files changed, 182 insertions(+), 305 deletions(-) delete mode 100644 Src/Fido2.Models/Fido2ResponseBase.cs delete mode 100644 Src/Fido2.Models/Objects/MakeNewCredentialResult.cs diff --git a/BlazorWasmDemo/Client/Shared/UserService.cs b/BlazorWasmDemo/Client/Shared/UserService.cs index 018a23fb..208ad127 100644 --- a/BlazorWasmDemo/Client/Shared/UserService.cs +++ b/BlazorWasmDemo/Client/Shared/UserService.cs @@ -134,11 +134,6 @@ public async Task LoginAsync(string? username) return "No options received"; } - if (options.Status != "ok") - { - return options.ErrorMessage ?? string.Empty; - } - // Present options to user and get response (usernameless users will be asked by their authenticator, which credential they want to use to sign the challenge) var assertion = await _webAuthn.VerifyAsync(options); diff --git a/BlazorWasmDemo/Server/Controllers/UserController.cs b/BlazorWasmDemo/Server/Controllers/UserController.cs index d1ce9ef3..7ad042ab 100644 --- a/BlazorWasmDemo/Server/Controllers/UserController.cs +++ b/BlazorWasmDemo/Server/Controllers/UserController.cs @@ -126,9 +126,9 @@ public CredentialCreateOptions GetCredentialOptions( // 6. return options to client return options; } - catch (Exception e) + catch (Exception) { - return new CredentialCreateOptions { Status = "error", ErrorMessage = FormatException(e) }; + throw; } } @@ -150,29 +150,25 @@ public async Task CreateCredentialAsync([FromRoute] string username, [Fr // 2. Create callback so that lib can verify credential id is unique to this user // 3. Verify and make the credentials - var result = await _fido2.MakeNewCredentialAsync(attestationResponse, options, CredentialIdUniqueToUserAsync, cancellationToken: cancellationToken); - - if (result.Status is "error" || result.Result is null) - { - return result.ErrorMessage ?? string.Empty; - } + var credential = await _fido2.MakeNewCredentialAsync(attestationResponse, options, CredentialIdUniqueToUserAsync, cancellationToken: cancellationToken); // 4. Store the credentials in db _demoStorage.AddCredentialToUser(options.User, new StoredCredential { - AttestationFormat = result.Result.AttestationFormat, - Id = result.Result.Id, - PublicKey = result.Result.PublicKey, - UserHandle = result.Result.User.Id, - SignCount = result.Result.SignCount, + + AttestationFormat = credential.AttestationFormat, + Id = credential.Id, + PublicKey = credential.PublicKey, + UserHandle = credential.User.Id, + SignCount = credential.SignCount, RegDate = DateTimeOffset.UtcNow, - AaGuid = result.Result.AaGuid, - DevicePublicKeys = [result.Result.DevicePublicKey], - Transports = result.Result.Transports, - IsBackupEligible = result.Result.IsBackupEligible, - IsBackedUp = result.Result.IsBackedUp, - AttestationObject = result.Result.AttestationObject, - AttestationClientDataJson = result.Result.AttestationClientDataJson, + AaGuid = credential.AaGuid, + DevicePublicKeys = [credential.DevicePublicKey], + Transports = credential.Transports, + IsBackupEligible = credential.IsBackupEligible, + IsBackedUp = credential.IsBackedUp, + AttestationObject = credential.AttestationObject, + AttestationClientDataJson = credential.AttestationClientDataJson, }); // 5. Now we need to remove the options from the pending dictionary @@ -228,9 +224,9 @@ public AssertionOptions MakeAssertionOptions([FromRoute] string? username, [From // 5. return options to client return options; } - catch (Exception e) + catch (Exception) { - return new AssertionOptions { Status = "error", ErrorMessage = FormatException(e) }; + throw; } } @@ -280,19 +276,13 @@ public async Task MakeAssertionAsync([FromBody] AuthenticatorAssertionRa cancellationToken: cancellationToken); // 4. Store the updated counter - if (res.Status is "ok") + _demoStorage.UpdateCounter(res.CredentialId, res.SignCount); + if (res.DevicePublicKey is not null) { - _demoStorage.UpdateCounter(res.CredentialId, res.SignCount); - if (res.DevicePublicKey is not null) - { - creds.DevicePublicKeys.Add(res.DevicePublicKey); - } - } - else - { - return $"Error: {res.ErrorMessage}"; + creds.DevicePublicKeys.Add(res.DevicePublicKey); } + // 5. return result to client var handler = new JwtSecurityTokenHandler(); var token = handler.CreateEncodedJwt( diff --git a/Demo/Controller.cs b/Demo/Controller.cs index 481c6356..733f11e7 100644 --- a/Demo/Controller.cs +++ b/Demo/Controller.cs @@ -81,7 +81,7 @@ public JsonResult MakeCredentialOptions([FromForm] string username, } catch (Exception e) { - return Json(new CredentialCreateOptions { Status = "error", ErrorMessage = FormatException(e) }); + return Json(new { Status = "error", ErrorMessage = FormatException(e) }); } } @@ -106,32 +106,32 @@ public async Task MakeCredential([FromBody] AuthenticatorAttestation }; // 2. Verify and make the credentials - var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback, cancellationToken: cancellationToken); + var credential = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback, cancellationToken: cancellationToken); // 3. Store the credentials in db DemoStorage.AddCredentialToUser(options.User, new StoredCredential { - Id = success.Result.Id, - PublicKey = success.Result.PublicKey, - UserHandle = success.Result.User.Id, - SignCount = success.Result.SignCount, - AttestationFormat = success.Result.AttestationFormat, + Id = credential.Id, + PublicKey = credential.PublicKey, + UserHandle = credential.User.Id, + SignCount = credential.SignCount, + AttestationFormat = credential.AttestationFormat, RegDate = DateTimeOffset.UtcNow, - AaGuid = success.Result.AaGuid, - Transports = success.Result.Transports, - IsBackupEligible = success.Result.IsBackupEligible, - IsBackedUp = success.Result.IsBackedUp, - AttestationObject = success.Result.AttestationObject, - AttestationClientDataJson = success.Result.AttestationClientDataJson, - DevicePublicKeys = [success.Result.DevicePublicKey] + AaGuid = credential.AaGuid, + Transports = credential.Transports, + IsBackupEligible = credential.IsBackupEligible, + IsBackedUp = credential.IsBackedUp, + AttestationObject = credential.AttestationObject, + AttestationClientDataJson = credential.AttestationClientDataJson, + DevicePublicKeys = [credential.DevicePublicKey] }); // 4. return "ok" to the client - return Json(success); + return Json(credential); } catch (Exception e) { - return Json(new MakeNewCredentialResult(status: "error", errorMessage: FormatException(e), result: null)); + return Json(new { status = "error", errorMessage = FormatException(e) }); } } @@ -176,7 +176,7 @@ public ActionResult AssertionOptionsPost([FromForm] string username, [FromForm] catch (Exception e) { - return Json(new AssertionOptions { Status = "error", ErrorMessage = FormatException(e) }); + return Json(new { Status = "error", ErrorMessage = FormatException(e) }); } } @@ -217,7 +217,7 @@ public async Task MakeAssertion([FromBody] AuthenticatorAssertionRaw } catch (Exception e) { - return Json(new VerifyAssertionResult { Status = "error", ErrorMessage = FormatException(e) }); + return Json(new { Status = "error", ErrorMessage = FormatException(e) }); } } } diff --git a/Demo/TestController.cs b/Demo/TestController.cs index eaf3c86f..d0d67163 100644 --- a/Demo/TestController.cs +++ b/Demo/TestController.cs @@ -1,5 +1,6 @@ using System.Text; - +using System.Text.Json; +using System.Text.Json.Serialization; using Fido2NetLib; using Fido2NetLib.Development; using Fido2NetLib.Objects; @@ -34,7 +35,7 @@ public TestController(IOptions fido2Configuration) [HttpPost] [Route("/attestation/options")] - public JsonResult MakeCredentialOptionsTest([FromBody] TEST_MakeCredentialParams opts) + public OkObjectResult MakeCredentialOptionsTest([FromBody] TEST_MakeCredentialParams opts) { var attType = opts.Attestation; @@ -72,12 +73,16 @@ public JsonResult MakeCredentialOptionsTest([FromBody] TEST_MakeCredentialParams HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson()); // 5. return options to client - return Json(options); + + var jsonResponse = JsonSerializer.SerializeToNode(options); + jsonResponse["status"] = "ok"; + jsonResponse["errorMessage"] = ""; + return new OkObjectResult(jsonResponse); } [HttpPost] [Route("/attestation/result")] - public async Task MakeCredentialResultTestAsync([FromBody] AuthenticatorAttestationRawResponse attestationResponse, CancellationToken cancellationToken) + public async Task MakeCredentialResultTestAsync([FromBody] AuthenticatorAttestationRawResponse attestationResponse, CancellationToken cancellationToken) { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); @@ -91,19 +96,22 @@ public async Task MakeCredentialResultTestAsync([FromBody] Authentic }; // 2. Verify and make the credentials - var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback, cancellationToken: cancellationToken); + var credential = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback, cancellationToken: cancellationToken); // 3. Store the credentials in db _demoStorage.AddCredentialToUser(options.User, new StoredCredential { - Id = success.Result.Id, - PublicKey = success.Result.PublicKey, - UserHandle = success.Result.User.Id, - SignCount = success.Result.SignCount + Id = credential.Id, + PublicKey = credential.PublicKey, + UserHandle = credential.User.Id, + SignCount = credential.SignCount }); // 4. return "ok" to the client - return Json(success); + var jsonResponse = JsonSerializer.SerializeToNode(credential); + jsonResponse["status"] = "ok"; + jsonResponse["errorMessage"] = ""; + return new OkObjectResult(jsonResponse); } [HttpPost] @@ -142,7 +150,10 @@ public IActionResult AssertionOptionsTest([FromBody] TEST_AssertionClientParams HttpContext.Session.SetString("fido2.assertionOptions", options.ToJson()); // 5. Return options to client - return Json(options); + var jsonResponse = JsonSerializer.SerializeToNode(options); + jsonResponse["status"] = "ok"; + jsonResponse["errorMessage"] = ""; + return new OkObjectResult(jsonResponse); } [HttpPost] diff --git a/Src/Fido2.Models/AssertionOptions.cs b/Src/Fido2.Models/AssertionOptions.cs index 3c4f6e27..4ac4fb9c 100644 --- a/Src/Fido2.Models/AssertionOptions.cs +++ b/Src/Fido2.Models/AssertionOptions.cs @@ -9,7 +9,7 @@ namespace Fido2NetLib; /// /// Sent to the browser when we want to Assert credentials and authenticate a user /// -public class AssertionOptions : Fido2ResponseBase +public class AssertionOptions { /// /// This member represents a challenge that the selected authenticator signs, along with other data, when producing an authentication assertion. @@ -71,8 +71,6 @@ public static AssertionOptions Create( { return new AssertionOptions() { - Status = "ok", - ErrorMessage = string.Empty, Challenge = challenge, Timeout = config.Timeout, RpId = config.ServerDomain, diff --git a/Src/Fido2.Models/CredentialCreateOptions.cs b/Src/Fido2.Models/CredentialCreateOptions.cs index f792b5d1..1e5b2239 100644 --- a/Src/Fido2.Models/CredentialCreateOptions.cs +++ b/Src/Fido2.Models/CredentialCreateOptions.cs @@ -6,7 +6,7 @@ namespace Fido2NetLib; -public sealed class CredentialCreateOptions : Fido2ResponseBase +public sealed class CredentialCreateOptions { /// /// @@ -117,8 +117,6 @@ public static CredentialCreateOptions Create( { return new CredentialCreateOptions { - Status = "ok", - ErrorMessage = string.Empty, Challenge = challenge, Rp = new PublicKeyCredentialRpEntity(config.ServerDomain, config.ServerName, config.ServerIcon), Timeout = config.Timeout, diff --git a/Src/Fido2.Models/Fido2ResponseBase.cs b/Src/Fido2.Models/Fido2ResponseBase.cs deleted file mode 100644 index 91d5cc0c..00000000 --- a/Src/Fido2.Models/Fido2ResponseBase.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Fido2NetLib; - -public abstract class Fido2ResponseBase -{ - [JsonPropertyName("status")] - public string Status { get; set; } - -#nullable enable - - [JsonPropertyName("errorMessage")] - public string? ErrorMessage { get; set; } -} diff --git a/Src/Fido2.Models/Objects/MakeNewCredentialResult.cs b/Src/Fido2.Models/Objects/MakeNewCredentialResult.cs deleted file mode 100644 index e4ae50b3..00000000 --- a/Src/Fido2.Models/Objects/MakeNewCredentialResult.cs +++ /dev/null @@ -1,20 +0,0 @@ -#nullable enable - -namespace Fido2NetLib.Objects; - -/// -/// Result of parsing and verifying attestation. Used to transport Public Key back to RP. -/// -public sealed class MakeNewCredentialResult : Fido2ResponseBase -{ - public MakeNewCredentialResult(string status, string errorMessage, RegisteredPublicKeyCredential? result) - { - Status = status; - ErrorMessage = errorMessage; - Result = result; - } - - public RegisteredPublicKeyCredential? Result { get; } - - // todo: add debuginfo? -} diff --git a/Src/Fido2.Models/Objects/RegisteredPublicKeyCredential.cs b/Src/Fido2.Models/Objects/RegisteredPublicKeyCredential.cs index 0fbaa6ff..3ada5ade 100644 --- a/Src/Fido2.Models/Objects/RegisteredPublicKeyCredential.cs +++ b/Src/Fido2.Models/Objects/RegisteredPublicKeyCredential.cs @@ -5,7 +5,7 @@ namespace Fido2NetLib.Objects; /// /// Holds parsed credential data /// -public class RegisteredPublicKeyCredential : Fido2ResponseBase +public class RegisteredPublicKeyCredential { /// /// The type of the public key credential source. diff --git a/Src/Fido2.Models/Objects/VerifyAssertionResult.cs b/Src/Fido2.Models/Objects/VerifyAssertionResult.cs index abd9896c..dc397c73 100644 --- a/Src/Fido2.Models/Objects/VerifyAssertionResult.cs +++ b/Src/Fido2.Models/Objects/VerifyAssertionResult.cs @@ -3,7 +3,7 @@ /// /// Result of the MakeAssertion verification /// -public class VerifyAssertionResult : Fido2ResponseBase +public class VerifyAssertionResult { public byte[] CredentialId { get; init; } diff --git a/Src/Fido2/AuthenticatorAssertionResponse.cs b/Src/Fido2/AuthenticatorAssertionResponse.cs index c917c4f8..e2b30b13 100644 --- a/Src/Fido2/AuthenticatorAssertionResponse.cs +++ b/Src/Fido2/AuthenticatorAssertionResponse.cs @@ -176,7 +176,6 @@ public async Task VerifyAsync( return new VerifyAssertionResult { - Status = "ok", CredentialId = Raw.Id, SignCount = authData.SignCount, IsBackedUp = authData.IsBackedUp, diff --git a/Src/Fido2/Fido2.cs b/Src/Fido2/Fido2.cs index df317f9c..11dc1b93 100644 --- a/Src/Fido2/Fido2.cs +++ b/Src/Fido2/Fido2.cs @@ -67,21 +67,16 @@ public CredentialCreateOptions RequestNewCredential( /// The delegate used to validate that the CredentialID is unique to this user. /// The used to propagate notifications that the operation should be canceled. /// - public async Task MakeNewCredentialAsync( + public async Task MakeNewCredentialAsync( AuthenticatorAttestationRawResponse attestationResponse, CredentialCreateOptions originalOptions, IsCredentialIdUniqueToUserAsyncDelegate isCredentialIdUniqueToUser, CancellationToken cancellationToken = default) { var parsedResponse = AuthenticatorAttestationResponse.Parse(attestationResponse); - var success = await parsedResponse.VerifyAsync(originalOptions, _config, isCredentialIdUniqueToUser, _metadataService, cancellationToken); - - // todo: Set Errormessage etc. - return new MakeNewCredentialResult( - status: "ok", - errorMessage: string.Empty, - result: success - ); + var credential = await parsedResponse.VerifyAsync(originalOptions, _config, isCredentialIdUniqueToUser, _metadataService, cancellationToken); + + return credential; } /// diff --git a/Src/Fido2/IFido2.cs b/Src/Fido2/IFido2.cs index a0738db6..a536bbef 100644 --- a/Src/Fido2/IFido2.cs +++ b/Src/Fido2/IFido2.cs @@ -22,7 +22,7 @@ Task MakeAssertionAsync( IsUserHandleOwnerOfCredentialIdAsync isUserHandleOwnerOfCredentialIdCallback, CancellationToken cancellationToken = default); - Task MakeNewCredentialAsync( + Task MakeNewCredentialAsync( AuthenticatorAttestationRawResponse attestationResponse, CredentialCreateOptions originalOptions, IsCredentialIdUniqueToUserAsyncDelegate isCredentialIdUniqueToUser, diff --git a/Test/Attestation/AndroidKey.cs b/Test/Attestation/AndroidKey.cs index 7053b5e2..53022433 100644 --- a/Test/Attestation/AndroidKey.cs +++ b/Test/Attestation/AndroidKey.cs @@ -63,20 +63,16 @@ public AndroidKey() [Fact] public async Task TestAndroidKey() { - var res = await MakeAttestationResponseAsync(); - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("android-key", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); - Assert.Equal(new[] { AuthenticatorTransport.Internal }, res.Result.Transports); + var credential = await MakeAttestationResponseAsync(); + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("android-key", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); + Assert.Equal(new[] { AuthenticatorTransport.Internal }, credential.Transports); } [Fact] diff --git a/Test/Attestation/AndroidSafetyNet.cs b/Test/Attestation/AndroidSafetyNet.cs index 85073e5c..0d290e90 100644 --- a/Test/Attestation/AndroidSafetyNet.cs +++ b/Test/Attestation/AndroidSafetyNet.cs @@ -99,20 +99,16 @@ public AndroidSafetyNet() [Fact] public async Task TestAndroidSafetyNet() { - var res = await MakeAttestationResponseAsync(); - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("android-safetynet", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); - Assert.Equal([AuthenticatorTransport.Internal], res.Result.Transports); + var credential = await MakeAttestationResponseAsync(); + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("android-safetynet", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); + Assert.Equal([AuthenticatorTransport.Internal], credential.Transports); } [Fact] @@ -187,19 +183,15 @@ public async Task TestAndroidSafetyNetRSA() { "response", Encoding.UTF8.GetBytes(securityToken) } }); - var res = await MakeAttestationResponseAsync(); - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("android-safetynet", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); + var credential = await MakeAttestationResponseAsync(); + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("android-safetynet", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); } } diff --git a/Test/Attestation/Apple.cs b/Test/Attestation/Apple.cs index e394993b..a09862dd 100644 --- a/Test/Attestation/Apple.cs +++ b/Test/Attestation/Apple.cs @@ -243,13 +243,11 @@ public async Task TestApplePublicKeyMismatch() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = _challenge, - ErrorMessage = "", PubKeyCredParams = [ PubKeyCredParam.ES256 ], Rp = new PublicKeyCredentialRpEntity("https://www.passwordless.dev", "6cc3c9e7967a.ngrok.io", ""), - Status = "ok", User = new Fido2User { Name = "testuser", diff --git a/Test/Attestation/FidoU2f.cs b/Test/Attestation/FidoU2f.cs index 9a22ba49..ddd3c834 100644 --- a/Test/Attestation/FidoU2f.cs +++ b/Test/Attestation/FidoU2f.cs @@ -55,20 +55,16 @@ .. publicKeyU2F [Fact] public async Task TestU2f() { - var res = await MakeAttestationResponseAsync(); - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("fido-u2f", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); - Assert.Equal(new[] { AuthenticatorTransport.Internal }, res.Result.Transports); + var credential = await MakeAttestationResponseAsync(); + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("fido-u2f", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); + Assert.Equal(new[] { AuthenticatorTransport.Internal }, credential.Transports); } [Fact] diff --git a/Test/Attestation/None.cs b/Test/Attestation/None.cs index afe0c838..01aec620 100644 --- a/Test/Attestation/None.cs +++ b/Test/Attestation/None.cs @@ -25,22 +25,18 @@ public async Task TestNone() _attestationObject.Add("attStmt", new CborMap()); _credentialPublicKey = Fido2Tests.MakeCredentialPublicKey((keyType, alg, crv)); - MakeNewCredentialResult res; - - res = await MakeAttestationResponseAsync(); - - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("none", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); + + + var credential = await MakeAttestationResponseAsync(); + + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("none", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); _attestationObject = new CborMap { { "fmt", "none" } }; } } diff --git a/Test/Attestation/Packed.cs b/Test/Attestation/Packed.cs index 40f746ae..0a703e8b 100644 --- a/Test/Attestation/Packed.cs +++ b/Test/Attestation/Packed.cs @@ -33,22 +33,18 @@ public async Task TestSelf() { "sig", signature } }); - var res = await MakeAttestationResponseAsync(); - - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("packed", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); + var credential = await MakeAttestationResponseAsync(); + + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("packed", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); _attestationObject = new CborMap { { "fmt", "packed" } }; - Assert.Equal(new[] { AuthenticatorTransport.Internal }, res.Result.Transports); + Assert.Equal(new[] { AuthenticatorTransport.Internal }, credential.Transports); } } @@ -203,7 +199,7 @@ public async Task TestFull() DateTimeOffset notAfter = notBefore.AddDays(2); var attDN = new X500DistinguishedName("CN=Testing, OU=Authenticator Attestation, O=FIDO2-NET-LIB, C=US"); - MakeNewCredentialResult res = null; + RegisteredPublicKeyCredential credential = null; switch (type) { @@ -262,7 +258,7 @@ public async Task TestFull() { "x5c", x5c } }); - res = await MakeAttestationResponseAsync(); + credential = await MakeAttestationResponseAsync(); } break; case COSE.KeyType.RSA: @@ -306,7 +302,7 @@ public async Task TestFull() { "x5c", x5c } }); - res = await MakeAttestationResponseAsync(); + credential = await MakeAttestationResponseAsync(); } break; case COSE.KeyType.OKP: @@ -314,24 +310,18 @@ public async Task TestFull() var avr = new VerifyAssertionResult { CredentialId = [0xf1, 0xd0], - ErrorMessage = string.Empty, - Status = "ok", }; } break; } - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("packed", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("packed", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); _attestationObject = new CborMap { { "fmt", "packed" } }; } } @@ -879,9 +869,8 @@ public async Task TestAttCertSubjectCommaAsync() { "x5c", x5c }, }); - var res = await MakeAttestationResponseAsync(); - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); + var credential = await MakeAttestationResponseAsync(); + Assert.NotEmpty(credential.Id); } [Fact] diff --git a/Test/Attestation/Tpm.cs b/Test/Attestation/Tpm.cs index 1c034ce1..f50044f8 100644 --- a/Test/Attestation/Tpm.cs +++ b/Test/Attestation/Tpm.cs @@ -289,22 +289,18 @@ .. y break; } - var res = await MakeAttestationResponseAsync(); - - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("tpm", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); + var credential = await MakeAttestationResponseAsync(); + + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("tpm", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), credential.User.Id); + Assert.Equal("testuser", credential.User.Name); _attestationObject = new CborMap { { "fmt", "tpm" } }; - Assert.Equal([AuthenticatorTransport.Internal], res.Result.Transports); + Assert.Equal([AuthenticatorTransport.Internal], credential.Transports); } } @@ -408,21 +404,17 @@ public async Task TestTPMAikCertSANTCGConformant() { "pubArea", pubArea } }); - var res = await MakeAttestationResponseAsync(); - - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("tpm", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8, res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); - Assert.Equal([AuthenticatorTransport.Internal], res.Result.Transports); + var credential = await MakeAttestationResponseAsync(); + + Assert.Equal(_aaguid, credential.AaGuid); + Assert.Equal(_signCount, credential.SignCount); + Assert.Equal("tpm", credential.AttestationFormat); + Assert.Equal(_credentialID, credential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), credential.PublicKey); + Assert.Equal("Test User", credential.User.DisplayName); + Assert.Equal("testuser"u8, credential.User.Id); + Assert.Equal("testuser", credential.User.Name); + Assert.Equal([AuthenticatorTransport.Internal], credential.Transports); } [Fact] @@ -5054,21 +5046,17 @@ public async Task TestTPMAikCertMisingAAGUID() { "pubArea", pubArea } }); - var res = await MakeAttestationResponseAsync(); - - Assert.Equal(string.Empty, res.ErrorMessage); - Assert.Equal("ok", res.Status); - Assert.Equal(_aaguid, res.Result.AaGuid); - Assert.Equal(_signCount, res.Result.SignCount); - Assert.Equal("tpm", res.Result.AttestationFormat); - Assert.Equal(_credentialID, res.Result.Id); - Assert.Null(res.Result.ErrorMessage); - Assert.Equal(_credentialPublicKey.GetBytes(), res.Result.PublicKey); - Assert.Null(res.Result.Status); - Assert.Equal("Test User", res.Result.User.DisplayName); - Assert.Equal("testuser"u8.ToArray(), res.Result.User.Id); - Assert.Equal("testuser", res.Result.User.Name); - Assert.Equal([AuthenticatorTransport.Internal], res.Result.Transports); + var crendential = await MakeAttestationResponseAsync(); + + Assert.Equal(_aaguid, crendential.AaGuid); + Assert.Equal(_signCount, crendential.SignCount); + Assert.Equal("tpm", crendential.AttestationFormat); + Assert.Equal(_credentialID, crendential.Id); + Assert.Equal(_credentialPublicKey.GetBytes(), crendential.PublicKey); + Assert.Equal("Test User", crendential.User.DisplayName); + Assert.Equal("testuser"u8.ToArray(), crendential.User.Id); + Assert.Equal("testuser", crendential.User.Name); + Assert.Equal([AuthenticatorTransport.Internal], crendential.Transports); } [Fact] diff --git a/Test/AuthenticatorResponse.cs b/Test/AuthenticatorResponse.cs index 9046c07e..50ff27d0 100644 --- a/Test/AuthenticatorResponse.cs +++ b/Test/AuthenticatorResponse.cs @@ -97,13 +97,11 @@ public async Task TestAuthenticatorOriginsAsync(string origin, string expectedOr UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ PubKeyCredParam.ES256 ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -200,13 +198,11 @@ public async Task TestAuthenticatorOriginsFail(string origin, string expectedOri UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -411,13 +407,11 @@ public async Task TestAuthenticatorAttestationResponseInvalidType() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -483,13 +477,11 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawId(byte[] value) UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -553,13 +545,11 @@ public async Task TestAuthenticatorAttestationResponseInvalidRawType() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -630,13 +620,11 @@ public async Task TestAuthenticatorAttestationResponseRpidMismatch() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -709,13 +697,11 @@ public async Task TestAuthenticatorAttestationResponseNotUserPresentAsync() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -788,13 +774,11 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyRequir UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -866,13 +850,11 @@ public async Task TestAuthenticatorAttestationResponseBackupEligiblePolicyDisall UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -944,13 +926,11 @@ public async Task TestAuthenticatorAttestationResponseNoAttestedCredentialData() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -1022,13 +1002,11 @@ public async Task TestAuthenticatorAttestationResponseUnknownAttestationType() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -1100,13 +1078,11 @@ public async Task TestAuthenticatorAttestationResponseNotUniqueCredId() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -1177,13 +1153,11 @@ public async Task TestAuthenticatorAttestationResponseUVRequired() UserVerification = UserVerificationRequirement.Required, }, Challenge = challenge, - ErrorMessage = "", PubKeyCredParams = [ new PubKeyCredParam(COSE.Algorithm.ES256) ], Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", diff --git a/Test/ExistingU2fRegistrationDataTests.cs b/Test/ExistingU2fRegistrationDataTests.cs index 4a61e46e..55f2f80e 100644 --- a/Test/ExistingU2fRegistrationDataTests.cs +++ b/Test/ExistingU2fRegistrationDataTests.cs @@ -55,9 +55,9 @@ public async Task TestFido2AssertionWithExistingU2fRegistrationWithAppId() Origins = new HashSet { "https://localhost:44336" } //data was generated with this origin }); - var res = await fido2.MakeAssertionAsync(authResponse, options, publicKey.Encode(), null, 0, null); + var credential = await fido2.MakeAssertionAsync(authResponse, options, publicKey.Encode(), null, 0, null); - Assert.Equal("ok", res.Status); + Assert.NotEmpty(credential.CredentialId); } public static CborMap CreatePublicKeyFromU2fRegistrationData(byte[] keyHandleData, byte[] publicKeyData) diff --git a/Test/Fido2Tests.cs b/Test/Fido2Tests.cs index afb9163b..a6b578d7 100644 --- a/Test/Fido2Tests.cs +++ b/Test/Fido2Tests.cs @@ -149,7 +149,7 @@ public Attestation() idFidoGenCeAaGuidExt = new X509Extension(oidIdFidoGenCeAaGuid, _asnEncodedAaguid, false); } - public async Task MakeAttestationResponseAsync() + public async Task MakeAttestationResponseAsync() { _attestationObject.Set("authData", new CborByteString(_authData.ToByteArray())); @@ -189,7 +189,6 @@ public async Task MakeAttestationResponseAsync() UserVerification = UserVerificationRequirement.Discouraged, }, Challenge = _challenge, - ErrorMessage = "", PubKeyCredParams = new List() { new(COSE.Algorithm.ES256), @@ -206,7 +205,6 @@ public async Task MakeAttestationResponseAsync() new(COSE.Algorithm.ES256K), }, Rp = new PublicKeyCredentialRpEntity(rp, rp, ""), - Status = "ok", User = new Fido2User { Name = "testuser", @@ -814,8 +812,6 @@ public async Task TestAssertionResponse() avr = await MakeAssertionResponseAsync(type, alg); } - Assert.Null(avr.ErrorMessage); - Assert.Equal("ok", avr.Status); Assert.Equal([0xf1, 0xd0], avr.CredentialId); Assert.Equal("1", avr.SignCount.ToString("X")); }