public RawAuthenticatorMakeCredentialOptions(AuthenticatorMakeCredentialOptions makeOptions)
        {
            ExcludeCredentialsList = new RawCredentialsList(makeOptions.ExcludeCredentials);

            if (makeOptions.ExcludeCredentialsEx?.Count > 0)
            {
                _excludeCredentialsExList = new RawCredentialExList(makeOptions.ExcludeCredentialsEx);
                ExcludeCredentialsExListPtr = Marshal.AllocHGlobal(Marshal.SizeOf<RawCredentialExList>());
                Marshal.StructureToPtr(_excludeCredentialsExList, ExcludeCredentialsExListPtr, false);
            }

            CancellationId = IntPtr.Zero;
            if (makeOptions.CancellationId.HasValue)
            {
                CancellationId = Marshal.AllocHGlobal(Marshal.SizeOf<Guid>());
                Marshal.StructureToPtr(makeOptions.CancellationId.Value, CancellationId, false);
            }

            TimeoutMilliseconds = makeOptions.TimeoutMilliseconds;
            AuthenticatorAttachment = makeOptions.AuthenticatorAttachment;
            UserVerificationRequirement = makeOptions.UserVerificationRequirement;
            AttestationConveyancePreference = makeOptions.AttestationConveyancePreference;
            RequireResidentKey = makeOptions.RequireResidentKey;

            Extensions = new RawWebauthnExtensions { Count = 0, Extensions = IntPtr.Zero }; //TODO
        }
Пример #2
0
        /// <summary>
        /// Returns CredentialCreateOptions including a challenge to be sent to the browser/authr to create new credentials
        /// </summary>
        /// <returns></returns>
        /// <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>
        /// <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>
        public CredentialCreateOptions RequestNewCredential(
            Fido2User user,
            List <PublicKeyCredentialDescriptor> excludeCredentials,
            AuthenticatorSelection authenticatorSelection,
            AttestationConveyancePreference attestationPreference,
            AuthenticationExtensionsClientInputs extensions = null)
        {
            var challenge = new byte[_config.ChallengeSize];

            _crypto.GetBytes(challenge);

            var options = CredentialCreateOptions.Create(_config, challenge, user, authenticatorSelection, attestationPreference, excludeCredentials, extensions);

            return(options);
        }
        public static string MakeWebAuthnAttestationRequest(Fido2Configuration fido2Config, byte[] challenge, LoginUsr LUser, List <PublicKeyCredentialDescriptor> excludedCredentials)
        {
            string    usrId    = LUser.UsrId.ToString();
            string    usrIdB64 = System.Convert.ToBase64String(usrId.ToUtf8ByteArray());
            Fido2User user     = new Fido2User
            {
                DisplayName = LUser.UsrName,
                /* must be restricted to no more than than 64 for device like yubikey as it would fail without reason */
                //Name = (Guid.NewGuid().ToString() + " " + DateTime.UtcNow.ToString("o")).Left(64),
                //Id= Guid.NewGuid().ToString().ToUtf8ByteArray()
                Name = LUser.LoginName,
                Id   = usrIdB64.ToUtf8ByteArray()
            };
            AuthenticatorSelection authenticatorSelection = new AuthenticatorSelection
            {
                RequireResidentKey = false,
                UserVerification   = UserVerificationRequirement.Discouraged,
                //                 AuthenticatorAttachment = AuthenticatorAttachment.Platform,
            };
            AttestationConveyancePreference      attConveyancePreference = AttestationConveyancePreference.None;
            AuthenticationExtensionsClientInputs clientExtensions        = new AuthenticationExtensionsClientInputs
            {
                Extensions = true,
                SimpleTransactionAuthorization = string.Format("you are registering to {0}", fido2Config.ServerName),
                Location = true,
                UserVerificationMethod = true,
                BiometricAuthenticatorPerformanceBounds = new AuthenticatorBiometricPerfBounds
                {
                    FAR = float.MaxValue,
                    FRR = float.MaxValue
                }
            };

            var fido2 = new Fido2(fido2Config);

            // must do this for the verification to work
            var options = fido2.RequestNewCredential(user, excludedCredentials, authenticatorSelection, attConveyancePreference, clientExtensions);

            // the challenge is random byte but we need more info, replace it
            options.Challenge = challenge;
            var createRequest = Fido2NetLib.CredentialCreateOptions.Create(fido2Config
                                                                           , challenge, user, authenticatorSelection, attConveyancePreference
                                                                           , excludedCredentials != null && excludedCredentials.Count > 0 ? excludedCredentials : null
                                                                           , clientExtensions);
            string createRequestJson = options.ToJson();

            return(createRequestJson);
        }
