Hi, I just published my first package brasilikum/is-password-known
It uses the free and public API of HaveIBeenPwned.com to check passwords agains an ever growing list of compromised, and therefore unsafe passwords.
How does this not completely disclose the password?
See this blogpost for an detailed explanation
Tldr; Even if someone can read the request you make to the API, they only know the requested password is one of 478 results (on average).
Goals of the package API
Handling passwords is always very delicate so my primary goal was to make it very explicit what is happening:
This usage example on Ellie includes a Debug.log for exactly that reason.
Thanks to the Elm Architecture, there is no way my package could sneakily send the password out, right?
The second goal was to make it impossible to send the actual password over by accident, which I achieved by creating an opaque type (custom type without exposed constructor) for the hashed password.
The third goal was to make the package easy to use.
Looking at my usage example, I am not very convinced I succeeded. I could move much of the logic inside of the package, but I am not sure how to avoid sacrificing goal 1 in the process.
Because the request to the API returns line-based values of the format
partOfTheHash:NumberOfDatasetsFoundIn, I had to write my own elm/parser (or did I not?). I certainly did not understand the package entirely already, but was able to build a working parser from examples and tinkering.
Creating a package was initially not easy. I initialized an app with
elm init and was not aware of the differences between a package and an app when specifying the dependency versions. Other than that,
elm publish guided me through the process very very well!
I did not initially think of the case that the user might change the password before the previous response returns. If not handled correctly, the response would be compared to the new password, which would result in a wrong result.
The complexity this creates for the consumer of the current API is a strong indicator for me that I have to find a better API design.
Please feel free to give me feedback on both the package and the usage example. Especially the update function in the latter looks like it could be expressed more readable.
What do you think of my prioritization of goals? Would you prefer the tradeoffs this brings over a simpler package API?