Search code examples
asp.net-mvc-3wif

Potentially dangerous Request.Form in WSFederationAuthenticationModule.IsSignInResponse


In my MVC3 site I've avoided setting requestValidationMode="2.0" with the new ValidateInput attribute, but now I'm trying to switch to WIF for authentication, and when the STS redirects back to my site, I'm getting the exception because WSFederationAuthenticationModule.IsSignInResponse is calling Request.Form instead of Request.Unvalidated().Form ... is there any way to deal with this without going to requestValidationMode="2.0" (which I really don't want to do).

Here's the stack trace, so you can see what I mean. My Controller's method never really gets called.

[HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (wresult="<trust:RequestSecuri...").]
   System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection) +8755668
   System.Web.HttpRequest.ValidateNameValueCollection(NameValueCollection nvc, RequestValidationSource requestCollection) +122
   System.Web.HttpRequest.get_Form() +114
   Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.IsSignInResponse(HttpRequest request) +21
   Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.CanReadSignInResponse(HttpRequest request, Boolean onPage) +121
   Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +78
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +148
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

Solution

  • The correct way of dealing with this is to add specific validator to the HttpRuntime, that knows how to detect valid security tokens.

    Look at any of the examples here: http://claimsid.codeplex.com/releases/view/62929

    Here's an excerpt from one of those (sample #5 t be specific which is also an MVC app):

    namespace FShipping
    {
        using System;
        using System.Web;
        using System.Web.Util;
        using Microsoft.IdentityModel.Protocols.WSFederation;
    
        public class WsFederationRequestValidator : RequestValidator
        {
            protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
            {
                validationFailureIndex = 0;
                if (requestValidationSource == RequestValidationSource.Form &&
                    collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
                {
                    if (WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage != null)
                    {
                        return true;
                    }
                }
    
                return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
            }
        }
    }
    

    Here's the config:

    <system.web> 
    ...   
       <httpRuntime requestValidationType="FShipping.WsFederationRequestValidator" />
    </system.web>