base64url encoding
It’s often more convenient to manage data in text format rather than binary data (for example a string column in a database, or a string rendered into a HTTP response). Common examples in security are digital signatures and encryption. Signing and encrypting typically produce bytes of data and in a web application sometimes it’s just easier to manage that data as text.
Base64 is a useful tool for doing this encoding. The only problem is that base64 encoding uses characters that do not work well in URLs and sometimes HTTP headers (e.g. the +, / and = characters are either reserved or have special meaning in URLs). URL encoding is designed to address that problem, but it’s sometimes error prone (e.g. double encoding) or the tooling just doesn’t do the right thing (IIS decodes %2F into a / before it arrives into the application and thus confuses the ASP.NET routing framework). It is very useful to put these sorts of values in a URL, but it’s also frustrating that it’s problematic and that we have to work around these issues again and again.
While reading the JWT specs they faced the same problem and they addressed it by using base64url encoding (which is almost the same, yet different than base64 encoding). Base64url encoding is basically base64 encoding except they use non-reserved URL characters (e.g. – is used instead of + and _ is used instead of /) and they omit the padding characters. I’ve been using this for some time now and am quite happy with it as a replacement for base64 encoding.
Unfortunately there’s no implementation (that I know of) in the .NET framework for this, so we’ve built our own in our Thinktecture.IdentityModel security helper library. You can use our helpers by using the NuGet, or you can grab the code from here, or you can just copy from the snippet below.
public static class Base64Url { public static string Encode(byte[] arg) { string s = Convert.ToBase64String(arg); // Standard base64 encoder s = s.Split('=')[0]; // Remove any trailing '='s s = s.Replace('+', '-'); // 62nd char of encoding s = s.Replace('/', '_'); // 63rd char of encoding return s; } public static byte[] Decode(string arg) { string s = arg; s = s.Replace('-', '+'); // 62nd char of encoding s = s.Replace('_', '/'); // 63rd char of encoding switch (s.Length % 4) // Pad with trailing '='s { case 0: break; // No pad chars in this case case 2: s += "=="; break; // Two pad chars case 3: s += "="; break; // One pad char default: throw new Exception("Illegal base64url string!"); } return Convert.FromBase64String(s); // Standard base64 decoder } }
Edit: Turns out there are two places in .NET where this sort of functionality is available: 1) ASP.NET’s HttpServerUtility.UrlTokenEncode, and 2) Katana’s Microsoft.Owin.Security assembly with the Base64UrlTextEncoder class.
if you are ok with padding chars you could use System.Web.HttpServerUtility.UrlTokenEncode
Wow, amazing that’s been in ASP.NET so long and I’ve not seen it. Thanks.
So this extension class does no longer exists in the IdentityModel repository, correct?
It’s still there.
Need the same for ASP classic, do you have a clue ? thanks
The code would be easly to implement in VBScript, I imagine. But I’ve not done it, sorry.
We used the bitoftech blog (Taiseer Joudeh) to give us a leg up on our oauth implementation. He used “TextEncodings.Base64Url.Decode(..)” but we encountered a problem with the special characters Brock mentions above. So we switched to “TextEncodings.Base64.Decode(..)” (NOTE the remove of “Url” after “Base64”) and everything seems to be working fine. Unless there is something different we need from Brock’s implementation that someone can point out.
Careful about UrlTokenEncode it is not the same as the code above.