As we're constantly working to improve Report URI, time is not always spent on new features and bug fixes. We always want to offer the most secure service we can and recently, we made some upgrades that will help our users keep their accounts more secure!

Existing Measures

Of course, we already take a bunch of existing measures to protect the precious credentials that our users trust us with, but there's always room for improvement.

You can browse through our last 3 years of Penetration Test Reports, all of which are public for you to read. Alongside that, we require our own internal testing of the application, have had external code reviews and use a trusted storage provider in the form of Microsoft Azure to store all of our data. Data is stored in Azure with AES 256bit encryption at rest and in transit, your password is protected by a minimum of TLSv1.2 with a strong cipher suite. We even publish details of how we securely hash, salt and store your password in our FAQ:

How do you store my password?
We use the password_hash() function in PHP to hash your password before storage. This means we're currently using the bcrypt hashing algorithm with a work factor of 10 and 128 bit salt. Our code: password_hash($password, PASSWORD_DEFAULT)

Even so, we've now launched a couple of other changes to help our users keep their accounts more secure by encouraging the use of really good passwords!

The Pwned Passwords API

If you're not familiar with Pwned Passwords, you should be! The service is part of Have I Been Pwned, run by Troy Hunt, and allows you to query if a password is part of an enormous collection of known passwords from previous data breaches. Using a password for your account that is known to attackers is not the best idea and now, we check user's passwords against the Pwned Passwords API.

But wait! Before anyone gets concerned, of course we're not shipping your passwords off to some external service. The Pwned Passwords API use a k-Anonymity model to query the API which means your password is never disclosed to the API and in fact, none of your data is sent to the API at all.

We check passwords against the Pwned Passwords API during registration and we will prevent a user from using a known compromised password when they setup their account.

We also enforce the new Pwned Passwords rule on the Change Password functionality, again preventing you from changing your account password to something that we know has been previously compromised. Finally, we also check your password against the API during authentication events. This is because we have tens of thousands of users who have previously created passwords that have never been checked, and, a password could be Pwned in the future and we'd then pick that up. The check during authentication will only pop a notification on your account homepage when you login to advise that you that we found your password in a breach online and suggest that you change it. We didn't want to interfere with normal operation of the service but we did want to get the message across!

zxcvbn

Z x c v what now?! If you're not familiar with zxcvbn, it's a password strength estimator created and used by Dropbox across their web, desktop and mobile platforms to check user passwords have enough entropy (randomness). It's a great replacement for those annoying password complexity rules, you know, like a minimum of one uppercase and lowercase character, a number and a special character, and instead provides a more usable policy requirement for password strength.

Your password is run through our zxcvbn check locally on both Registration and Password Change, as above for the Pwned Passwords check, and a password that isn't strong enough will be rejected.

We also run your password through zxcvbn during authentication events to cover those tens of thousands of users who haven't had their password checked, and, to check agaisnt any possible future changes in our strength requirements. If your existing password isn't up to scratch, you'll get a notification in your account advising you that we recommend your password is updated to something better.

Password Managers

Password managers rock, and we do many things to make your use of a password manager on our site as easy as possible. I have come across many sites that do things that are very unfriendly to users of a password manager, like myself, but you might also not be aware that there are things you can do to make using a password manager easier! If you want my recommendation for a password manager, I've always used 1Password.

/.well-known/change-password

If a user uses a password manager, there is now a standardised way for you to let the Password Manager know where the change password functionality of your site is. All you need to do is create a redirect from the path /.well-known/change-password to the location where your change password page is. For us, it looks like this:

--> GET https://report-uri.com/.well-known/change-password
<-- 303 See Other
<-- Location: https://report-uri.com/account/settings/
--> GET https://report-uri.com/account/settings/

If you're using the 1Password browser extension like I am, that leads to a really nice experience.

Form element improvements

To further improve the ease of use of password managers on our site, the form elements on our site give indicators to these tools on how they should be used. For example, the registration form indicates that it's expecting a new password and that the password manager should create a new password for this input. This is done with the autocomplete attribute on the input element.

<input type="password" autocomplete="new-password" id="new-password" …>

On our login form, we tell the password manager that we're expecting the email address and the current password for the user.

<input type="email" autocomplete="email" id="email">
<input type="password" autocomplete="current-password" id="current-password" …>

Indicate which account is being changed

On forms like the change password form, it's not always clear to the password manager which account is being updated, so we let it know. You can see here on our change password form that we have a hidden input that is populated with the email address of the currently authenticated user so the password manager will know which entry to update if the form is used.

<form action="https://report-uri.com/account/change_password/" role="form" method="post" accept-charset="utf-8">
    <input type="email" class="hidden" name="email" autocomplete="email" value="scott@report-uri.com">

This means that when I select the existing password input, the first suggestion from 1Password is the correct account and it will populate the existing password for me.

Create a super strong password

We've always been pretty serious about password security at Report URI and our existing password criteria are pretty simple, mainly focusing on the most important characteristic of a password, length.

We require passwords to be anywhere from 16 characters all the way up to 100 characters so our minimum length is quite high, but for a security focused service, we feel we can get away with that. The maximum length of 100 allows you to go absolutely wild with your password manager complexity settings and you can dial that sucker all the way up to 11! Or, well, maybe 100... 😅

What's even better though, is that we can prompt a password manager to really crank this up to the next level. If a user is typing a 16 character password, that's probably as much as we can get away with as I say, but, if they're using a password manager, we can go much higher. Because we have a .{16-100} pattern on our password input, 1Password will generate a 16 character password like this.

The thing is, we can tell 1Password, or other software generating passwords for you, to do better using the passwordrules attribute on the input and now require a 72 character password be generated!

You can see that password there is now loads better and instead of just exercising the minimum requirement, it's now creating something much stronger. We still allow a 16 character password, because maybe the user is writing it down somewhere and typing it in, but, if it's a piece of software that's generating, storing and inserting this password, there's no reason we shouldn't push this up. Here's the attribute on our password input.

<input type="password" ... passwordrules="minlength: 72; maxlength: 100; required: lower; required: upper; required: digit; required: [-];">

To top it off, because of the account indicator we mentioned above, when going through the password change process, your password manager will know which entry to update with this new password automatically. It's now just an effortless few clicks to udpate your password!

You can read more on the passwordrules attribute, Apple have published a tool to generate a valid policy along with some docs, and, 1Password mentions how to use it too.

2FA

It's not strictly password related, but I wanted to quickly mention what is probably the best account security measure you can enable on Report URI and indeed, any other service too. We support 2FA on Report URI, and team owners can even require that all members of their team/organisation have 2FA enabled. Adding this second layer of protection to your account, on top of the strong password requirements above, puts you in a really good place with regards to your account security and we'd highly recommend heading over to the Settings page and enabling 2FA on your account!

Feedback or suggestions

As always, please feel free to drop by the comments section below if you have any suggestions on how we can further improve account or password security at Report URI, we'd really appreciate it!