Пример #4
0
 /// <summary>
 /// Create static method implementation
 /// </summary>
 public static RegisterCredentialOptions Create(Fido2Configuration config, byte[] challenge, Fido2User user, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationConveyancePreference, List <PublicKeyCredentialDescriptor> excludeCredentials, AuthenticationExtensionsClientInputs extensions)
 {
     return(new RegisterCredentialOptions
     {
         Status = "ok",
         ErrorMessage = string.Empty,
         Challenge = challenge,
         Rp = new PublicKeyCredentialRpEntity(config.ServerDomain, config.ServerName, config.ServerIcon),
         Timeout = config.Timeout,
         User = user,
         PubKeyCredParams = new List <PubKeyCredParam>()
         {
             // Add additional as appropriate
             ES256,
             RS256,
             PS256,
             ES384,
             RS384,
             PS384,
             ES512,
             RS512,
             PS512,
         },
         AuthenticatorSelection = authenticatorSelection,
         Attestation = attestationConveyancePreference,
         ExcludeCredentials = excludeCredentials ?? new List <PublicKeyCredentialDescriptor>(),
         Extensions = extensions
     });
 }
Пример #5
0
        public JsonResult MakeCredentialOptions([FromForm] string username, [FromForm] string attType, [FromForm] string authType, [FromForm] bool requireResidentKey, [FromForm] string userVerification)
        {
            try
            {
                // 1. Get user from DB by username (in our example, auto create missing users)
                var user = DemoStorage.GetOrAddUser(username, () => new User
                {
                    DisplayName = "Display " + username,
                    Name        = username,
                    Id          = Encoding.UTF8.GetBytes(username) // byte representation of userID is required
                });

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

                // 3. Create options
                var authenticatorSelection = new AuthenticatorSelection
                {
                    AuthenticatorAttachment = !string.IsNullOrEmpty(authType) ? AuthenticatorAttachment.Parse(authType) : null,
                    RequireResidentKey      = requireResidentKey,
                    UserVerification        = UserVerificationRequirement.Parse(userVerification)
                };
                var options = _lib.RequestNewCredential(user, existingKeys, authenticatorSelection, AttestationConveyancePreference.Parse(attType));

                // 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)
                }));
            }
        }
