Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

HttpHeaderAntiForgeryTokenAttribute #2

Merged
merged 6 commits into from

2 participants

@rmbrunet

1.- HttpHeaderAntiForgeryTokenAttribute
2.- Substituted the SimplePostVariableParameterBindingAttribute

rmbrunet added some commits
@rmbrunet rmbrunet Implemented the HttpHeaderAntiForgeryAttribute
1.- HttpHeaderAntiForgeryTokenAttribute
2.- Substituted the SimplePostVariableParameterBindingAttribute
29482fe
@rmbrunet rmbrunet Merge remote-tracking branch 'upstream/master'
Conflicts:
	MVC4/PersonaMVC4Example/Controllers/PersonaController.cs
	MVC4/PersonaMVC4Example/Views/Account/Login.cshtml
c8ad1aa
@rmbrunet rmbrunet Synchronizing with remote...
eliminating SimplePostParameterBinding
87d348e
@rmbrunet rmbrunet Trying again d8c4abb
@rmbrunet rmbrunet Merge branch 'master' of https://github.com/shanselman/AspNetPersonaId
Conflicts:
	MVC4/PersonaMVC4Example/Controllers/PersonaController.cs
15c9d6c
@rmbrunet rmbrunet Added EnsureSuccessStatusCode. ced528b
@shanselman
Owner

Cool. I'll make a few mods after this.

@shanselman shanselman merged commit dc9dcf6 into shanselman:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 28, 2013
  1. @rmbrunet

    Implemented the HttpHeaderAntiForgeryAttribute

    rmbrunet authored
    1.- HttpHeaderAntiForgeryTokenAttribute
    2.- Substituted the SimplePostVariableParameterBindingAttribute
  2. @rmbrunet

    Merge remote-tracking branch 'upstream/master'

    rmbrunet authored
    Conflicts:
    	MVC4/PersonaMVC4Example/Controllers/PersonaController.cs
    	MVC4/PersonaMVC4Example/Views/Account/Login.cshtml
  3. @rmbrunet

    Synchronizing with remote...

    rmbrunet authored
    eliminating SimplePostParameterBinding
  4. @rmbrunet

    Trying again

    rmbrunet authored
Commits on Jan 29, 2013
  1. @rmbrunet

    Merge branch 'master' of https://github.com/shanselman/AspNetPersonaId

    rmbrunet authored
    Conflicts:
    	MVC4/PersonaMVC4Example/Controllers/PersonaController.cs
  2. @rmbrunet
