====== Self-serve password reset implementation ====== ===== New requirements ===== * UUID::Tiny (trunk already requires this) ===== Schema ===== CREATE TABLE actor.usr_password_reset ( uuid TEXT NOT NULL, usr BIGINT NOT NULL REFERENCES actor.usr(id) DEFERRABLE INITIALLY DEFERRED, request_time TIMESTAMP NOT NULL DEFAULT NOW(), has_been_reset BOOLEAN NOT NULL DEFAULT false ); ===== Fieldmapper ===== ===== OU settings, with defaults ===== * Password reset time-to-live: 24 hours? * Number of concurrent active password reset requests for all users: 1000? * Number of concurrent active password reset requests for one user: 3? ===== Overview ===== - User forgets password when prompted to log in; clicks "Forgot my password" link. - Form prompts user for one of three types of identification: * User name (unique) * Barcode (unique) * Email address? Not unique. Problem if multiple people share the same email address - whose password is getting reset? - Upon submission, page responds that if there is a match for the provided identification and an email address on file for the corresponding user, an email will be sent with further instructions for recovering your password. Otherwise, [ local customization here - might be "Visit your local library" or whatever ] - Assuming there is a match: - Check how many currently active entries in the actor.usr_password_reset table exist (currently active = current password_reset_TTL (WHERE request_time > NOW() - password_reset_TTL) AND has_been_reset IS FALSE) * Log a warning if > 75% global_threshold * Log an error and throttle reset requests to 1 per minute if > global_threshold - Check how many currently active entries in the actor.usr_password_reset table match usr * Log an error if > usr_threshold and do not generate a reset - Generate a random UUID: create_uuid_as_string(UUID_V4) - don't want to base this on the identifiers, as those are entirely predictable; rand() is not strong but good enough? * Create an entry in actor.usr_password_reset - Send an email to the email address on file: actor.usr.email * "Someone has requested to have the password for your account at actor.usr.home_ou.name reset. If this was not you, please disregard this email message. If this was you, please open the following link in a Web browser to continue the password reset process: https://foobar/forgot-password/$uuid - Listen for the magic URL on HTTPS (because we want the new password encrypted when it goes over the wire) * We should monitor how many requests are being fired towards the magic URL root to prevent rainbow attacks, but kind of need that globally * If we get a hit on an active entry in actor.usr_password_reset, display a Web form that gives the user the chance to set their password * Password must be entered twice and must match * Password should be subject to aou setting's password complexity rules