public static bool RequestTicket(string mailAddress)
        {
            mailAddress = mailAddress.Trim();

            if (string.IsNullOrEmpty(mailAddress))
            {
                return(false); // this is the only case when we return false: a _syntactically_invalid_ address
            }

            People concernedPeople = People.FromMail(mailAddress);  // Should result in exactly 1

            if (concernedPeople.Count != 1)
            {
                return(true); // TODO: Prevent registration with duplicate mail addy, or this will cause problems down the road
            }

            Person concernedPerson = concernedPeople[0];

            if (!string.IsNullOrEmpty(concernedPerson.BitIdAddress))
            {
                // Cannot reset password - two factor auth is enabled. Manual intervention required.

                OutboundComm.CreateSecurityNotification(concernedPerson, null, null, string.Empty,
                                                        NotificationResource.Password_CannotReset2FA);
                return(true); // still returning true - the fail info is in mail only
            }


            string resetTicket = SupportFunctions.GenerateSecureRandomKey(16);

            resetTicket = resetTicket.Substring(0, 21);                                                                                   // We're using a 21-character (84-bit) key mostly for UI consistency with the ticket sent in mail, and it's secure enough

            concernedPerson.ResetPasswordTicket = DateTime.UtcNow.AddHours(1).ToString(CultureInfo.InvariantCulture) + "," + resetTicket; // Adds expiry - one hour

            OutboundComm.CreateSecurityNotification(concernedPerson, null, null, resetTicket,
                                                    NotificationResource.Password_ResetOnRequest);

            SwarmopsLog.CreateEntry(null,
                                    new PasswordResetRequestLogEntry(concernedPerson, SupportFunctions.GetRemoteIPAddressChain()));

            return(true);
        }
Esempio n. 2
0
        public static bool PerformReset(string mailAddress, string ticket, string newPassword)
        {
            People people = People.FromMail(mailAddress.Trim());

            if (people.Count != 1)
            {
                return(false);
            }

            Person resetPerson = people[0];

            string[] resetData = resetPerson.ResetPasswordTicket.Split(',');

            if (resetData.Length != 2)
            {
                return(false); // invalid data or no ticket
            }

            // This may throw on invalid data, which will give a slightly different error but that's fine too for now.
            DateTime ticketExpiresUtc = DateTime.Parse(resetData[0]);

            if (DateTime.UtcNow > ticketExpiresUtc)
            {
                // Ticket expired.
                return(false);
            }

            if (ticket != resetData[1])
            {
                // Bad ticket.
                return(false);
            }

            // When we get here, all checks to reset the password have completed. Change the password, log the change,
            // notify the user that the password was changed, set a new authentication cookie, and have the web page
            // redirect to Dashboard (by returning true).

            // Clear password reset ticket

            resetPerson.ResetPasswordTicket = string.Empty;

            // Create lockdown code, notify

            string lockdownTicket = SupportFunctions.GenerateSecureRandomKey(16);

            OutboundComm.CreateSecurityNotification(resetPerson, null, null, lockdownTicket,
                                                    NotificationResource.Password_Changed);
            resetPerson.AccountLockdownTicket = DateTime.UtcNow.AddDays(1).ToString(CultureInfo.InvariantCulture) + "," +
                                                lockdownTicket;

            // Set new password

            resetPerson.SetPassword(newPassword);

            // Log the password reset

            SwarmopsLog.CreateEntry(resetPerson,
                                    new PasswordResetLogEntry(resetPerson, SupportFunctions.GetRemoteIPAddressChain()));

            // Set authentication cookies

            int lastOrgId = resetPerson.LastLogonOrganizationId;

            if (lastOrgId == 0)
            {
                lastOrgId = Organization.SandboxIdentity;
            }

            if (!resetPerson.ParticipatesInOrganizationOrParent(lastOrgId))
            {
                // If the person doesn't have access to the last organization (anymore), log on to Sandbox

                lastOrgId = 1;
            }

            // Set cookies

            FormsAuthentication.SetAuthCookie(Authority.FromLogin(resetPerson).ToEncryptedXml(), true);
            DashboardMessage.Set(Resources.Pages.Security.ResetPassword_Success);

            return(true); // temp

            // do NOT NOT NOT trim password - this is deliberate. Passwords starting/ending in whitespace must be possible
        }