Consider using URL safe base64 tokens for email verification instead of URL encoding
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
As shown in this email verification example, it is required to URL encode the base64 email confirmation token before sending them in an email:
https://github.com/aspnet/Identity/blob/47060f5e529ee4b872d9fcf66774935dafb051fc/samples/IdentitySample.DefaultUI/Areas/Identity/Pages/Account/Register.cshtml.cs#L100
This works the majority of the time. However, at no fault of our own, there are email providers out there that will still re-encode `%` characters that appear in anchor tags with `%25`, resulting in invalid tokens.
For example, `==` (original b64 characters) → `%3D%3D` (correct) → `%253D%253D` (incorrect).
This is obviously a bug with the email client itself, but we have come across the case several times with multiple different email clients (for example, mailbox.org will do this).
Since this really effects everyone (though most may not have noticed), I would propose that the team here should consider using URL safe base64 strings by default within the framework. This would eliminate the need for us to manually create our own TokenProvider, which we've had to resort to today. URL safe base64 strings are used, for example, in JWT tokens as a standard. Here is some sample code that we use to achieve it:
public static string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", string.Empty);
return output;
}
public static byte[] Base64UrlDecode(string input)
{
var output = input;
// 62nd char of encoding
output = output.Replace('-', '+');
// 63rd char of encoding
output = output.Replace('_', '/');
// Pad with trailing '='s
switch(output.Length % 4)
{
case 0:
// No pad chars in this case
break;
case 2:
// Two pad chars
output += "=="; break;
case 3:
// One pad char
output += "="; break;
default:
throw new InvalidOperationException("Illegal base64url string!");
}
// Standard base64 decoder
return Convert.FromBase64String(output);
}
Contributor guide
Assessment
This issue has not been assessed yet.