Exemple #1
0
        private List <Tuple <string, TwoFactorProvider.U2fMetaData> > LoadKeys(TwoFactorProvider provider)
        {
            var keys = new List <Tuple <string, TwoFactorProvider.U2fMetaData> >();

            if (!HasProperMetaData(provider))
            {
                return(keys);
            }

            // Support up to 5 keys
            for (var i = 1; i <= 5; i++)
            {
                var keyName = $"Key{i}";
                if (provider.MetaData.ContainsKey(keyName))
                {
                    var key = new TwoFactorProvider.U2fMetaData((dynamic)provider.MetaData[keyName]);
                    if (!key?.Compromised ?? false)
                    {
                        keys.Add(new Tuple <string, TwoFactorProvider.U2fMetaData>(keyName, key));
                    }
                }
            }

            return(keys);
        }
        public async Task <bool> TwoFactorIsEnabledAsync(ITwoFactorProvidersUser user)
        {
            var providers = user.GetTwoFactorProviders();

            if (providers == null)
            {
                return(false);
            }

            foreach (var p in providers)
            {
                if (p.Value?.Enabled ?? false)
                {
                    if (!TwoFactorProvider.RequiresPremium(p.Key))
                    {
                        return(true);
                    }
                    if (await CanAccessPremium(user))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #3
0
        public bool TwoFactorIsEnabled()
        {
            var providers = GetTwoFactorProviders();

            if (providers == null)
            {
                return(false);
            }

            return(providers.Any(p => (p.Value?.Enabled ?? false) && (Premium || !TwoFactorProvider.RequiresPremium(p.Key))));
        }
Exemple #4
0
        public bool TwoFactorProviderIsEnabled(TwoFactorProviderType provider)
        {
            var providers = GetTwoFactorProviders();

            if (providers == null || !providers.ContainsKey(provider))
            {
                return(false);
            }

            return(providers[provider].Enabled && (Premium || !TwoFactorProvider.RequiresPremium(provider)));
        }
        public TwoFactorProviderResponseModel(TwoFactorProviderType type, TwoFactorProvider provider)
            : base(ResponseObj)
        {
            if (provider == null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            Enabled = provider.Enabled;
            Type    = type;
        }
Exemple #6
0
        private async Task <Dictionary <string, object> > BuildTwoFactorParams(User user, TwoFactorProviderType type,
                                                                               TwoFactorProvider provider)
        {
            if (!user.TwoFactorProviderIsEnabled(type))
            {
                return(null);
            }

            switch (type)
            {
            case TwoFactorProviderType.Duo:
            case TwoFactorProviderType.U2f:
            case TwoFactorProviderType.Email:
            case TwoFactorProviderType.YubiKey:
                var token = await _userManager.GenerateTwoFactorTokenAsync(user, type.ToString());

                if (type == TwoFactorProviderType.Duo)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Host"] = provider.MetaData["Host"],
                        ["Signature"] = token
                    });
                }
                else if (type == TwoFactorProviderType.U2f)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Challenges"] = token
                    });
                }
                else if (type == TwoFactorProviderType.Email)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Email"] = RedactEmail((string)provider.MetaData["Email"])
                    });
                }
                else if (type == TwoFactorProviderType.YubiKey)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Nfc"] = (bool)provider.MetaData["Nfc"]
                    });
                }
                return(null);

            default:
                return(null);
            }
        }
Exemple #7
0
        public TwoFactorU2fResponseModel(User user, TwoFactorProvider provider, U2fRegistration registration = null)
            : base("twoFactorU2f")
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            if (registration != null)
            {
                Challenge = new ChallengeModel(user, registration);
            }
            Enabled = provider?.Enabled ?? false;
        }
Exemple #8
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);
        }
        public async Task <bool> TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider, ITwoFactorProvidersUser user)
        {
            var providers = user.GetTwoFactorProviders();

            if (providers == null || !providers.ContainsKey(provider) || !providers[provider].Enabled)
            {
                return(false);
            }

            if (!TwoFactorProvider.RequiresPremium(provider))
            {
                return(true);
            }

            return(await CanAccessPremium(user));
        }
        private void Build(TwoFactorProvider provider)
        {
            if (provider?.MetaData != null && provider.MetaData.Count > 0)
            {
                Enabled = provider.Enabled;

                if (provider.MetaData.ContainsKey("Host"))
                {
                    Host = (string)provider.MetaData["Host"];
                }
                if (provider.MetaData.ContainsKey("SKey"))
                {
                    SecretKey = (string)provider.MetaData["SKey"];
                }
                if (provider.MetaData.ContainsKey("IKey"))
                {
                    IntegrationKey = (string)provider.MetaData["IKey"];
                }
            }
            else
            {
                Enabled = false;
            }
        }