Пример #6
0
        /// <summary>
        /// Returns CredentialCreateOptions including a challenge to be sent to the browser/authr to create new credentials
        /// </summary>
        /// <returns></returns>
        /// <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>
        /// <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>
        public CredentialCreateOptions RequestNewCredential(User user, List <PublicKeyCredentialDescriptor> excludeCredentials, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationPreference)
        {
            // note: I have no idea if this crypto is ok...
            var challenge = new byte[Config.ChallengeSize];

            _crypto.GetBytes(challenge);

            var options = CredentialCreateOptions.Create(Config, challenge, user, authenticatorSelection, attestationPreference, excludeCredentials);

            return(options);
        }
 public static CredentialCreateOptions Create(Configuration config, byte[] challenge, User user, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationConveyancePreference, List <PublicKeyCredentialDescriptor> excludeCredentials)
 {
     return(new CredentialCreateOptions
     {
         Status = "ok",
         ErrorMessage = string.Empty,
         Challenge = challenge,
         Rp = new Rp(config.ServerDomain, config.ServerName),
         Timeout = config.Timeout,
         User = user,
         PubKeyCredParams = new List <PubKeyCredParam>()
         {
             // Add additional as appropriate
             ES256,
             RS256,
             PS256,
             ES384,
             RS384,
             PS384,
             ES512,
             RS512,
             PS512,
             RS1
         },
         AuthenticatorSelection = authenticatorSelection,
         Attestation = attestationConveyancePreference,
         ExcludeCredentials = excludeCredentials ?? new List <PublicKeyCredentialDescriptor>()
     });
 }
        public static PublicKeyCredentialCreationOptions ConvertToPublicKeyCredentialCreationOptions(IFido2Client fido2Client,
                                                                                                     ServerPublicKeyCredentialCreationOptionsResponse response)
        {
            PublicKeyCredentialCreationOptions.Builder builder = new PublicKeyCredentialCreationOptions.Builder();

            string name = response.Rp.Name;
            PublicKeyCredentialRpEntity entity = new PublicKeyCredentialRpEntity(name, name, null);

            builder.SetRp(entity);

            string id = response.User.Id;

            try
            {
                builder.SetUser(new PublicKeyCredentialUserEntity(id, System.Text.Encoding.UTF8.GetBytes(id)));
            }
            catch (UnsupportedEncodingException e)
            {
                Log.Error(Tag, e.Message, e);
            }

            builder.SetChallenge(ByteUtils.Base64ToByte(response.Challenge));

            if (response.PubKeyCredParams != null)
            {
                List <PublicKeyCredentialParameters>  parameters = new List <PublicKeyCredentialParameters>();
                ServerPublicKeyCredentialParameters[] serverPublicKeyCredentialParameters = response.PubKeyCredParams;
                foreach (ServerPublicKeyCredentialParameters param in serverPublicKeyCredentialParameters)
                {
                    try
                    {
                        PublicKeyCredentialParameters parameter = new PublicKeyCredentialParameters(
                            PublicKeyCredentialType.PublicKey, Algorithm.FromCode(param.Alg));
                        parameters.Add(parameter);
                    }
                    catch (System.Exception e)
                    {
                        Log.Error(Tag, e.Message, e);
                    }
                }
                builder.SetPubKeyCredParams(parameters);
            }

            if (response.ExcludeCredentials != null)
            {
                List <PublicKeyCredentialDescriptor>  descriptors       = new List <PublicKeyCredentialDescriptor>();
                ServerPublicKeyCredentialDescriptor[] serverDescriptors = response.ExcludeCredentials;
                foreach (ServerPublicKeyCredentialDescriptor desc in serverDescriptors)
                {
                    List <AuthenticatorTransport> transports = new List <AuthenticatorTransport>();
                    if (desc.Transports != null)
                    {
                        try
                        {
                            transports.Add(AuthenticatorTransport.FromValue(desc.Transports));
                        }
                        catch (System.Exception e)
                        {
                            Log.Error(Tag, e.Message, e);
                        }
                    }
                    PublicKeyCredentialDescriptor descriptor = new PublicKeyCredentialDescriptor(
                        PublicKeyCredentialType.PublicKey, ByteUtils.Base64ToByte(desc.Id), transports);
                    descriptors.Add(descriptor);
                }
                builder.SetExcludeList(descriptors);
            }

            Attachment attachment = null;

            if (response.AuthenticatorSelection != null)
            {
                ServerAuthenticatorSelectionCriteria selectionCriteria = response.AuthenticatorSelection;
                if (selectionCriteria.AuthenticatorAttachment != null)
                {
                    try
                    {
                        attachment = Attachment.FromValue(selectionCriteria.AuthenticatorAttachment);
                    }
                    catch (System.Exception e)
                    {
                        Log.Error(Tag, e.Message, e);
                    }
                }

                bool residentKey = selectionCriteria.IsRequireResidentKey;

                UserVerificationRequirement requirement = null;
                if (selectionCriteria.UserVerification != null)
                {
                    try
                    {
                        requirement = UserVerificationRequirement.FromValue(selectionCriteria.UserVerification);
                    }
                    catch (System.Exception e)
                    {
                        Log.Error(Tag, e.Message, e);
                    }
                }

                AuthenticatorSelectionCriteria fido2Selection =
                    new AuthenticatorSelectionCriteria(attachment, (Java.Lang.Boolean)residentKey, requirement);
                builder.SetAuthenticatorSelection(fido2Selection);
            }

            // attestation
            if (response.Attestation != null)
            {
                try
                {
                    AttestationConveyancePreference preference =
                        AttestationConveyancePreference.FromValue(response.Attestation);
                    builder.SetAttestation(preference);
                }
                catch (System.Exception e)
                {
                    Log.Error(Tag, e.Message, e);
                }
            }

            Dictionary <string, Java.Lang.Object> extensions = new Dictionary <string, Java.Lang.Object>();

            if (response.Extensions != null)
            {
                extensions.AddRangeOverride(response.Extensions);
            }

            // Specify a platform authenticator and related extension items. You can specify a platform
            // authenticator or not as needed.
            if (Attachment.Platform.Equals(attachment))
            {
                UseSelectedPlatformAuthenticator(fido2Client, extensions);
            }
            builder.SetExtensions(extensions);
            builder.SetTimeoutSeconds((Java.Lang.Long)response.Timeout);
            return(builder.Build());
        }