summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs')
-rw-r--r--src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs53
1 files changed, 48 insertions, 5 deletions
diff --git a/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
index d33913a..6a898a1 100644
--- a/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
+++ b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.AspNet {
using System;
using System.Diagnostics.CodeAnalysis;
+ using System.Text;
using System.Web;
using System.Web.Security;
using DotNetOpenAuth.AspNet.Clients;
@@ -19,6 +20,11 @@ namespace DotNetOpenAuth.AspNet {
#region Constants and Fields
/// <summary>
+ /// Purposes string used for protecting the anti-XSRF token.
+ /// </summary>
+ private const string AntiXsrfPurposeString = "DotNetOpenAuth.AspNet.AntiXsrfToken.v1";
+
+ /// <summary>
/// The provider query string name.
/// </summary>
private const string ProviderQueryStringName = "__provider__";
@@ -166,7 +172,10 @@ namespace DotNetOpenAuth.AspNet {
string sessionId = Guid.NewGuid().ToString("N");
uri = uri.AttachQueryStringParameter(SessionIdQueryStringName, sessionId);
- var xsrfCookie = new HttpCookie(SessionIdCookieName, sessionId) {
+ // The cookie value will be the current username secured against the session id we just created.
+ byte[] encryptedCookieBytes = MachineKeyUtil.Protect(Encoding.UTF8.GetBytes(GetUsername(this.requestContext)), AntiXsrfPurposeString, "Token: " + sessionId);
+
+ var xsrfCookie = new HttpCookie(SessionIdCookieName, HttpServerUtility.UrlTokenEncode(encryptedCookieBytes)) {
HttpOnly = true
};
if (FormsAuthentication.RequireSSL) {
@@ -245,6 +254,19 @@ namespace DotNetOpenAuth.AspNet {
}
/// <summary>
+ /// Returns the username of the current logged-in user.
+ /// </summary>
+ /// <param name="context">The HTTP request context.</param>
+ /// <returns>The username, or String.Empty if anonymous.</returns>
+ private static string GetUsername(HttpContextBase context) {
+ string username = null;
+ if (context.User.Identity.IsAuthenticated) {
+ username = context.User.Identity.Name;
+ }
+ return username ?? string.Empty;
+ }
+
+ /// <summary>
/// Validates the request against XSRF attack.
/// </summary>
/// <param name="sessionId">The session id embedded in the query string.</param>
@@ -252,24 +274,45 @@ namespace DotNetOpenAuth.AspNet {
/// <c>true</c> if the request is safe. Otherwise, <c>false</c>.
/// </returns>
private bool ValidateRequestAgainstXsrfAttack(out string sessionId) {
+ sessionId = null;
+
// get the session id query string parameter
string queryStringSessionId = this.requestContext.Request.QueryString[SessionIdQueryStringName];
// verify that the query string value is a valid guid
Guid guid;
if (!Guid.TryParse(queryStringSessionId, out guid)) {
- sessionId = null;
return false;
}
- // get the cookie id query string parameter
+ // the cookie value should be the current username secured against this guid
var cookie = this.requestContext.Request.Cookies[SessionIdCookieName];
+ if (cookie == null || string.IsNullOrEmpty(cookie.Value)) {
+ return false;
+ }
+
+ // extract the username embedded within the cookie
+ // if there is any error at all (crypto, malformed, etc.), fail gracefully
+ string usernameInCookie = null;
+ try {
+ byte[] encryptedCookieBytes = HttpServerUtility.UrlTokenDecode(cookie.Value);
+ byte[] decryptedCookieBytes = MachineKeyUtil.Unprotect(encryptedCookieBytes, AntiXsrfPurposeString, "Token: " + queryStringSessionId);
+ usernameInCookie = Encoding.UTF8.GetString(decryptedCookieBytes);
+ }
+ catch {
+ return false;
+ }
- bool successful = cookie != null && queryStringSessionId == cookie.Value;
+ string currentUsername = GetUsername(this.requestContext);
+ bool successful = string.Equals(currentUsername, usernameInCookie, StringComparison.OrdinalIgnoreCase);
if (successful) {
// be a good citizen, clean up cookie when the authentication succeeds
- this.requestContext.Response.Cookies.Remove(SessionIdCookieName);
+ var xsrfCookie = new HttpCookie(SessionIdCookieName, string.Empty) {
+ HttpOnly = true,
+ Expires = DateTime.Now.AddYears(-1)
+ };
+ this.requestContext.Response.Cookies.Set(xsrfCookie);
}
sessionId = queryStringSessionId;