|
2 | 2 | <div class="col-md-6"> |
3 | 3 | <div class="panel panel-default"> |
4 | 4 | <div class="panel-body"> |
5 | | - <form method="post" action="/api/accounts/new"> |
| 5 | + <form method="post" action="/api/accounts/new" onsubmit="return validatePasswordBeforeSubmit(e)"> |
6 | 6 | {{> shared/error}} |
7 | 7 |
|
8 | 8 | <div class="form-group"> |
|
19 | 19 | <input type="checkbox" id="showPassword"/> Show Password |
20 | 20 | </label> |
21 | 21 | </div> |
| 22 | + <span id="passwordHelp" class="text-danger"></span> |
22 | 23 | </div> |
23 | 24 |
|
24 | 25 | <div class="form-group"> |
|
66 | 67 | </div> |
67 | 68 |
|
68 | 69 |
|
| 70 | +<script src="https://raw.githubusercontent.com/nowsecure/owasp-password-strength-test/master/owasp-password-strength-test.js" |
| 71 | + defer></script> |
| 72 | +<script> |
| 73 | + |
| 74 | +</script> |
69 | 75 | <script> |
70 | 76 | (function () { |
71 | 77 | 'use strict' |
|
75 | 81 | password.type = password.type === 'password' ? 'text' : 'password' |
76 | 82 | }) |
77 | 83 | })() |
| 84 | +
|
| 85 | + function validatePasswordBeforeSubmit (e) { |
| 86 | + e.preventDefault(); |
| 87 | + const pwdErrorDiv = document.getElementById('passwordHelp'); |
| 88 | + let pw = document.getElementById('password').value; |
| 89 | + let owaspCheck = owaspPasswordStrengthTest.test(pw) |
| 90 | + if (owaspCheck.strong === true) { |
| 91 | + pwdErrorDiv.innerText = ''; |
| 92 | + sha1(pw).then((digest) => { |
| 93 | + const preFix = digest.slice(0, 5); |
| 94 | + const url = 'https://api.pwnedpasswords.com/range/'; |
| 95 | + fetch(url+preFix).then( |
| 96 | + response => response.text() |
| 97 | + ).then( |
| 98 | + data => { |
| 99 | + if (data.indexOf(digest) !== -1) { |
| 100 | + pwdErrorDiv.innerText = 'This password was exposed in a data breach. Please use a more secure alternative one!'; |
| 101 | + return false; |
| 102 | + } |
| 103 | + } |
| 104 | + ) |
| 105 | + }); |
| 106 | + } |
| 107 | + else { |
| 108 | + pwdErrorDiv.innerText = owaspCheck.requiredTestErrors[0] |
| 109 | + return false; |
| 110 | + } |
| 111 | + return true; |
| 112 | + } |
| 113 | +
|
| 114 | + function sha1(str) { |
| 115 | + let buffer = new TextEncoder("utf-8").encode(str); |
| 116 | + return crypto.subtle.digest("SHA-1", buffer).then(function (hash) { |
| 117 | + return hex(hash); |
| 118 | + }); |
| 119 | + } |
| 120 | +
|
| 121 | + function hex(buffer) { |
| 122 | + let hexCodes = []; |
| 123 | + let view = new DataView(buffer); |
| 124 | + for (let i = 0; i < view.byteLength; i += 4) { |
| 125 | + let value = view.getUint32(i); |
| 126 | + let stringValue = value.toString(16); |
| 127 | + const padding = '00000000'; |
| 128 | + let paddedValue = (padding + stringValue).slice(-padding.length); |
| 129 | + hexCodes.push(paddedValue); |
| 130 | + } |
| 131 | + return hexCodes.join(""); |
| 132 | + } |
78 | 133 | </script> |
0 commit comments