Sunday, September 20, 2015

ASP.Net SignalR IIS hosting


Recently I created a sample SignalR simple chat application. That included a hub class and the calling client in the same application i.e. when the client application is hosted, the hub get's hosted itself. You can check that article here. But after creating that, I realized that what if we need to have the hub and the client applications separately, say the hub is hosted as one application in IIS and the client application is hosted on another server. So decided to create these two as separate applications and see what configurations are required for them.

So let's start by creating the hub class. For this, we create a new empty asp.net application. Next, in order to make it a server hub class, we add references to the SignalR package using nuget package manager. This also includes the OWIN libraries so that the OWIN Starup class can be created for this.




Next, we add a class file to create a hub on the server and name it as ServerHub.cs. This will be having the same method which we had in our previous article of chat application i.e. BroadCastMessage. We will derive it from the Hub class. So the code will look like below:


 using Microsoft.AspNet.SignalR;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;

 namespace HubClass
 {
    public class ServerHub : Hub
    {
        public void BroadCastMessage(String msgFrom, String msg)
        {
            Clients.All.receiveMessage(msgFrom, msg);
        }
    }
 } 

Next, we add another class and name it as Startup.cs, which will be for OWIN startup class. We add the OwinStartup attribute and Configuration method. Here, an important point is needed to be considered. This is app.UseCors(CoreOptions.AllowAll), which is required for cross domain calls, between the hub and the client. If we hover over it, it's definition can be seen as:

Adds a CORS middleware to your web application pipeline to allow cross domain

So the code will look like thee following:



 using Microsoft.AspNet.SignalR;
 using Microsoft.Owin;
 using Microsoft.Owin.Cors;
 using Owin;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;

 [assembly: OwinStartup(typeof(HubClassStartup))]
 namespace HubClass
 {
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }
 }


So our server hub is now ready to be hosted in IIS. Open your IIS and create a new virtual application under the Default Website. We will name it as ServerHub and point it to location of our code. See the image below:



Now, start the website and click on Browse application to see the hub hosted. In order to make sure that the hub is hosted properly, add the suffix '/signalr/hubs' to the url of the application. This will load the hub proxy javascript file in the browser. See the image below:




So our hub is now ready to be called from a separate application. For this, we create another empty asp.net application and add an html page. All the client calling code will remain the same, except two changes are to be made. But before we that, we need to add reference to the signalr client libraries, including the javascript files. See the image below:




So our solution will look like the following:





The first change we make is the url reference to the javascript proxy file which will help in connecting to the server hub. This will be changed to the following:


     <script src="http://localhost/ServerHub/signalr/hubs"></script>

Note that we have added the base url where the hub is hosted, to the reference. The second change we make is, add the hub url to be of the same location, where we have the hub hosted. So it will be like the following:

$.connection.hub.url = "http://localhost/ServerHub/signalr/";

Rest of the code remain the same and can be checked at: http://dotnetfreakblog.blogspot.com/2015/02/chat-application-using-aspnet-signal-r.html 

That's it. Run the application in two different browsers and you can see the code in action. 




So this was how we can host the signalr hub on IIS as a separate application. Hope you enjoyed reading it. Happy coding...!!!

Saturday, September 19, 2015

SirgnalR - Error during negotiation request

While creating a SignalR sample application, i came across an issue related to request negotiation with the server. It was:  

Error during negotiation request

My scenario was that I had a SignalR hub which was hosted on IIS and a javascript client application which was connecting to this hub. So basically they were created as separate applications. In my case, the issue required a single line fix with the following code in the javascript client:


 $.connection.hub.url = "http://localhost/MyHub/signalr/";

Hope this helps others in case they face the same issue. Happy coding...!!!

Saturday, September 12, 2015

Implement Basic Authentication in ASP.Net Web API at Host level (IIS)


In our previous discussion, we discussed what are different ways to implement security in ASP.Net web-api. Before you proceed, I would recommend to go through that article on the link below first, as that will act as a kind of base for where and how we will implement the security.
In this discussion, we will be implementing basic authentication in web-api at the host level. 
As per MSDN, basic authentication is:



As per the above description, there is one limitation to the use of IIS as the host and implementing basic authentication at IIS level. This means, IIS uses Windows credentials to authenticate the users. So this implementation is suitable for any intranet applications, where the users have to access the application within the domain. 

To start with, we will create a new empty project using Empty ASP.Net Web -API template project. Let's name it as BasicAuthenticationIIS.


Next, we add a controller called as SampleController and inherit it from ApiController, to make it a WebAPI controller type. Also, we add a method named GetCurrentDateTime which will return current date and time as string to the user. So our controller will look like:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace BasicAuthenticationIIS.Controllers
{
    public class SampleController : ApiController
    {
        public String GetCurrentDateTime()
        {
            return DateTime.Now.ToString();
        }
    }
}


Next, we simply host the application in IIS. So open IIS, select " Default Web Site", right click and select the option "Add Application". Provide an Alias name to it and provide the physical path to the application directory. 

