Exemplo n.º 1
0
        public async Task <JsonResult> MakeCredentialOptions([FromForm] string username, [FromForm] string displayName, [FromForm] string attType, [FromForm] string authType, [FromForm] bool requireResidentKey, [FromForm] string userVerification)
        {
            try
            {
                if (string.IsNullOrEmpty(username))
                {
                    username = $"{displayName} (Usernameless user created at {DateTime.UtcNow})";
                }

                var identityUser = await _userManager.FindByEmailAsync(username);

                var user = new Fido2User
                {
                    DisplayName = identityUser.UserName,
                    Name        = identityUser.UserName,
                    Id          = Encoding.UTF8.GetBytes(identityUser.UserName) // byte representation of userID is required
                };

                // 2. Get user existing keys by username
                var items = await _fido2Storage.GetCredentialsByUsername(identityUser.UserName);

                var existingKeys = new List <PublicKeyCredentialDescriptor>();
                foreach (var publicKeyCredentialDescriptor in items)
                {
                    existingKeys.Add(publicKeyCredentialDescriptor.Descriptor);
                }

                // 3. Create options
                var authenticatorSelection = new AuthenticatorSelection
                {
                    RequireResidentKey = requireResidentKey,
                    UserVerification   = userVerification.ToEnum <UserVerificationRequirement>()
                };

                if (!string.IsNullOrEmpty(authType))
                {
                    authenticatorSelection.AuthenticatorAttachment = authType.ToEnum <AuthenticatorAttachment>();
                }

                var exts = new AuthenticationExtensionsClientInputs()
                {
                    Extensions = true, UserVerificationIndex = true, Location = true, UserVerificationMethod = true, BiometricAuthenticatorPerformanceBounds = new AuthenticatorBiometricPerfBounds {
                        FAR = float.MaxValue, FRR = float.MaxValue
                    }
                };

                var options = _lib.RequestNewCredential(user, existingKeys, authenticatorSelection, attType.ToEnum <AttestationConveyancePreference>(), exts);

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

                // 5. return options to client
                return(Json(options));
            }
            catch (Exception e)
            {
                return(Json(new CredentialCreateOptions {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
        public async Task <ActionResult> AssertionOptionsPost([FromForm] string username, [FromForm] string userVerification)
        {
            try
            {
                var identityUser = await _signInManager.GetTwoFactorAuthenticationUserAsync();

                if (identityUser == null)
                {
                    throw new InvalidOperationException(_sharedLocalizer["FIDO2_UNABLE_TO_LOAD_2FA_AUTHENTICATED_USER"]);
                }

                var existingCredentials = new List <PublicKeyCredentialDescriptor>();

                if (!string.IsNullOrEmpty(identityUser.UserName))
                {
                    var user = new Fido2User
                    {
                        DisplayName = identityUser.UserName,
                        Name        = identityUser.UserName,
                        Id          = Encoding.UTF8.GetBytes(identityUser.UserName) // byte representation of userID is required
                    };

                    if (user == null)
                    {
                        throw new ArgumentException(_sharedLocalizer["FIDO2_USERNAME_NOT_REGISTERED"]);
                    }

                    // 2. Get registered credentials from database
                    var items = await _fido2Storage.GetCredentialsByUsername(identityUser.UserName);

                    existingCredentials = items.Select(c => c.Descriptor).ToList();
                }

                var exts = new AuthenticationExtensionsClientInputs()
                {
                    SimpleTransactionAuthorization = "FIDO", GenericTransactionAuthorization = new TxAuthGenericArg {
                        ContentType = "text/plain", Content = new byte[] { 0x46, 0x49, 0x44, 0x4F }
                    }, UserVerificationIndex = true, Location = true, UserVerificationMethod = true
                };

                // 3. Create options
                var uv      = string.IsNullOrEmpty(userVerification) ? UserVerificationRequirement.Discouraged : userVerification.ToEnum <UserVerificationRequirement>();
                var options = _lib.GetAssertionOptions(
                    existingCredentials,
                    uv,
                    exts
                    );

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

                // 5. Return options to client
                return(Json(options));
            }

            catch (Exception e)
            {
                return(Json(new AssertionOptions {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }