public Result <CredentialCreateOptions> MakeCredentialOptions(int userId, string username, string displayName, long loginId)
        {
            var user = new Fido2User
            {
                Name        = username,
                DisplayName = displayName,
                Id          = BitConverter.GetBytes(userId)
            };

            var authenticatorSelection = new AuthenticatorSelection
            {
                UserVerification = UserVerificationRequirement.Required
            };

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

            var options = _fido2.RequestNewCredential(user, null, authenticatorSelection, AttestationConveyancePreference.Direct);

            _cache.Set($"CredentialOptions:{loginId}", options, _options.Value.ChallengeExpiration);

            _logger.LogInformation($"Created options for login {loginId}");

            return(Result.Success(options));
        }
        public 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})";
                }

                // 1. Get user from DB by username (in our example, auto create missing users)
                var user = DemoStorage.GetOrAddUser(username, () => new Fido2User
                {
                    DisplayName = displayName,
                    Name        = username,
                    Id          = Encoding.UTF8.GetBytes(username) // byte representation of userID is required
                });

                // 2. Get user existing keys by username
                var existingKeys = DemoStorage.GetCredentialsByUser(user).Select(c => c.Descriptor).ToList();

                // 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,
                    UserVerificationMethod = true,
                };

                var options = _fido2.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)
                }));
            }
        }
示例#3
0
        public async Task <CredentialCreateOptions> StartWebAuthnRegistrationAsync(User user)
        {
            var providers = user.GetTwoFactorProviders();

            if (providers == null)
            {
                providers = new Dictionary <TwoFactorProviderType, TwoFactorProvider>();
            }
            var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);

            if (provider == null)
            {
                provider = new TwoFactorProvider
                {
                    Enabled = false
                };
            }
            if (provider.MetaData == null)
            {
                provider.MetaData = new Dictionary <string, object>();
            }

            var fidoUser = new Fido2User
            {
                DisplayName = user.Name,
                Name        = user.Email,
                Id          = user.Id.ToByteArray(),
            };

            var excludeCredentials = provider.MetaData
                                     .Where(k => k.Key.StartsWith("Key"))
                                     .Select(k => new TwoFactorProvider.WebAuthnData((dynamic)k.Value).Descriptor)
                                     .ToList();

            var authenticatorSelection = new AuthenticatorSelection
            {
                AuthenticatorAttachment = null,
                RequireResidentKey      = false,
                UserVerification        = UserVerificationRequirement.Discouraged
            };
            var options = _fido2.RequestNewCredential(fidoUser, excludeCredentials, authenticatorSelection, AttestationConveyancePreference.None);

            provider.MetaData["pending"] = options.ToJson();
            providers[TwoFactorProviderType.WebAuthn] = provider;
            user.SetTwoFactorProviders(providers);
            await UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, false);

            return(options);
        }
示例#4
0
        public ActionResult CredentialOptions([FromBody] RegisterModel model)
        {
            var user = new Fido2User
            {
                DisplayName = $"{model.FirstName} {model.LastName}",
                Name        = model.Email,
                Id          = Encoding.UTF8.GetBytes(model.Email)
            };

            var options = fido2.RequestNewCredential(user, new List <PublicKeyCredentialDescriptor>());

            HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson());

            return(Json(options));
        }
示例#5
0
        public async Task <CredentialCreateOptions> RequestCreation(string userId)
        {
            await using var dbContext = _contextFactory.CreateContext();
            var user = await dbContext.Users.Include(applicationUser => applicationUser.Fido2Credentials)
                       .FirstOrDefaultAsync(applicationUser => applicationUser.Id == userId);

            if (user == null)
            {
                return(null);
            }

            // 2. Get user existing keys by username
            var existingKeys =
                user.Fido2Credentials
                .Where(credential => credential.Type == Fido2Credential.CredentialType.FIDO2)
                .Select(c => c.GetFido2Blob().Descriptor).ToList();

            // 3. Create options
            var authenticatorSelection = new AuthenticatorSelection
            {
                RequireResidentKey = false,
                UserVerification   = UserVerificationRequirement.Preferred
            };

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

            var options = _fido2.RequestNewCredential(
                new Fido2User()
            {
                DisplayName = user.UserName, Name = user.UserName, Id = user.Id.ToBytesUTF8()
            },
                existingKeys, authenticatorSelection, AttestationConveyancePreference.None, exts);

            // options.Rp = new PublicKeyCredentialRpEntity(Request.Host.Host, options.Rp.Name, "");
            CreationStore.AddOrReplace(userId, options);
            return(options);
        }