Browse the application and enter the path of the webapi and see the results. 
So this was without any security. Anyone who is not authenticated, can access the method. Let's add the authentication to the api. So we start by adding the settings in the config file. So we add the authentication mode to the web.config as Windows. 

<system.web>
    <authentication mode="Windows"></authentication>
</system.web>

Next, add the [Authorize] attribute on the method for which we need to add the security. So our method will look like:


[Authorize]
public String GetCurrentDateTime()
{
            return DateTime.Now.ToString();
}

Build the application. Next, go to IIS and select the option "Authentication".

Within this, select the Basic Authentication option, right click and Enable it.
That's it. Restart the application in IIS and browse the application. It asks for credentials. 
Cancel it and it says Un-Authorized.

Let's refresh and enter windows account credentials. 

Press Ok and see the results.

We can also create a sample application and test it. Create a new a Console application and write the following code:

WebRequest req = WebRequest.Create("http://localhost/BasicAuthSample/api/sample/GetCurrentDateTime");
req.Method = "GET";
req.ContentType = "text/xml";
byte[] authBytes = Encoding.UTF8.GetBytes("emailAddress:Password".ToCharArray());
req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes));
System.Net.WebResponse response = req.GetResponse();
System.IO.StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();


Run the application and see the results:



In case you do not send the credentials, it will throw an error of type WebException, which you can catch and check status code. The complete code will be like the following:


class Program
    {
        static void Main(string[] args)
        {
            try
            {
                WebRequest req = WebRequest.Create("http://localhost/BasicAuthSample/api/sample/GetCurrentDateTime");
                req.Method = "GET";
                req.ContentType = "text/xml";
                Byte[] authBytes = Encoding.UTF8.GetBytes((ConstantStruct.UserName + ":" + ConstantStruct.Password));
                req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes));
                req.Headers.Add("test", "test");

                System.NetWebResponse response = req.GetResponse();
                System.IOStreamReader reader = new StreamReader(response.GetResponseStream());
                Console.Write(reader.ReadToEnd());
            }
            catch (WebException ex)
            {
                var statusCode = ((HttpWebResponse)ex.Response).StatusCode;
                if (statusCode == HttpStatusCode.Unauthorized)
                {
                    Console.Write("Authorization failed.");
                }
            }
            Console.Read();
        }
    }

So this is how we can implement the host level (i.e. IIS), basic authentication in a web-api. Hope you enjoyed reading it. Happy coding...!!!

Thursday, September 10, 2015

Security in ASP.Net Web API

While exploring security options in asp.net web api, found many options on the web including the official ASP.Net Web API website. So explored it further and things became more clear. Finally decided to compile the understanding about this concept and hope it will help you also:

To start with we have to basic things/aspects about the security implementation. These are:


  • Authentication: Authentication is whether a user has proved his authenticity to access the web-api.The client request proves authenticity usually in the form of some kind of username and password. 
        For ex. an office may only allow people to enter, who is having any access card, to               enter office premises. If he is not, the system will not allow him to enter the office.
  • Authorization: Authorization on the other hand means, although being authenticated to access the web-api, should a user be allowed access a particular method of the web-api. 
         For ex. although a person may be allowed to enter the office he may still not have                  access to certain areas of the office, due to different department.This is the concept of          authorization. If you are not authorized, you will not be allowed to access the                          resource. 

Further, in order to implement the security we have two different points/level where we can implement the security. These are :

  1. Host Level:  Host is basically which is used to host the web-api. Host level options include the to use the Http Modules and OWIN middle-ware componentsHttp modules restrict to use IIS as the host option i.e. you can use the Http modules to implement security only if you are using IIS for hosting the web- api. On the other hand, to use OWIN middle-ware components we must use OWIN based hosting of the web api.

  2. ASP.Net Web API pipeline: This allows implementation within the asp.net web-api pipeline, rather then dependency on the hosting option used for it.This means they are host agnostic i.e. there implementation does not rely on the underlying hosting option. We may have IIS or OWIN based hosting and use any of the options available in this category. Some of the options available in this category include:
    • Use of Message Handlers
    • Use of Action Filters
    • Use of Authorization Filters
    • Use of Authentication Filters
So if we talk about what we discussed above, we can represent the different options in hierarchy as :



Host level options are executed before the request reaches the web-api. So when implemented, they get called earlier in the request cycle and may get called, even if the request is not aimed at the web-api resource. On the other hand, web-api level options are executed after the host and are more specific to the requests which are intended for the api.

For ex. when Http modules are used as an option to implement the authentication, it will be called for any type of incoming request to the web-server, even if it's not related to the web-api. On the other hand, option like Message handler (at web-api level), executes only for the requests which are aimed at the web-api.

Host level options are less preferable as they restrict the type of host used. Options at the web-api level provide more granular level of permissions which means they can be applied at the Controller level or the Method level in api. 

For ex. Authentication filters are a new feature in ASP.Net Web-API 2. This option is available at the web-api level and provides more granular control over the security, as it allows the filters to be applied at the controller and the individual method levels as well.

So this is about the basic concepts about security implementation in asp.net web-api. I hope you enjoyed reading it. Any feedback is welcome. Happy coding...!!!