Programmatic Configuration

Apr 25, 2014 at 3:03 AM
Edited Apr 25, 2014 at 3:04 AM
Is there any way to configure NWebSec programatically at runtime? I've been trying the following code but I can't change the config since it throws an error saying the config is read only.
            if (RoleEnvironment.IsAvailable)
            {
                var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["HttpsIn"];
                string baseUri = String.Format("{0}://{1}",
                    endpoint.Protocol, endpoint.IPEndpoint.Address);
                HttpHeaderSecurityConfigurationSection nWebSecConfig = ConfigHelper.GetConfig();
                var allowedUrls = nWebSecConfig.RedirectValidation.AllowedUris;
                RedirectUriElementCollection redirectUrls = nWebSecConfig.RedirectValidation.RedirectUris;
                RedirectUriConfigurationElement azureHostUri = new RedirectUriConfigurationElement();
                azureHostUri.RedirectUri = new Uri(baseUri);
                List<string> updatedAllowedUrls = new List<string>();
                updatedAllowedUrls.Add(baseUri);
                foreach (var allowedUrl in allowedUrls)
                {
                    updatedAllowedUrls.Add(allowedUrl);
                }
                nWebSecConfig.RedirectValidation.AllowedUris = updatedAllowedUrls;
                RedirectUriElementCollection updatedRedirectUrls = new RedirectUriElementCollection();
                updatedRedirectUrls.Add(azureHostUri);
                foreach (RedirectUriConfigurationElement redirectUrl in redirectUrls)
                {
                    updatedRedirectUrls.Add(redirectUrl);
                }
                nWebSecConfig.RedirectValidation.RedirectUris = updatedRedirectUrls;
}

I also tried using OWIN but could not get it working so I rolled back.

The reason I am trying this is that when deploying to an Azure cloud services staging environment the IP address or hostname of the machine can't be known in advance and therefore can't be set in the web.config. I was hoping to determine the IP address of the host using Microsoft.WindowsAzure.ServiceRuntime and the above code and thereby configure redirect validation at runtime.

Any ideas how I may do this are appreciated and thanks for sharing the library!
Coordinator
Apr 26, 2014 at 1:05 PM
Edited Apr 26, 2014 at 1:07 PM
Hi, and thanks for the feedback. Yes, the configuration section is read only, that's all handled by the configuration magic in the framework.

For the record, redirect validation will
...validate all HTTP responses with a status code of 3xx, except 304 (Not Modified). Redirects to relative URIs are allowed, as well as redirects to the same site — meaning the same scheme/host/port.
So same site redirects would be allowed event though you enable redirect validation without any config. Are you getting RedirectValidationExceptions? In that case, could you provide an example of address the app is running on, and where it tries to redirect?

With Owin, you could configure this when the Startup class is run, but I'm not sure that you can get a hold of the (staging) hostname at that point in time.
Apr 28, 2014 at 2:27 AM
Thanks for the reply.

Here is the exception that I observed.