示例#6
0
        /// <summary>
        /// <para>注册:创建证明选项</para>
        /// <param name="opts"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public CredentialCreateOptions MakeCredentialOptions(User user, MakeCredentialParams opts)
        {
            var fidoUser = opts.GetFido2UserByUser();
            // Create options
            var exts = new AuthenticationExtensionsClientInputs()
            {
                Extensions             = true,
                UserVerificationMethod = true,
            };
            var existingKeys = GetPublicKeyCredentialDescriptors(user.UserId);

            var options = _fido2.RequestNewCredential(
                fidoUser,
                existingKeys,
                opts.AuthenticatorSelection,
                opts.Attestation,
                exts);

            distributedCache.SetString(user.UserId.ToString() + "attestationOptions", options.ToJson(), 120);
            return(options);
        }
示例#7
0
        public JsonResult MakeCredentialOptions([FromForm] string username,
                                                [FromForm] string displayName,
                                                [FromForm] string attType,
                                                [FromForm] string authType,
                                                [FromForm] bool requireResidentKey,
                                                [FromForm] string userVerification)
        {
            try
            {
                // user must already exist in Identity
                var identityUser = _users.FindByUsername(username);
                if (identityUser == null)
                {
                    throw new Exception("User not found");
                }

                if (!HttpContext.User.IsAuthenticated())
                {
                    throw new Exception("User is not authenticated");
                }
                ;

                // 1. Get user from DB by username (in our example, auto create missing users)
                var user = PasswordlessStore.GetOrAddUser(username, () => new Fido2User
                {
                    DisplayName = displayName,
                    Name        = username,
                    Id          = Encoding.UTF8.GetBytes(username) // byte representation of userID is required
                });

                // 2. Get user existing keys by username
                var existingKeys = PasswordlessStore.GetCredentialsByUser(user).Select(c => c.Descriptor).ToList();

                // 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 = _fido2.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 <CredentialCreateOptions> > MakeCredentialOptions(CredentialOption option)
        {
            try
            {
                // 註冊使用者
                var user = await context.Members.Where(x => x.UserName == option.UserName).FirstOrDefaultAsync();

                if (user == null)
                {
                    user = new Member
                    {
                        MemberId    = Guid.NewGuid(),
                        UserName    = option.UserName,
                        DisplayName = option.DisplayName,
                        UserId      = Encoding.UTF8.GetBytes(option.UserName)
                    };
                    context.Members.Add(user);
                    await context.SaveChangesAsync();
                }
                var fidoUser = new Fido2User
                {
                    DisplayName = user.DisplayName,
                    Name        = user.UserName,
                    Id          = user.UserId
                };
                // 取得 Key. 排除已經註冊過的 Credentials
                var existingKeys = await context.StoredCredentials.Where(x => x.UserId == user.UserId).Select(x => x.Descriptor).ToListAsync();

                // 建立 Option
                var authenticatorSelection = new AuthenticatorSelection
                {
                    RequireResidentKey = option.RequireResidentKey,
                    UserVerification   = option.UserVerification.ToEnum <UserVerificationRequirement>()
                };
                if (!string.IsNullOrEmpty(option.AuthType))
                {
                    authenticatorSelection.AuthenticatorAttachment = option.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 = _fido2.RequestNewCredential(fidoUser, existingKeys, authenticatorSelection, option.AttType.ToEnum <AttestationConveyancePreference>(), exts);

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

                // 回傳
                return(Ok(options));
            }
            catch (Exception e)
            {
                return(BadRequest(new CredentialCreateOptions {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
示例#9
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
            {
                var applicationUser = await _userManager.GetUserAsync(HttpContext.User);

                // 1. Get user from DB by username (in our example, auto create missing users)
                var user = new Fido2User
                {
                    Id = Encoding.UTF8.GetBytes(applicationUser.Id) // byte representation of userID is required
                };

                // 2. Get user existing keys by username
                // var existingKeys = DemoStorage.GetCredentialsByUser(user).Select(c => c.Descriptor).ToList();
                var existingKeys = new List <PublicKeyCredentialDescriptor>();
                //_fido2CredentialService.GetCredentialsByUser(applicationUser).Select(c => c.Descriptor).ToList();

                // 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 = _fido2.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)
                }));
            }
        }