Exemple #11
0
        private async Task <Dictionary <string, object> > BuildTwoFactorParams(Organization organization, User user,
                                                                               TwoFactorProviderType type, TwoFactorProvider provider)
        {
            switch (type)
            {
            case TwoFactorProviderType.Duo:
            case TwoFactorProviderType.WebAuthn:
            case TwoFactorProviderType.Email:
            case TwoFactorProviderType.YubiKey:
                if (!(await _userService.TwoFactorProviderIsEnabledAsync(type, user)))
                {
                    return(null);
                }

                var token = await _userManager.GenerateTwoFactorTokenAsync(user,
                                                                           CoreHelpers.CustomProviderName(type));

                if (type == TwoFactorProviderType.Duo)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Host"] = provider.MetaData["Host"],
                        ["Signature"] = token
                    });
                }
                else if (type == TwoFactorProviderType.WebAuthn)
                {
                    if (token == null)
                    {
                        return(null);
                    }

                    return(JsonSerializer.Deserialize <Dictionary <string, object> >(token));
                }
                else if (type == TwoFactorProviderType.Email)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Email"] = token
                    });
                }
                else if (type == TwoFactorProviderType.YubiKey)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Nfc"] = (bool)provider.MetaData["Nfc"]
                    });
                }
                return(null);

            case TwoFactorProviderType.OrganizationDuo:
                if (await _organizationDuoWebTokenProvider.CanGenerateTwoFactorTokenAsync(organization))
                {
                    return(new Dictionary <string, object>
                    {
                        ["Host"] = provider.MetaData["Host"],
                        ["Signature"] = await _organizationDuoWebTokenProvider.GenerateAsync(organization, user)
                    });
                }
                return(null);

            default:
                return(null);
            }
        }
Exemple #12
0
 private bool HasProperMetaData(TwoFactorProvider provider)
 {
     return(provider?.MetaData?.Any() ?? false);
 }
Exemple #13
0
 private bool HasProperMetaData(TwoFactorProvider provider)
 {
     return((provider?.MetaData?.Count ?? 0) > 0);
 }
        public async Task <bool> CompleteU2fRegistrationAsync(User user, int id, string name, string deviceResponse)
        {
            if (string.IsNullOrWhiteSpace(deviceResponse))
            {
                return(false);
            }

            var challenges = await _u2fRepository.GetManyByUserIdAsync(user.Id);

            if (!challenges?.Any() ?? true)
            {
                return(false);
            }

            var registerResponse = BaseModel.FromJson <RegisterResponse>(deviceResponse);

            try
            {
                var challenge  = challenges.OrderBy(i => i.Id).Last(i => i.KeyHandle == null);
                var startedReg = new StartedRegistration(challenge.Challenge, challenge.AppId);
                var reg        = U2fLib.FinishRegistration(startedReg, registerResponse);

                await _u2fRepository.DeleteManyByUserIdAsync(user.Id);

                // Add device
                var providers = user.GetTwoFactorProviders();
                if (providers == null)
                {
                    providers = new Dictionary <TwoFactorProviderType, TwoFactorProvider>();
                }
                var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
                if (provider == null)
                {
                    provider = new TwoFactorProvider();
                }
                if (provider.MetaData == null)
                {
                    provider.MetaData = new Dictionary <string, object>();
                }

                if (provider.MetaData.Count >= 5)
                {
                    // Can only register up to 5 keys
                    return(false);
                }

                var keyId = $"Key{id}";
                if (provider.MetaData.ContainsKey(keyId))
                {
                    provider.MetaData.Remove(keyId);
                }

                provider.Enabled = true;
                provider.MetaData.Add(keyId, new TwoFactorProvider.U2fMetaData
                {
                    Name        = name,
                    KeyHandle   = reg.KeyHandle == null ? null : Utils.ByteArrayToBase64String(reg.KeyHandle),
                    PublicKey   = reg.PublicKey == null ? null : Utils.ByteArrayToBase64String(reg.PublicKey),
                    Certificate = reg.AttestationCert == null ? null : Utils.ByteArrayToBase64String(reg.AttestationCert),
                    Compromised = false,
                    Counter     = reg.Counter
                });

                if (providers.ContainsKey(TwoFactorProviderType.U2f))
                {
                    providers.Remove(TwoFactorProviderType.U2f);
                }

                providers.Add(TwoFactorProviderType.U2f, provider);
                user.SetTwoFactorProviders(providers);
                await UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.U2f);

                return(true);
            }
            catch (U2fException e)
            {
                Logger.LogError(e, "Complete U2F registration error.");
                return(false);
            }
        }