Server Error ¡n ‘/’ Application.
A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect:
https://17.66.58.83/
Description: An unhandled exception occurred during the execution of the current web request- Please review the stack trace for more information about the error and where it originated in the code
Exception Details: NWebsec.CoreExceptionsRedirectValidationException: A potentially dangerous redirect was detected. Add the destination to the whitelistin configuration it the redirect was intended Offending redirect: https://17.66.58.83/
Source Error:


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below
Stack Trace:
[RedirectValidationException: A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect: https://17.66.58.83
NWebsec .Core. RedirectValidator.ValidateRedirect(1nt32 statusCode, String locationHeader, Un requestAuthority, IRedirectValidationConfiguration config) +358
NWebsec.Helpers..RedirectValidationHelper.ValidatelfRedirect(I-tttpContextBase context) +284
NWebsec.Modules.HttpHeaderSecurityModule.app_EndRequest(Object sender, EventArgs e) +83
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep. Execute() +136
System.Web.HttpApplication . ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Version Information: Microsoft NET Framework Version:4.O.30319: ASP.NET Version:4.O.3031934009
Staging Server IP Address = 17.66.58.83
Production Server IP Address = 65.45.126.186
I worked around the issue for the time being by adding the following.
  <redirectValidation enabled="true">
    <add allowedDestination="https://www.myproductiondomain.com/"/>
<add allowedDestination="https://localhost/"/>
<add allowedDestination="https://2601233572354659864a9cce326f4a64.cloudapp.net/"/>
<add allowedDestination="https://17.66.58.83/"/>
  </redirectValidation>

As I said I tried configuring usung OWIN and by using the Azure RoleEntryPoint.OnStart to obtain the IP address/hostname of the cloudservice instance for the current deployment. I could not yet get that working to properly and find out if that technique is indeed viable. I am using Sitefinity CMS so I am not sure if my OWIN issues could be related to Sitefinity. I'll keep testing through this week and if I get any progress I'll provide and update.
Apr 28, 2014 at 7:55 AM
Edited Apr 28, 2014 at 7:57 AM
I should further add that I was trying to make sure the entire site is delivered over https by using the following code in Global.asax

http://stackoverflow.com/questions/47089/best-way-in-asp-net-to-force-https-for-an-entire-site
        protected void Application_BeginRequest(Object sender, EventArgs e){
            //http://stackoverflow.com/questions/47089/best-way-in-asp-net-to-force-https-for-an-entire-site
            switch (Request.Url.Scheme){
                case "https":
                    Response.AddHeader("Strict-Transport-Security", "max-age=300");
                    break;
                case "http":
                    var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
                    Response.Status = "301 Moved Permanently";
                    Response.AddHeader("Location", path);
                    break;
            }
        }

Coordinator
Oct 7, 2014 at 7:52 PM
Looking at this again, it seems you want to redirect from HTTP to HTTPS on the site? I'm sorry that I missed that. I added support for this in todays release, so you don't need to know the hostname in order to redirect to HTTPS.

HTH.
Oct 8, 2014 at 12:36 PM
Thanks,

Everything has been working fairly well for me since I raised this issue. I think I set <redirectValidation enabled="false">. I'll test out the new code and see if I can enable it now. And yes I just want to redirect from http to https for the site.
Coordinator
Oct 8, 2014 at 8:59 PM
Ok, good to hear that things have been working out apart from the redirects. I hope the redirects will work out for you now too.
Nov 9, 2014 at 6:48 PM
Edited Nov 9, 2014 at 6:49 PM
I just had a chance to deploy to Azure today. I observed the following exception

NWebsec.Core.Exceptions.RedirectValidationException: A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect: https://b96b63a606694f858812943fd76dca40.cloudapp.net/favicon.ico
Generated: Sun, 09 Nov 2014 19:33:13 GMT

NWebsec.Core.Exceptions.RedirectValidationException: A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect: https://b96b63a606694f858812943fd76dca40.cloudapp.net/favicon.ico
at NWebsec.Core.RedirectValidator.ValidateRedirect(Int32 statusCode, String locationHeader, Uri requestAuthority, IRedirectValidationConfiguration config)
at NWebsec.Helpers.RedirectValidationHelper.ValidateIfRedirect(HttpContextBase context)
at NWebsec.Modules.HttpHeaderSecurityModule.app_EndRequest(Object sender, EventArgs e)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Can I configure a wildcard for any sub domain of cloudapp.net?

So instead of specifying

<add allowedDestination="https://2601233572354659864a9cce326f4a64.cloudapp.net/"/>

I'd specify

<add allowedDestination="https://*.cloudapp.net/"/>

In this way it would not matter what Azure host the site was deployed on. Normally I am doing final testing in staging on the cloudapp.net subdomain before switching the virtual IP so that the https://www.myproductiondomain.com/ will resolve and be on the whitelist.
Coordinator
Nov 9, 2014 at 6:56 PM
Edited Nov 9, 2014 at 7:12 PM
Is you site running on http://b96b63a606694f858812943fd76dca40.cloudapp.net/favicon.ico and attempting a redirect to https? Or does you app live elsewhere?

Did you configure NWebsec to allow redirects to HTTPS?
<redirectValidation enabled="true">
  <allowSameHostRedirectsToHttps enabled="true" />
</redirectValidation>
You can check out the full documentation here.