The way you create cookies is also insecure, you should be using crypto/rand instead of math/rand AND rather hex.EncodeToString() the result instead of just generating random numbers in the alphanumeric range.
The hex.EncodeToString() point is a nit. Generate 128 bits of randomness, and then encode it however you'd like. The track record of people trying to get "generate random numbers in the alphanumeric range" isn't great; it's an opportunity to reintroduce bias. Start with a random token of sufficient size, then encode.
The Argon2 vs. bcrypt thing is unhelpful. It does not matter what password hash you use, so long as you use a hash designed for password storage (ie: not "salted SHA-2"). Bcrypt is fine. I prefer scrypt, for the obvious hardware tradeoff. I don't recommend Argon2 to people (or tell people to stop using it) because of the library support issues.
But I think it's specifically a bad idea to tell people to switch password hashes from bcrypt (or PBKDF2) to the trendy new hash. The security benefit of "upgrading" from one password hash to another is marginal.
(Obviously, the benefit of switching from "salted" hashes to real password hashes is not).
And I think one can also make mistakes with scrypt when choosing parameters which Colin himself acknowledged. So isn't it time to go ahead with Argon2?
People have weird ideas about the importance of picking password hashes. It's important not to use non-password-hashes. Other than that, which password hash you use? Not so important.
There are a few 3rd party implementations... But is it more secure to use a lesser known 3rd party package to have Argon2 support or is it more secure to use the more widely adopted bcrypt package supported by the Go dev community?
I was talking about password hashes in a general sense, not just about the current project.
Does it not have the issue that it will silently truncate passphrases beyond 72 bytes? As far as I can tell OP does not check for that and the Go API they use makes no mention of it and was affected at some point.
72 bytes is not a very high limit when SEA abugida use roughly as many symbols as western alphabets per word/phrase but each symbol takes 3 bytes (assuming UTF-8) rather than one.
For instance "Gujarati script" is 15 codepoints and 15 bytes but and "ગુજરાતી લિપિ" ("Gujarati script" in Gujarati) is 12 codepoints and 34 bytes.
Even fairly trivial codephases are at risk, XKCD's "correct horse battery staple" is 28 bytes but translated to Gujarati (via gtrans) it's 60.
On the other hand, 72 bytes is a lot, especially when you have decent bcrypt settings.
Yes, the issue is that you have to remember to do that.
> On the other hand, 72 bytes is a lot
From my own comment:
> 72 bytes is not a very high limit when SEA abugida use roughly as many symbols as western alphabets per word/phrase but each symbol takes 3 bytes (assuming UTF-8) rather than one.
> For instance "Gujarati script" is 15 codepoints and 15 bytes but and "ગુજરાતી લિપિ" ("Gujarati script" in Gujarati) is 12 codepoints and 34 bytes.
In two words, Gujarati (and many other SEA/Brahmic abugida e.g. Tai) is halfway there, a decent passphrase in an SEA script will blow right through.