def test_unicode_user_inputs(): # test Issue #12 -- don't raise a UnicodeError with unicode user_inputs or # passwords. input_ = u'Фамилия' password = u'pÄssword junkiË' zxcvbn(password, user_inputs=[input_])
def validate(self, password, user=None): def add_list_of_advices(header, comments, advices): if isinstance(advices, str): comments.append(f"{header} : {translate_zxcvbn_text(advices)}") else: for advice in advices: comments.append( f"{header} : {translate_zxcvbn_text(advice)}") return comments user_imputs = [] if user: for value in user.__dict__.values(): user_imputs.append(value) results = zxcvbn(password, user_inputs=user_imputs) password_strengh = results["score"] if password_strengh < self.password_minimal_strengh: crack_time = results["crack_times_display"] offline_time = crack_time["offline_slow_hashing_1e4_per_second"] warnings = results["feedback"]["warning"] advices = results["feedback"]["suggestions"] comments = [] comments.append("{} {}".format( _('Your password is too guessable :'), _('It would take an offline attacker %(time)s to guess it.') % {"time": translate_zxcvbn_time_estimate(offline_time)})) if warnings: comments = add_list_of_advices(_('Warning'), comments, warnings) if advices: comments = add_list_of_advices(_('Advice'), comments, advices) raise ValidationError(comments)
def test_password_strength(password, user_inputs=None): '''Wrapper around zxcvbn.password_strength''' result = zxcvbn(password, user_inputs) result.update({ "feedback": get_feedback(result.get('score'), result.get('sequence')) }) return result
def UpdatePassword(): """ update infos on account """ j = request.get_json() current_user = models.User[current_identity.id] if 'current_password' in j: current_password = j['current_password'] else: return 'Missing current password', 400 if 'new_password' in j: new_password = j['new_password'] else: return json.dumps({'message': 'Missing new password'}), 400 password_test = zxcvbn(new_password) if password_test['score'] < 3: return json.dumps({ 'message': password_test['feedback']['warning'] + ' ' + ''.join(password_test['feedback']['suggestions']) }), 422 if check_password_hash(current_user.password, current_password): enc_password = generate_password_hash(new_password).decode("utf-8") current_user.password = enc_password pony.orm.commit() return json.dumps({'message': 'Password updated'}) else: return json.dumps({'message': 'Bad current password'}), 403
def set_password(): """ Set a new password for the logged in user.. Notes ----- Expects json containing 'password' and 'newPassword' keys. Checks the password is the same as the existing one and that the new password is strong. """ edits = request.get_json() try: old_pass = edits["password"] except KeyError: raise InvalidUsage("Missing old password.", payload={"bad_field": "password"}) try: new_pass = edits["newPassword"] except KeyError: raise InvalidUsage( "Missing new password.", payload={"bad_field": "newPassword"} ) if current_user.is_correct_password(old_pass): if len(new_pass) == 0 or zxcvbn(new_pass)["score"] < 4: raise InvalidUsage( "Password not complex enough.", payload={"bad_field": "newPassword"} ) current_user.password = new_pass db.session.add(current_user) db.session.commit() return jsonify({}), 200 else: raise InvalidUsage("Password incorrect.", payload={"bad_field": "password"})
def validate(self, password, user=None): # NOTE: Keep list of forbidden words in sync with # zxcvbn_ProgressBar_Register.js and # zxcvbn_ProgressBar_Change.js bad_words = ['physio', 'physionet'] try: fname = user.profile.first_names lname = user.profile.last_name except AttributeError: # new user, profile does not yet exist fname = user.first_names lname = user.last_name bad_words += re.findall(_subword, fname) bad_words += re.findall(_subword, lname) bad_words += re.findall(_subword, user.email) bad_words += re.findall(_subword, user.username) info = zxcvbn(password, bad_words) if info['score'] < self.minimum_complexity: raise ValidationError( _("This password is too weak."), code='password_weak_password', )
def validate(self, password, user=None): result = zxcvbn(password) if result['score'] < 4: raise ValidationError(_( 'Password is too weak. Please use stronger password.' ))
def check_password(message): splitMessage = message.content.split(' ') if len(splitMessage) == 1 or Analyze.isHelp(splitMessage[1]): return Analyze.getHelp() # set variables passwd = ' '.join(splitMessage[1:]) result = zxcvbn(passwd) score = result['score'] scoreColor = [0xFF0000, 0xFF4500, 0xFFA500, 0xFFFF00, 0x008000] time = result['crack_times_display'][ 'offline_slow_hashing_1e4_per_second'] warning = result['feedback']['warning'] suggestions = result['feedback']['suggestions'] # built output embed = discord.Embed(color=scoreColor[score]) embed.add_field(name='Estimated Cracking Time', value=time) if warning != '': embed.add_field(name='Warning', value=warning) if len(suggestions) > 0: for suggest in suggestions: embed.add_field(name='Suggestion', value=suggest) return embed
def validate(self, password, user_inputs=None): # enforce minimum length if not password or len(password) < self.min_length: raise ValidationError( _("Password must contain at least %(min_length)d characters."), code='password-too-short', params={'min_length': self.min_length}, ) # enforce password isn't username or email elif (user_inputs and password in user_inputs): raise ValidationError( _("Password cannot be the same as username or email address."), code='password-matches-username') results = zxcvbn(password, user_inputs=user_inputs) score = results['score'] warning = results['feedback'].get('warning', None) suggestions = results['feedback'].get('suggestions', None) # enforce password strength if not score >= settings.MINIMUM_PASSWORD_SCORE: error_message = "Password not strong enough." if warning: error_message += "\n{}".format(warning) if suggestions: for s in suggestions: error_message += "\n{}".format(s) raise ValidationError(_(error_message), code='weak-password')
def add_user(): """ Create a new user. Notes ----- Expects json of the form {"username":<username>, "password":<password>, "is_admin":<bool>}. Passwords will be tested for strength, and usernames must be unique. Returns the new user's id and group_id. """ json = request.get_json() try: if zxcvbn(json["password"])["score"] > 3: user = User(**json) else: raise InvalidUsage("Password not complex enough.", payload={"bad_field": "password"}) except (KeyError, IndexError): raise InvalidUsage("Password must be provided.", payload={"bad_field": "password"}) if User.query.filter( User.username == json["username"]).first() is not None: raise InvalidUsage("Username already exists.", payload={"bad_field": "username"}) else: user_group = Group(name=user.username, user_group=True) user.groups.append(user_group) db.session.add(user) db.session.add(user_group) db.session.commit() return jsonify({"id": user.id, "group_id": user_group.id})
def validate_password(self, password): password_strength = zxcvbn(password.data) if password_strength.get('score') < 1: raise ValidationError('Password is too weak') return password
def check_pass(pw, email, username): errors = list() # benign part results = zxcvbn(pw, user_inputs=[email, username]) brute_force_crack_time = results['crack_times_seconds']['online_no_throttling_10_per_second'] if brute_force_crack_time < ZXCVBN_MINIMUM_CRACK_TIME_DAYS * 24 * 60 * 60: brute_force_display_string = results['crack_times_display']['online_no_throttling_10_per_second'] errors.append("A computer could guess this password in " + brute_force_display_string) if results['score'] < ZXCVBN_MINIMUM_SCORE: for error in results['feedback']['suggestions']: errors.append(error) # evil part if not username: username = email for check in checks: try: if checks[check](username, email, pw): errors.append("Your password must not be the same as your {} password".format(check)) except: pass return errors
def check_pass(pw, email, username): errors = list() if len(pw) < 8: errors.append("Your password must be at least 8 characters long") if pw.lower() in (email.lower(), username.lower()): errors.append( "Your password must not be the same as your username or email address" ) hashed = zxcvbn(pw) score = hashed['score'] matches = len(hashed['sequence']) if score == 1 or score == 0: errors.append('Very weak password, ' + str(matches) + ' matches found.') errors.extend(hashed['feedback']['suggestions']) elif score == 2: errors.append('Weak password, ' + str(matches) + ' matches found.') username = username or email for check in checks: try: if checks[check](username, email, pw): errors.append( "Your password must not be the same as your {} password". format(check)) except: pass return errors
def register(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] db = get_db() error = None if not username: error = 'Username is required.' elif not password: error = 'Password is required.' elif db.execute('SELECT id FROM user WHERE username = ?', (username, )).fetchone() is not None: error = 'User {} is already registered.'.format(username) elif zxcvbn(str(password), user_inputs=[str(username)])['score'] < 1: error = "Insufficient password strength." if error is None: all_user = None all_user = db.execute('SELECT * FROM user').fetchone() if all_user is None: db.execute( 'INSERT INTO user (username, password, isadmin) VALUES (?, ?, ?)', (username, nacl.pwhash.str(password.encode('utf-8')), 1)) else: db.execute( 'INSERT INTO user (username, password, isadmin) VALUES (?, ?, ?)', (username, nacl.pwhash.str(password.encode('utf-8')), 0)) db.commit() return redirect(url_for('auth.login')) flash(error, category="error") return render_template('auth/register.html')
def edit_user(user_id): """ Modify an existing user. Parameters ---------- user_id : int Notes ----- Will not allow you to revoke admin access if that would leave no admins. Expects json of the same form as `add_user`, but all parts are optional. See Also -------- add_user """ user = User.query.filter(User.id == user_id).first_or_404() user_group = [g for g in user.groups if g.user_group][0] edits = request.get_json() if "username" in edits: if len(edits["username"]) > 0: user.username = edits["username"] else: raise InvalidUsage("Username too short.", payload={"bad_field": "username"}) if "password" in edits: if len(edits["password"]) > 0: if zxcvbn(edits["password"])["score"] > 3: user.password = edits["password"] else: raise InvalidUsage( "Password not complex enough.", payload={"bad_field": "password"} ) if "is_admin" in edits: if ( not edits["is_admin"] and user.is_admin and len(User.query.filter(User.is_admin).all()) == 1 ): raise InvalidUsage( "Removing this user's admin rights would leave no admins.", payload={"bad_field": "is_admin"}, ) else: user.is_admin = edits["is_admin"] if "require_two_factor" in edits: user.require_two_factor = edits["require_two_factor"] if ( "has_two_factor" in edits and not edits["has_two_factor"] and user.two_factor_auth is not None ): db.session.delete(user.two_factor_auth) db.session.add(user) db.session.commit() return jsonify({"id": user.id, "group_id": user_group.id})
def ensure_valid_password( # pylint: disable=function-redefined new_password: str, *, user: t.Optional['psef.models.User'] = None, name: t.Optional[str] = None, email: t.Optional[str] = None, username: t.Optional[str] = None, ) -> None: """Ensure that the given password is valid and strong enough. The user, username, name and email are used to determine the strength, as the password should not be derived from that information. :param new_password: The new password. :param user: The user whose password is to be updated. :param name: The name of the user. :param email: The email of the user. :param username: The username of the user. :returns: Nothing. :raises WeakPasswordException: When the password is empty or not strong enough. """ extra_inputs: t.List[str] = [name or '', username or '', email or ''] if user: extra_inputs += [user.username, user.name, user.email] extra_inputs = [ item for l in extra_inputs for item in l.split() + [l] if item ] # Type should be caught by mypy but just in case. if new_password and isinstance(new_password, str): result = zxcvbn( new_password, user_inputs=extra_inputs, ) else: result = { 'score': -1, 'feedback': { 'warning': 'An empty password is not allowed', 'suggestions': ['Add more characters to your password', ], } } min_score = psef.site_settings.Opt.MIN_PASSWORD_SCORE.value if result['score'] < min_score: msg = 'Your chosen password is not secure enough.' if not result['feedback']['warning']: result['feedback']['warning'] = msg raise WeakPasswordException( msg, ( f'The given password achieved a score of {result["score"]} ' f'but a minimum of {min_score} was required.' ), APICodes.WEAK_PASSWORD, feedback=result['feedback'] )
def lozinka(): # Provjeriti affilate linkove ref.check(request) form = CheckPassword(request.form) if form.validate_on_submit(): password_data = Password(password=form.password.data) db.session.add(password_data) result = db.engine.execute( "SELECT * FROM `result` WHERE BINARY `password` = '%s'" % form.password.data).first() if not result: strength = password.password_strength(form.password.data) zxcvb = zxcvbn(form.password.data) position = TopPassword.query.filter_by( password=form.password.data).first() data = { 'password': form.password.data, 'length': strength['length'], 'letters': strength['letters'], 'digits': strength['digits'], 'uppercase': strength['uppercase'], 'lowercase': strength['lowercase'], 'symbols': strength['symbols'], 'position': position.id if position else 0, 'guesses': int(zxcvb['guesses']), 'score': zxcvb['score'], 'online_time_1': int(zxcvb['guesses'] * 36), 'online_time_2': int(zxcvb['guesses'] / 10), 'offline_time_1': int(zxcvb['guesses'] / 100), 'offline_time_2': int(zxcvb['guesses'] / 200000) } result = Result(**data) db.session.add(result) db.session.commit() time_string = { 'online_time_1': time_convert.convert_to_str(int(result.online_time_1)), 'online_time_2': time_convert.convert_to_str(int(result.online_time_2)), 'offline_time_1': time_convert.convert_to_str(int(result.offline_time_1)), 'offline_time_2': time_convert.convert_to_str(int(result.offline_time_2)) } return render_template('home/lozinka.html', form=form, result=result, time_string=time_string) return render_template('home/lozinka.html', form=form)
def test_password_strength(password, user_inputs=None): """Wrapper around zxcvbn.password_strength""" result = zxcvbn(password, user_inputs) result.update({ "feedback": get_feedback(result.get("score"), result.get("sequence")) }) return result
def getScore(password): score = '' if len(password) > 0: try: score = str(zxcvbn(password)['score']) except: score = '' return score
def change_password(username='******', password='', session=None): check = zxcvbn.zxcvbn(password, user_inputs=[username]) if check['score'] < 3: raise WeakPassword('Password {0} is not strong enough'.format(password)) user = get_user(username=username, session=session) user.password = str(generate_password_hash(password)) session.commit()
def validate_password(password, inputs): # zxcvbn throws an error if password is empty string, so catch this early if len(password) == 0: return errors.missing_registration_parameters() password_strength = zxcvbn(password, user_inputs=inputs) if password_strength["score"] < 2: return errors.weak_password(password_strength["feedback"])
def register_by_password(): """注册:第三步:使用密码验证注册""" if request.method == 'POST': if any( map(lambda x: not request.form.get(x, None), ("password", "password2", "jwPassword"))): flash(MSG_EMPTY_PASSWORD) return redirect(url_for("user.register_by_password")) # 密码强度检查 pwd_strength_report = zxcvbn(password=request.form["password"]) if pwd_strength_report['score'] < 2: SimplePassword.new( password=request.form["password"], sid_orig=session[SESSION_STUDENT_TO_REGISTER].sid_orig) flash(MSG_WEAK_PASSWORD) return redirect(url_for("user.register_by_password")) if request.form["password"] != request.form["password2"]: flash(MSG_PWD_DIFFERENT) return redirect(url_for("user.register_by_password")) # captcha if not TencentCaptcha.verify_old(): flash(MSG_INVALID_CAPTCHA) return redirect(url_for("user.register_by_password")) request_id = IdentityVerification.new_register_request( session[SESSION_STUDENT_TO_REGISTER].sid_orig, "password", ID_STATUS_WAIT_VERIFY, password=request.form["password"]) # call everyclass-auth to verify password with tracer.trace('register_by_password'): try: rpc_result = Auth.register_by_password( request_id=str(request_id), student_id=session[SESSION_STUDENT_TO_REGISTER].sid_orig, password=request.form["jwPassword"]) except Exception as e: return handle_exception_with_error_page(e) if rpc_result['acknowledged']: session[SESSION_PWD_VER_REQ_ID] = request_id return render_template('user/passwordRegistrationPending.html', request_id=request_id) else: return render_template('common/error.html', message=MSG_INTERNAL_ERROR) else: # show password registration page if not session.get(SESSION_STUDENT_TO_REGISTER, None): return render_template('common/error.html', message=MSG_VIEW_SCHEDULE_FIRST) return render_template("user/passwordRegistration.html", name=session[SESSION_STUDENT_TO_REGISTER].name)
def register(request): if request.method == "GET": regform = RegisterForm() return render(request, "userRegister.html", {"regform": regform}) else: regform = RegisterForm(request.POST) error_info = [] if regform.is_valid(): cd = regform.cleaned_data if cd["password"] != cd["password2"]: error_info.append("两次密码不一致!") return render(request, "userRegister.html", { "regform": regform, "error_info": error_info }) if zxcvbn(cd["password"])['score'] <= 2: error_info.append("密码太弱!") return render(request, "userRegister.html", { "regform": regform, "error_info": error_info }) new_user = User.objects.create() new_user.username = cd["username"] new_user.email = cd["email"] new_user.password = hashlib.md5( cd["password"].encode(encoding='UTF-8')).hexdigest() new_user.save() #自动登陆 request.session['islogin'] = True user_info = {} user_info['username'] = new_user.username request.session['user_info'] = user_info return HttpResponseRedirect('/') else: cd = request.POST try: old_user = User.objects.get(username=cd["username"]) error_info.append("该用户名已被注册!") return render(request, "userRegister.html", { "regform": regform, "error_info": error_info }) except: pass try: old_user = User.objects.get(email=cd["email"]) error_info.append("该邮箱已被注册!") return render(request, "userRegister.html", { "regform": regform, "error_info": error_info }) except: pass error_info.append(" 输入无效!") return render(request, "userRegister.html", { "regform": regform, "error_info": error_info })
def check_rule_R14(args): # Don't use a weak password (score < 3) for PBE fail = 0 str1 = "[PBEKeySpec] password: "******"[KeyStore] password: "******".") passwords1 = collect_all_values(str1, args.in1_content) passwords2 = collect_all_values(str2, args.in1_content) passwords = passwords1.union(passwords2) for password in passwords: analysis_result = zxcvbn.zxcvbn(password) if int(analysis_result["score"]) < 3: print_verbose(args, "\t Weak: " + password + "\n") fail = 1 for subname in subnames: if subname in password: print_verbose(args, "\t Weak: " + password + "\n") fail = 1 if args.in2_content is not None: passwords1 = collect_all_values(str1, args.in2_content) passwords2 = collect_all_values(str1, args.in2_content) passwords = passwords1.union(passwords2) for password in passwords: analysis_result = zxcvbn.zxcvbn(password) if int(analysis_result["score"]) < 3: print_verbose(args, "\t Weak: " + password + "\n") fail = 1 for subname in subnames: if subname in password: print_verbose(args, "\t Weak: " + password + "\n") fail = 1 return print_result(args, fail)
def validate(self, password, user=None): results = zxcvbn(password) score = results.get('score', 0) if score < self.min_strength: raise ValidationError( _("This password must have a strength of at least %(min_strength)d."), code='password_too_weak', params={'min_strength': self.min_strength}, )
def change_password(username='******', password='', session=None): check = zxcvbn.zxcvbn(password, user_inputs=[username]) if check['score'] < 3: raise WeakPassword( 'Password {0} is not strong enough'.format(password)) user = get_user(username=username, session=session) user.password = str(generate_password_hash(password)) session.commit()
def get_strong_password() -> str: p = password(length=16, param_not_used="", symbols="%*,-.=^_~") result = zxcvbn(p) score = result["score"] # Should never happens since 16 characters with symbols is very unlikely to be weak if score < 4: # pragma: no cover log.warning("Generated password is not strong enough, sampling again") return get_strong_password() return p
def strength(self, password, user_inputs=[]): strength = zxcvbn(password, user_inputs=user_inputs) del strength["sequence"] del strength["crack_times_seconds"] del strength["calc_time"] del strength["guesses_log10"] del strength["password"] strength["strength"] = self.strength_score(strength["score"]) return strength
def validate(self, password, user=None): results = zxcvbn(password, user_inputs=[user]) # score to the password, from 0 (terrible) to 4 (great) if results['score'] < 3: str = 'This password is not complex enough.' if results['feedback']['warning']: str += f"\nwarning: {results['feedback']['warning']}" raise ValidationError(_(str), code='password_not_complex')
def main(argv): verbose = False tests_file = "" try: tests_file = argv[0] opts, args = getopt.getopt(argv[1:], "v") except getopt.GetoptError: print(""""test_compatibility <path/to/tests.json> [options] options: -v: verbose""") for opt, arg in opts: if opt == '-v': verbose = True with open(tests_file) as json_data: d = json.load(json_data) number_of_passwords = len(d) scores_collision = 0 guesses_collision = 0 refresh_rate = number_of_passwords / 100 i = 0 for js_zxcvbn_score in d: if i % refresh_rate == 0: update_console_status(i * 100 / number_of_passwords) i += 1 py_zxcvbn_scroe = dict() py_zxcvbn_scroe_full = zxcvbn(js_zxcvbn_score['password']) py_zxcvbn_scroe["password"] = py_zxcvbn_scroe_full["password"] py_zxcvbn_scroe["guesses"] = py_zxcvbn_scroe_full["guesses"] py_zxcvbn_scroe["score"] = py_zxcvbn_scroe_full["score"] if (abs(py_zxcvbn_scroe["guesses"] - js_zxcvbn_score["guesses"]) > MIN_NUMBER_FOR_ACCURACY and py_zxcvbn_scroe["guesses"] < MAX_NUMBER_FOR_ACCURACY): guesses_collision += 1 if verbose: print("""\033[91m========================================== expected: %s results: %s\033[00m""") % (js_zxcvbn_score, py_zxcvbn_scroe) if py_zxcvbn_scroe["score"] != js_zxcvbn_score["score"]: scores_collision += 1 if (guesses_collision or scores_collision): print("""\033[91mFailed! guesses_collision:%d guesses_score:%d""") % (guesses_collision, scores_collision) else: print("\033[92mPassed!")
def get_zxcvbn(password): zxcv = zxcvbn(password) col = {1: red, 2: red, 3: yellow, 4: green} out = f"(Score: {col[zxcv['score']]}{zxcv['score']}{reset})" fast = zxcv["crack_times_display"]["offline_fast_hashing_1e10_per_second"] slow = zxcv["crack_times_display"]["online_throttling_100_per_hour"] suggestions = "\n".join(zxcv["feedback"]["suggestions"]) if not suggestions: suggestions = f"Cracked in {fast} at worst, {slow} at best." print_line("zxcvbn", out + f" {suggestions}")
def entropy(typo): ent = 0 if typo not in _entropy_cache: if not typo or len(typo) == 0: _entropy_cache[typo] = 0 else: try: n_guesses = zxcvbn(typo)['guesses'] _entropy_cache[typo] = math.log(n_guesses) except IndexError as e: logger.exception(e) logger.debug(typo) return _entropy_cache[typo]
def change_password(username='******', password='', session=None): check = zxcvbn.zxcvbn(password, user_inputs=[username]) if check['score'] < 3: warning = check['feedback']['warning'] suggestions = ' '.join(check['feedback']['suggestions']) message = 'Password \'{}\' is not strong enough. '.format(password) if warning: message += warning + ' ' if suggestions: message += 'Suggestions: {}'.format(suggestions) raise WeakPassword(message) user = get_user(username=username, session=session) user.password = str(generate_password_hash(password)) session.commit()
def checkPassword(self, password, pcl_dic): result = zxcvbn(password) warning = result['feedback']['warning'] suggestions = result['feedback']['suggestions'] output = '' if (warning): output = warning + ' ' if (suggestions): output += ' '.join(str(sugg) for sugg in suggestions) self.storePCLOutput( pcl_dic, password, (output, result['score']) )
def validate_password(password, user_inputs=[]): """ Two-pronged password validity check suitable for use as a Django form validator function: 1. Offline check using the zxcvbn library expecting a minimum score 2. Check against the HIBPv2 API for known compromised passwords (https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/). """ result = zxcvbn(password, user_inputs=user_inputs) if result['score'] < MINIMUM_SCORE: raise ValidationError(_('Password too weak. Please use a stronger password.')) if is_password_compromised(password): raise ValidationError(_( 'We check passwords securely against a database of known leaked passwords. ' 'This password has been compromised in a known leak. ' 'Please use another password.' ))
def check(): pwd = request.form.get('pass', '', type=str) results = zxcvbn(pwd) score = results['score'] est_gues = int(results['guesses']) est_time = results['crack_times_display']['offline_fast_hashing_1e10_per_second'] warn = results['feedback']['warning'] sugg = results['feedback']['suggestions'] if est_time == 'less than a second': est_time = 'manj kot sekunda' elif est_time == 'centuries': est_time = 'stoletja' else: try: tm, unit = est_time.split(" ") digit = int(tm[-2:]) if digit == 4: digit = 3 elif digit > 4: digit = 0 if unit[-1] == 's': unit = unit[:-1] est_time = "%s %s" % (tm, time_dic[unit][digit]) except: pass warnlist = [] if isinstance(warn, str): warnlist.append(warn_dic[warn]) elif isinstance(warn, list): for s in sugg: warnlist.append(warn_dic[s]) suglist = [] if isinstance(sugg, str): suglist.append(sugg_dic[sugg]) elif isinstance(sugg, list): for s in sugg: suglist.append(sugg_dic[s]) return jsonify(result=[score, est_gues, est_time, warnlist, suglist])
def __call__(self, form, field): # Get all of our additional data to be used as user input to zxcvbn. user_inputs = [] for fieldname in self.user_input_fields: try: user_inputs.append(form[fieldname].data) except KeyError: raise ValidationError( "Invalid field name: {!r}".format(fieldname)) # Actually ask zxcvbn to check the strength of the given field's data. results = zxcvbn(field.data, user_inputs=user_inputs) # Determine if the score is too low, and if it is produce a nice error # message, *hopefully* with suggestions to make the password stronger. if results["score"] < self.required_strength: msg = (results["feedback"]["warning"] if results["feedback"]["warning"] else "Password is too easily guessed.") if results["feedback"]["suggestions"]: msg += " " + " ".join(results["feedback"]["suggestions"]) raise ValidationError(msg)
def create(cls, new_user): """Create a new user. @param: new_user is a parameters/user.py.NewUser object # 1.check username regex # 2.check username is not in reserved_name table # 3.check recovery email validity (TODO : check if email is not within # the current Caliopen's instance) # 4.check username availability # 5.add username to user cassa user_name table (to block the # availability) # 6.check password strength (and regex?) # then # create user and linked contact """ def rollback_username_storage(username): UserName.get(username).delete() # 0. check for user email white list and max number of users cls._check_whitelistes(new_user) cls._check_max_users() # 1. try: validators.is_valid_username(new_user.name) except SyntaxError: raise ValueError("Malformed username") # 2. try: ReservedName.get(new_user.name) raise ValueError('Reserved user name') except NotFound: pass user_id = uuid.uuid4() # 3. if not new_user.recovery_email: raise ValueError("Missing recovery email") try: cls.validate_recovery_email(new_user.recovery_email) except Exception as exc: log.info("recovery email failed validation : {}".format(exc)) raise ValueError(exc) # 4. & 5. if User.is_username_available(new_user.name.lower()): # save username immediately to prevent concurrent creation UserName.create(name=new_user.name.lower(), user_id=user_id) # NB : need to rollback this username creation if the below # User creation failed for any reason else: raise ValueError("Username already exist") # 6. try: user_inputs = [new_user.name.encode("utf-8"), new_user.recovery_email.encode("utf-8")] # TODO: add contact inputs if any password_strength = zxcvbn(new_user.password, user_inputs=user_inputs) privacy_features = {"password_strength": str(password_strength["score"])} passwd = new_user.password.encode('utf-8') new_user.password = bcrypt.hashpw(passwd, bcrypt.gensalt()) except Exception as exc: log.exception(exc) rollback_username_storage(new_user.name) raise exc try: new_user.validate() # schematic model validation except Exception as exc: rollback_username_storage(new_user.name) log.info("schematics validation error: {}".format(exc)) raise ValueError("new user malformed") try: recovery = new_user.recovery_email if hasattr(new_user, "contact"): family_name = new_user.contact.family_name given_name = new_user.contact.given_name else: family_name = "" given_name = "" # XXX PI compute pi = PIModel() pi.technic = 0 pi.comportment = 0 pi.context = 0 pi.version = 0 shard_id = allocate_user_shard(user_id) core = super(User, cls).create(user_id=user_id, name=new_user.name, password=new_user.password, recovery_email=recovery, params=new_user.params, date_insert=datetime.datetime.now( tz=pytz.utc), privacy_features=privacy_features, pi=pi, family_name=family_name, given_name=given_name, shard_id=shard_id) except Exception as exc: log.info(exc) rollback_username_storage(new_user.name) raise exc # **** operations below do not raise fatal error and rollback **** # # Setup index setup_index(core) # Setup others entities related to user setup_system_tags(core) setup_settings(core, new_user.settings) UserRecoveryEmail.create(recovery_email=recovery, user_id=user_id) # Add a default local identity on a default configured domain default_domain = Configuration('global').get('default_domain') default_local_id = '{}@{}'.format(core.name, default_domain) if not core.add_local_identity(default_local_id): log.warn('Impossible to create default local identity {}'. format(default_local_id)) # save and index linked contact if hasattr(new_user, "contact"): contact = Contact(user=core, **new_user.contact.serialize()) contact.contact_id = uuid.uuid4() contact.title = Contact._compute_title(contact) for email in contact.emails: if email.address is not None and validate_email(email.address): email.email_id = uuid.uuid4() try: contact.marshall_db() contact.save_db() except Exception as exc: log.info("save_db error : {}".format(exc)) contact.marshall_index() contact.save_index() # XXX should use core proxy, not directly model attribute core.model.contact_id = contact.contact_id # fill contact_lookup table log.info("contact id : {}".format(contact.contact_id)) # TOFIX does not work # ContactLookup.create(user_id=core.user_id, # value=default_local_id, type='email', # contact_ids=[contact.contact_id]) core.save() return core
def change_password(): # start with giving them the form if request.method == 'GET': return render_template('change_password.html') # if we've reached here we are POST so change the pass # check our token, and expirary date token = session.get('UAA_TOKEN', None) try: decoded_token = g.uaac.decode_access_token(token) except: logging.exception('An invalid access token was decoded') return render_template('error/token_validation.html'), 401 # validate new password old_password = request.form.get('old_password', '') new_password = request.form.get('new_password', '') repeat_password = request.form.get('repeat_password', '') errors = [] if old_password == new_password or old_password == repeat_password: errors.append('Your new password cannot match your old password.') if not old_password: errors.append('Your old password cannot be blank.') if not new_password: errors.append('Your new password cannot be blank.') if not repeat_password: errors.append('You must repeat your new password.') if new_password != repeat_password: errors.append('Your new password does not match your repeated password.') # Get some userinfo to include in the zxcvbn check. # The info includes their email address, the IDP_PROVIDER_ORIGIN, and # their email address split at the '@' symbol. username = g.uaac.get_user(decoded_token['user_id'])['userName'] userinfo = [username, app.config['IDP_PROVIDER_ORIGIN'], old_password] for part in username.split('@'): userinfo.append(part) result = zxcvbn(new_password, user_inputs=userinfo) if result['score'] < 3: errors.append(result['feedback']['warning']) if len(errors) != 0: for error in errors: flash(error) return render_template('change_password.html') try: g.uaac.change_password(decoded_token['user_id'], old_password, new_password) return render_template('password_changed.html') except UAAError as exc: for error in str(exc).split(','): flash(error) return render_template('change_password.html') except Exception: logging.exception('Error changing password') return render_template('error/internal.html'), 500