summaryrefslogtreecommitdiffstats
path: root/projecttemplates/WebFormsRelyingParty/Code/Utilities.cs
blob: a211cad0918c1cb2d9f2adf8ff665e1f6f92f99a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//-----------------------------------------------------------------------
// <copyright file="Utilities.cs" company="Andrew Arnott">
//     Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace WebFormsRelyingParty.Code {
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Security.Cryptography;
	using System.Web;

	public static class Utilities {
		private const string csrfCookieName = "CsrfCookie";
		private static readonly RandomNumberGenerator CryptoRandomDataGenerator = new RNGCryptoServiceProvider();

		/// <summary>
		/// Gets the full URI of the web application root.  Guaranteed to end in a slash.
		/// </summary>
		public static Uri ApplicationRoot {
			get {
				string appRoot = HttpContext.Current.Request.ApplicationPath;
				if (!appRoot.EndsWith("/", StringComparison.Ordinal)) {
					appRoot += "/";
				}

				return new Uri(HttpContext.Current.Request.Url, appRoot);
			}
		}

		public static string SetCsrfCookie() {
			// Generate an unpredictable secret that goes to the user agent and must come back
			// with authorization to guarantee the user interacted with this page rather than
			// being scripted by an evil Consumer.
			byte[] randomData = new byte[8];
			CryptoRandomDataGenerator.GetBytes(randomData);
			string secret = Convert.ToBase64String(randomData);

			// Send the secret down as a cookie...
			var cookie = new HttpCookie(csrfCookieName, secret) {
				Path = HttpContext.Current.Request.Path,
				HttpOnly = true,
				Expires = DateTime.Now.AddMinutes(30),
			};
			HttpContext.Current.Response.SetCookie(cookie);

			// ...and also return the secret so the caller can save it as a hidden form field.
			return secret;
		}

		public static void VerifyCsrfCookie(string secret) {
			var cookie = HttpContext.Current.Request.Cookies[csrfCookieName];
			if (cookie != null) {
				if (cookie.Value == secret) {
					// Valid CSRF check.  Clear the cookie and return.
					cookie.Expires = DateTime.Now.Subtract(TimeSpan.FromDays(1));
					cookie.Value = string.Empty;
					if (HttpContext.Current.Request.Browser["supportsEmptyStringInCookieValue"] == "false") {
						cookie.Value = "NoCookie";
					}
					HttpContext.Current.Response.SetCookie(cookie);
					return;
				}
			}

			throw new InvalidOperationException("Invalid CSRF check.");
		}
	}
}