X

Safe Base64 Url in ASP .NET

base64

How to do safe base64 url encoding in ASP .NET, I came into a problem of url encoding in IIS 7 where it does not like “+”, “/” in the Url. Basically a Url that looks like of like this

http://fake.abc/TIRlcEq0umjO6uJqtqvnkUGntUzv19rK+8mcvPK5qL1bwEZtEUqTlc3iF/TomuXU746Il5IF2iN9SeYuYDqt6SQzfdrv+Ltug2KZteKlYawc=

I know you may say what is this??? Its actually some kind of encrypted data that is in base64, but since IIS 7 does not like “+” or “/” even if its url encoded.

So I made a Utility class string extension method that just simply replaces the characters with “-” and “_”

Here is the code so maybe someday it would help you out also.

public static class SafeBase64UrlEncoder
	{
		private const string Plus = "+";
		private const string Minus = "-";
		private const string Slash = "/";
		private const string Underscore = "_";
		private const string EqualSign = "=";
		private const string Pipe = "|";
		private static readonly IDictionary _mapper;


		static SafeBase64UrlEncoder()
		{
			_mapper = new Dictionary {{Plus, Minus}, {Slash, Underscore}, {EqualSign, Pipe}};
		}

		public static string EncodeBase64Url(this string base64Str)
		{
			if (string.IsNullOrEmpty(base64Str))
				return base64Str;

			foreach (var pair in _mapper)
			{
				base64Str = base64Str.Replace(pair.Key, pair.Value);
			}
			
			return base64Str;
		}
		
		public static string DecodeBase64Url(this string safe64Url)
		{

			if (string.IsNullOrEmpty(safe64Url))
				return safe64Url;

			foreach (var pair in _mapper)
			{
				safe64Url = safe64Url.Replace(pair.Value, pair.Key);
			}

			return safe64Url;
		}
	}

And always there should be a test for it.

[TestFixture]
	public class SafeBase64UrlTests
	{

		[Test]
		public void Encode64Url_Should_Replace_Plus_With_Minus()
		{
			var str = "+".EncodeBase64Url();

			Assert.That(str.Equals("-"),Is.True);
		}


		[Test]
		public void Encode64Url_Should_Replace_ThreePlus_With_ThreeMinus()
		{
			var str = "+++".EncodeBase64Url();

			Assert.That(str.Equals("---"), Is.True);
		}

		[Test]
		public void Decode64Url_Should_Replace_Minus_With_Plus()
		{
			var str = "-".DecodeBase64Url();

			Assert.That(str.Equals("+"), Is.True);
		}

		[Test]
		public void Decode64Url_Should_Replace_ThreeMinus_With_ThreePlus()
		{
			var str = "---".DecodeBase64Url();

			Assert.That(str.Equals("+++"), Is.True);
		}


		[Test]
		public void Encode64Url_Should_Replace_Slash_With_Underscore()
		{
			var str = "/".EncodeBase64Url();

			Assert.That(str.Equals("_"), Is.True);
		}

		[Test]
		public void Encode64Url_Should_Replace_ThreeSlash_With_ThreeUnderscore()
		{
			var str = "///".EncodeBase64Url();

			Assert.That(str.Equals("___"), Is.True);
		}

		[Test]
		public void Decode64Url_Should_Replace_Underscore_With_Slash()
		{
			var str = "_".DecodeBase64Url();

			Assert.That(str.Equals("/"), Is.True);
		}

		[Test]
		public void Decode64Url_Should_Replace_ThreeUnderscore_With_ThreeSlash()
		{
			var str = "___".DecodeBase64Url();

			Assert.That(str.Equals("///"), Is.True);
		}


		[Test]
		public void Encode64Url_Should_Replace_Equal_With_Pipe()
		{
			var str = "=".EncodeBase64Url();

			Assert.That(str.Equals("|"), Is.True);
		}

		[Test]
		public void Encode64Url_Should_Replace_ThreeEqual_With_ThreePipe()
		{
			var str = "===".EncodeBase64Url();

			Assert.That(str.Equals("|||"), Is.True);
		}


		[Test]
		public void Decode64Url_Should_Replace_Pipe_With_Equal()
		{
			var str = "|".DecodeBase64Url();

			Assert.That(str.Equals("="), Is.True);
		}

		[Test]
		public void Decode64Url_Should_Replace_ThreePipe_With_ThreeEqual()
		{
			var str = "|||".DecodeBase64Url();

			Assert.That(str.Equals("==="), Is.True);
		}


		[Test]
		public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe()
		{
			var str = "=+/".EncodeBase64Url();

			Assert.That(str.Equals("|-_"), Is.True);
		}
		

		[Test]
		public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus()
		{
			var str = "|-_".DecodeBase64Url();

			Assert.That(str.Equals("=+/"), Is.True);
		}


		[Test]
		public void Encode64Url_Should_Replace_EqualSlashPlus_With_MinusUnderscorePipe_With_Alpha_Numeric_Characters()
		{
			var str = "1A=2b+3C/4d".EncodeBase64Url();

			Assert.That(str.Equals("1A|2b-3C_4d"), Is.True);
		}


		[Test]
		public void Decode64Url_Should_Replace_MinusUnderscorePipe_With_EqualSlashPlus_With_Alpha_Numeric_Characters()
		{
			var str = "1a|2B-3c_4D".DecodeBase64Url();

			Assert.That(str.Equals("1a=2B+3c/4D"), Is.True);
		}



		[Test]
		public void Encode64Url_Should_Return_Same_String_When_Empty()
		{
			var str = string.Empty.EncodeBase64Url();

			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}


		[Test]
		public void Decode64Url_Should_Return_Same_String_When_Empty()
		{
			var str = string.Empty.DecodeBase64Url();

			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}


		[Test]
		public void Encode64Url_Should_Return_Same_String_When_Null()
		{
			string str = null;

			str = str.EncodeBase64Url();

			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}


		[Test]
		public void Decode64Url_Should_Return_Same_String_When_Null()
		{
			string str = null;

			str = str.DecodeBase64Url();

			Assert.That(string.IsNullOrEmpty(str), Is.True);
		}

	
	}

There are other ways of fixing this and one can read them at
http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx
http://bentaylor.org/dasBlog-Patch-Add-Choice-Of-Dash-For-Post-Title-URL-Spaces.aspx

Categories: ASP .NET Misc
Taswar Bhatti:

View Comments (1)

Related Post