This page is out of date. Refresh to see the latest.
View
4 .gitignore
@@ -5,4 +5,6 @@ Packages
*.suo
# mstest test results
-TestResults
+TestResults
+MVC4/PersonaMVC4Example/App_Data/aspnet-PersonaMVC4Example-20120928074626.mdf
+MVC4/PersonaMVC4Example/App_Data/aspnet-PersonaMVC4Example-20120928074626_log.ldf
View
BIN  MVC4/PersonaMVC4Example/App_Data/aspnet-PersonaMVC4Example-20120928074626.mdf
Binary file not shown
View
BIN  MVC4/PersonaMVC4Example/App_Data/aspnet-PersonaMVC4Example-20120928074626_log.ldf
Binary file not shown
View
8 MVC4/PersonaMVC4Example/Controllers/PersonaController.cs
@@ -15,20 +15,17 @@
namespace PersonaMVC4Example.Controllers
{
- [SimplePostVariableParameterBinding]
+ [HttpHeaderAntiForgeryTokenAttribute]
public class PersonaController : ApiController
{
// POST api/persona
[HttpPost][ActionName("login")]
- public async Task<HttpResponseMessage> Login(string assertion)
+ public async Task<HttpResponseMessage> Login([FromBody] string assertion)
{
if (assertion == null)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
- var cookies = Request.Headers.GetCookies();
- string token = cookies[0]["__RequestVerificationToken"].Value;
- //TODO What do I do with this?
using (var client = new HttpClient())
{
@@ -39,6 +36,7 @@ public class PersonaController : ApiController
}
);
var result = await client.PostAsync("https://verifier.login.persona.org/verify", content);
+ result.EnsureSuccessStatusCode();
var stringresult = await result.Content.ReadAsStringAsync();
dynamic jsonresult = JsonConvert.DeserializeObject<dynamic>(stringresult);
if (jsonresult.status == "okay")
View
37 MVC4/PersonaMVC4Example/Filters/HttpHeaderAntiforgeryTokenAttribute.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Net.Http; //HttpRequestMessageExtensions
+using System.Net.Http.Headers;
+using System.Web.Helpers;
+using System.Web.Http;
+using System.Net;
+using System.Web.Mvc;
+
+namespace PersonaMVC4Example {
+ public class HttpHeaderAntiForgeryTokenAttribute : System.Web.Http.Filters.AuthorizationFilterAttribute {
+ static string _tokenKey = AntiForgeryConfig.CookieName;
+
+ public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) {
+ if (actionContext == null) {
+ throw new ArgumentNullException("actionContext");
+ }
+
+ try {
+
+ CookieHeaderValue cookie = actionContext.Request.Headers.GetCookies(_tokenKey).FirstOrDefault();
+ var cookieToken = cookie != null ? cookie[_tokenKey].Value : null;
+
+ string headerToken = actionContext.Request.Headers.GetValues(_tokenKey).First();
+ System.Web.Helpers.AntiForgery.Validate(cookieToken, headerToken); // Will throw HttpAntiForgeryException
+ }
+ catch {
+ actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) {
+ Content = new StringContent("Invalid or Missing AntiForgery Token")
+ };
+ }
+ return;
+ }
+ }
+}
View
176 MVC4/PersonaMVC4Example/ModelBinders/SimplePostVariableParameterBinding.cs
@@ -1,176 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Metadata;
-using System.Linq;
-using System.Globalization;
-
-namespace Westwind.Web.WebApi
-{
- /// <summary>
- /// A Custom HttpParameterBinding to bind multiple parameters from request body
- /// </summary>
- public class SimplePostVariableParameterBinding : HttpParameterBinding
- {
- private const string MultipleBodyParameters = "MultipleBodyParameters";
-
- public SimplePostVariableParameterBinding(HttpParameterDescriptor descriptor)
- : base(descriptor)
- {
- }
-
- /// <summary>
- /// Check for simple binding parameters in POST data. Bind POST
- /// data as well as query string data
- /// </summary>
- /// <param name="metadataProvider"></param>
- /// <param name="actionContext"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
- HttpActionContext actionContext,
- CancellationToken cancellationToken)
- {
- string stringValue = null;
-
- NameValueCollection col = TryReadBody(actionContext.Request);
- if (col != null)
- stringValue = col[Descriptor.ParameterName];
-
- // try reading query string if we have no POST/PUT match
- if (stringValue == null)
- {
- var query = actionContext.Request.GetQueryNameValuePairs();
- if (query != null)
- {
- var matches = query.Where(kv => kv.Key.ToLower() == Descriptor.ParameterName.ToLower());
- if (matches.Count() > 0)
- stringValue = matches.First().Value;
- }
- }
-
- object value = StringToType(stringValue);
-
- // Set the binding result here
- SetValue(actionContext, value);
-
- // now, we can return a completed task with no result
- TaskCompletionSource<AsyncVoid> tcs = new TaskCompletionSource<AsyncVoid>();
- tcs.SetResult(default(AsyncVoid));
- return tcs.Task;
- }
-
-
- /// <summary>
- /// Method that implements parameter binding hookup to the global configuration object's
- /// ParameterBindingRules collection delegate.
- ///
- /// This routine filters based on POST/PUT method status and simple parameter
- /// types.
- /// </summary>
- /// <example>
- /// GlobalConfiguration.Configuration.
- /// .ParameterBindingRules
- /// .Insert(0,SimplePostVariableParameterBinding.HookupParameterBinding);
- /// </example>
- /// <param name="descriptor"></param>
- /// <returns></returns>
- public static HttpParameterBinding HookupParameterBinding(HttpParameterDescriptor descriptor)
- {
- var supportedMethods = descriptor.ActionDescriptor.SupportedHttpMethods;
-
- // Only apply this binder on POST and PUT operations
- if (supportedMethods.Contains(HttpMethod.Post) ||
- supportedMethods.Contains(HttpMethod.Put))
- {
- var supportedTypes = new Type[] { typeof(string),
- typeof(int),
- typeof(decimal),
- typeof(double),
- typeof(bool),
- typeof(DateTime),
- typeof(byte[])
- };
-
- if (supportedTypes.Where(typ => typ == descriptor.ParameterType).Count() > 0)
- return new SimplePostVariableParameterBinding(descriptor);
- }
-
- return null;
- }
-
-
- private object StringToType(string stringValue)
- {
- object value = null;
-
- if (stringValue == null)
- value = null;
- else if (Descriptor.ParameterType == typeof(string))
- value = stringValue;
- else if (Descriptor.ParameterType == typeof(int))
- value = int.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(Int32))
- value = Int32.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(Int64))
- value = Int64.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(decimal))
- value = decimal.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(double))
- value = double.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(DateTime))
- value = DateTime.Parse(stringValue, CultureInfo.CurrentCulture);
- else if (Descriptor.ParameterType == typeof(bool))
- {
- value = false;
- if (stringValue == "true" || stringValue == "on" || stringValue == "1")
- value = true;
- }
- else
- value = stringValue;
-
- return value;
- }
-
- /// <summary>
- /// Read and cache the request body
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- private NameValueCollection TryReadBody(HttpRequestMessage request)
- {
- object result = null;
-
- // try to read out of cache first
- if (!request.Properties.TryGetValue(MultipleBodyParameters, out result))
- {
- var contentType = request.Content.Headers.ContentType;
-
- // only read if there's content and it's form data
- if (contentType == null || contentType.MediaType != "application/x-www-form-urlencoded")
- {
- // Nope no data
- result = null;
- }
- else
- {
- // parsing the string like firstname=Hongmei&lastname=ASDASD
- result = request.Content.ReadAsFormDataAsync().Result;
- }
-
- request.Properties.Add(MultipleBodyParameters, result);
- }
-
- return result as NameValueCollection;
- }
-
- private struct AsyncVoid
- {
- }
- }
-}
View
20 MVC4/PersonaMVC4Example/ModelBinders/SimplePostVariableParameterBindingAttribute.cs
@@ -1,20 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Http.Controllers;
-using Westwind.Web.WebApi;
-
-namespace PersonaMVC4Example
-{
- public class SimplePostVariableParameterBindingAttribute : Attribute, IControllerConfiguration
- {
- public void Initialize(HttpControllerSettings controllerSettings,
- HttpControllerDescriptor controllerDescriptor)
- {
- controllerSettings.ParameterBindingRules.Insert(0,
- new Func<HttpParameterDescriptor, HttpParameterBinding>(
- d => new SimplePostVariableParameterBinding(d)));
- }
- }
-}
View
13 MVC4/PersonaMVC4Example/PersonaMVC4Example.csproj
@@ -17,9 +17,12 @@
<MvcBuildViews>false</MvcBuildViews>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
- <IISExpressAnonymousAuthentication />
- <IISExpressWindowsAuthentication />
- <IISExpressUseClassicPipelineMode />
+ <IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
+ <IISExpressWindowsAuthentication>enabled</IISExpressWindowsAuthentication>
+ <IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
+ <IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
+ <IISExpressWindowsAuthentication>enabled</IISExpressWindowsAuthentication>
+ <IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
@@ -166,13 +169,12 @@
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\PersonaController.cs" />
+ <Compile Include="Filters\HttpHeaderAntiforgeryTokenAttribute.cs" />
<Compile Include="Filters\InitializeSimpleMembershipAttribute.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Helpers\PersonaAuthenticationClient.cs" />
- <Compile Include="ModelBinders\SimplePostVariableParameterBinding.cs" />
- <Compile Include="ModelBinders\SimplePostVariableParameterBindingAttribute.cs" />
<Compile Include="Models\AccountModels.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -292,6 +294,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
+ <Folder Include="ModelBinders\" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />
View
7 MVC4/PersonaMVC4Example/Views/Account/Login.cshtml
@@ -56,9 +56,12 @@
function onAssertion(assertion) {
if (assertion) {
$.ajax({ /* <-- This example uses jQuery, but you can use whatever you'd like */
+ headers: { // Pass the Token in a header value.
+ '__RequestVerificationToken': $("input[name='__RequestVerificationToken']").val()
+ },
type: 'POST',
- url: '/api/persona/login', // This is a URL on your website.
- data: { assertion: assertion, },
+ url: '/api/persona/login', // This is a URL on your website.
+ data: { '': assertion, }, //Use this format to make it work with the [FromBody] WebApi Attribute http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-1
success: function (res, status, xhr) { window.location.reload(); },
error: function (res, status, xhr) { alert("login failure" + res); }
});
Something went wrong with that request. Please try again.