Exemple #15
0
        public async Task<TwoFactorResponseModel> GetTwoFactor(string masterPasswordHash, TwoFactorProvider provider)
        {
            var user = _currentContext.User;
            if(!await _userManager.CheckPasswordAsync(user, masterPasswordHash))
            {
                await Task.Delay(2000);
                throw new BadRequestException("MasterPasswordHash", "Invalid password.");
            }

            await _userService.GetTwoFactorAsync(user, provider);

            var response = new TwoFactorResponseModel(user);
            return response;
        }
 private bool HasProperMetaData(TwoFactorProvider provider)
 {
     return(provider?.MetaData != null && provider.MetaData.ContainsKey("Email") &&
            !string.IsNullOrWhiteSpace((string)provider.MetaData["Email"]));
 }
Exemple #17
0
        public string ProvideScript(Func <IDbCommand> commandFactory)
        {
            var cmd = commandFactory();

            cmd.CommandText = "SELECT Id, TwoFactorProviders FROM [dbo].[User] WHERE TwoFactorProviders IS NOT NULL";

            var users = new List <object>();

            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var id = reader.GetGuid(0);
                    var twoFactorProviders = reader.GetString(1);

                    if (string.IsNullOrWhiteSpace(twoFactorProviders))
                    {
                        continue;
                    }

                    var providers = JsonConvert.DeserializeObject <Dictionary <TwoFactorProviderType, TwoFactorProvider> >(twoFactorProviders);

                    if (!providers.ContainsKey(TwoFactorProviderType.U2f))
                    {
                        continue;
                    }

                    var u2fProvider = providers[TwoFactorProviderType.U2f];

                    if (!u2fProvider.Enabled || !HasProperMetaData(u2fProvider))
                    {
                        continue;
                    }

                    var u2fKeys      = LoadKeys(u2fProvider);
                    var webAuthnKeys = u2fKeys.Select(key => (key.Item1, key.Item2.ToWebAuthnData()));

                    var webAuthnProvider = new TwoFactorProvider
                    {
                        Enabled  = true,
                        MetaData = webAuthnKeys.ToDictionary(x => x.Item1, x => (object)x.Item2)
                    };

                    providers[TwoFactorProviderType.WebAuthn] = webAuthnProvider;

                    users.Add(new User
                    {
                        Id = id,
                        TwoFactorProviders = JsonConvert.SerializeObject(providers),
                    });
                }
            }

            foreach (User user in users)
            {
                var command = commandFactory();

                command.CommandText = "UPDATE [dbo].[User] SET TwoFactorProviders = @twoFactorProviders WHERE Id = @id";
                var idParameter = command.CreateParameter();
                idParameter.ParameterName = "@id";
                idParameter.Value         = user.Id;

                var twoFactorParameter = command.CreateParameter();
                twoFactorParameter.ParameterName = "@twoFactorProviders";
                twoFactorParameter.Value         = user.TwoFactorProviders;

                command.Parameters.Add(idParameter);
                command.Parameters.Add(twoFactorParameter);

                command.ExecuteNonQuery();
            }

            return("");
        }
        private async Task <Dictionary <string, object> > BuildTwoFactorParams(Organization organization, User user,
                                                                               TwoFactorProviderType type, TwoFactorProvider provider)
        {
            switch (type)
            {
            case TwoFactorProviderType.Duo:
            case TwoFactorProviderType.U2f:
            case TwoFactorProviderType.Email:
            case TwoFactorProviderType.YubiKey:
                if (!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
                {
                    return(null);
                }

                var token = await _userManager.GenerateTwoFactorTokenAsync(user, type.ToString());

                if (type == TwoFactorProviderType.Duo)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Host"] = provider.MetaData["Host"],
                        ["Signature"] = token
                    });
                }
                else if (type == TwoFactorProviderType.U2f)
                {
                    // TODO: Remove "Challenges" in a future update. Deprecated.
                    var tokens = token?.Split('|');
                    return(new Dictionary <string, object>
                    {
                        ["Challenge"] = tokens != null && tokens.Length > 0 ? tokens[0] : null,
                        ["Challenges"] = tokens != null && tokens.Length > 1 ? tokens[1] : null
                    });
                }
                else if (type == TwoFactorProviderType.Email)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Email"] = RedactEmail((string)provider.MetaData["Email"])
                    });
                }
                else if (type == TwoFactorProviderType.YubiKey)
                {
                    return(new Dictionary <string, object>
                    {
                        ["Nfc"] = (bool)provider.MetaData["Nfc"]
                    });
                }
                return(null);

            case TwoFactorProviderType.OrganizationDuo:
                if (await _organizationDuoWebTokenProvider.CanGenerateTwoFactorTokenAsync(organization))
                {
                    return(new Dictionary <string, object>
                    {
                        ["Host"] = provider.MetaData["Host"],
                        ["Signature"] = await _organizationDuoWebTokenProvider.GenerateAsync(organization, user)
                    });
                }
                return(null);

            default:
                return(null);
            }
        }
        protected async Task BuildTwoFactorResultAsync(User user, Organization organization, T context, bool requires2FABecauseNewDevice)
        {
            var providerKeys = new List <byte>();
            var providers    = new Dictionary <string, Dictionary <string, object> >();

            var enabledProviders = new List <KeyValuePair <TwoFactorProviderType, TwoFactorProvider> >();

            if (organization?.GetTwoFactorProviders() != null)
            {
                enabledProviders.AddRange(organization.GetTwoFactorProviders().Where(
                                              p => organization.TwoFactorProviderIsEnabled(p.Key)));
            }

            if (user.GetTwoFactorProviders() != null)
            {
                foreach (var p in user.GetTwoFactorProviders())
                {
                    if (await _userService.TwoFactorProviderIsEnabledAsync(p.Key, user))
                    {
                        enabledProviders.Add(p);
                    }
                }
            }

            if (!enabledProviders.Any())
            {
                if (!requires2FABecauseNewDevice)
                {
                    await BuildErrorResultAsync("No two-step providers enabled.", false, context, user);

                    return;
                }

                var emailProvider = new TwoFactorProvider
                {
                    MetaData = new Dictionary <string, object> {
                        ["Email"] = user.Email.ToLowerInvariant()
                    },
                    Enabled = true
                };
                enabledProviders.Add(new KeyValuePair <TwoFactorProviderType, TwoFactorProvider>(
                                         TwoFactorProviderType.Email, emailProvider));
                user.SetTwoFactorProviders(new Dictionary <TwoFactorProviderType, TwoFactorProvider>
                {
                    [TwoFactorProviderType.Email] = emailProvider
                });
            }

            foreach (var provider in enabledProviders)
            {
                providerKeys.Add((byte)provider.Key);
                var infoDict = await BuildTwoFactorParams(organization, user, provider.Key, provider.Value);

                providers.Add(((byte)provider.Key).ToString(), infoDict);
            }

            SetTwoFactorResult(context,
                               new Dictionary <string, object>
            {
                { "TwoFactorProviders", providers.Keys },
                { "TwoFactorProviders2", providers }
            });

            if (enabledProviders.Count() == 1 && enabledProviders.First().Key == TwoFactorProviderType.Email)
            {
                // Send email now if this is their only 2FA method
                await _userService.SendTwoFactorEmailAsync(user, requires2FABecauseNewDevice);
            }
        }
Exemple #20
0
 private bool HasProperMetaData(TwoFactorProvider provider)
 {
     return(provider?.MetaData != null && provider.MetaData.ContainsKey("Key1"));
 }
        public async Task <TwoFactorResponseModel> GetTwoFactor(string masterPasswordHash, TwoFactorProvider provider)
        {
            var user = _currentContext.User;

            if (!await _userManager.CheckPasswordAsync(user, masterPasswordHash))
            {
                await Task.Delay(2000);

                throw new BadRequestException("MasterPasswordHash", "Invalid password.");
            }

            await _userService.GetTwoFactorAsync(user, provider);

            var response = new TwoFactorResponseModel(user);

            return(response);
        }