Thursday, November 28, 2013

Deal with authentication in AngularJS

What is Authentication?

Authentication is the process of identifying a user that wants to access a protected resource. We use authentication is our everyday lives: ID cards, user names and passwords, security cards, etc. The process that comes next is called ‘Authorization’ and they are very strong related and sometimes confused. With ‘Authorization’, we can check for user rights and see if they have or not access to a specific resource after they have been authenticated. However, make no mistake; there could be no ‘Authorization’ without ‘Authentication’. In this article we will discuss about the process of identifying ‘who is this user’ using AngularJS.

Considerations

Remember that all actions take place on the client side, which means that the client has full control over the browser and can overpass security checks. Therefore, it is very important to make the verification on the back-end also.

Setting up client-side Routing

Here we can decide which pages will need authentication and set the routing for the application. A route is defined providing at least the template or templateUrl and the controller of that page. In addition, I have added the ‘access’ property with ‘allowAnonymous’ attribute. This way we now if the current route needs authentication or it is a free access page. In our example we have the ‘Login’ page which is accessible by anyone and the ‘MembersPage’ that needs authentication.

// in app.js
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);   myApp.config(function ($httpProvider, $routeProvider) {
       window.routes = {
            '/Login':
{ templateUrl: '/Account/Login',
  controller: 'AccountController',
  access : {allowAnonymous : true}
},
            '/MembersPage:
{ templateUrl: '/Home/SomePage,
  controller: SomePageController',
  access: {allowAnonymous:false}}};
        for (var path in window.routes) {
            $routeProvider.when(path, window.routes[path]);
        }
        $routeProvider.otherwise({ redirectTo: '/Login' });
    });   

The next thing to do is to recognize an authenticated user and check if it has access to the routes.

Recognize an authenticated user

There are several ways for doing that but I prefer using the power of AngularJS throughout the use of ‘Services’. Therefore, I have created a ‘UserService’ where we store the current user name and a value-indicating if is authenticated or not.
// in UserService.js
myApp.factory('userService', function () {
    var user = {
        isLogged: false,
        username: '',       
    };

    var reset = function() {
        user.isLogged = false;
        user.username = '';
    };

    return {
        user: user,
        reset : reset
    };
});

After we have the service in place, it is time to use it and implement the check functionality for a route. There are several methods that intercept the route change event, but we are interested only in those that occur before the user was redirected so we can check if is authenticated: ‘$routeChangeStart’, ‘$locationChangeStart’. Here we can check if the route that the user is going to allows anonymous access and if the user is logged in. If the case of failure, we can display an error message and redirect the user to the login page.

// in RootController.js
myApp.controller('RootController',
  function ($scope, $route, $routeParams, $location, $rootScope, authenticationService, userService, toaster) {
     $scope.user = userService.user;
     $scope.$on('$routeChangeStart', function (e, next, current) {               
         if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) {
                    $location.path("/Login");                   
                }
            });

            $scope.logout = function () {
                authenticationService.logout()
                    .success(function (response) {
                        userService.reset();                       
                        toaster.pop("info", 'You are logged out.', '');
                    });
            };
           
 $rootScope.$on("$locationChangeStart", function (event, next, current) {
  for (var i in window.routes) {
    if (next.indexOf(i) != -1) {
     if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) {
           toaster.pop("error", 'You are not logged in!', '');
              $location.path("/Login");                                                 
                        }
                    }
                }
            });
        });


Authentication Service

This service provides a way of communicating with the server and sets up the login status. We are interested in login/logout methods for the moment. On the back-end it is used a Web API service.
The login method is a post request sending the ‘login’ data consisting of the username and password. Notice also the ‘RequestVerificationToken’ that is used to avoid cross-site request forgery attacks.

//in AuthenticationService.js
myApp.factory('authenticationService',
    function ($http, $log, $location) {
        return {
            login: function (login, antiForgeryToken) {
                return $http({
                    method: 'POST',
                    url: '/api/Account/AuthenticateUser',
                    data: login,
                    headers: { 'RequestVerificationToken': antiForgeryToken }
                });
            },
            logout: function () {
                return $http.post('/api/Account/Logout');
            }
        };
    });


Putting up all together

The only thing that remains is to create a view to collect login information and a controller where we can use the authentication service and the user service together.
A very simple login form would look like the example below. We have three input fields wrapped up in a form.

//in Login.cshtml
@model Model.LoginModel
@{ Layout = null; }
@functions {
  private String GetAntiForgeryToken()
  {
    string cookieToken, formToken;
    AntiForgery.GetTokens(null, out cookieToken, out formToken);
    return cookieToken + ":" + formToken;
  }
}

<div class="container">
  <form name="loginForm" class="form-signin">
    <input id="antiForgeryToken"
           data-ng-model="antiForgeryToken"           
           data-ng-init="antiForgeryToken='@GetAntiForgeryToken()'" type="hidden"/>
    <h2 class="form-signin-heading">Authentication</h2>
    <br />
    <input type="email" required="required" name="username" class="form-control"
      ng-model="userData.username" placeholder="Email address" />
    <input type="password" required name="password" class="form-control"
      ng-model="userData.password" placeholder="Password" />
    <label class="checkbox">
      <input type="checkbox" value="remember-me">Remember me</label>   
    <button type="submit" class="btn btn-lg btn-primary btn-block" ng-click="login(userData, loginForm)">Login</button>
  </form>
</div>

When the user clicks login button, the form data is sent to the account controller. Using the authentication service, the data is sent in a POST request. In case of success we use the user service to store the data and redirect the user to the desired page, otherwise we show an error message and keep the user on the login page.

// in AccountController.js
myApp.controller('AccountController',
    function AccountController($scope, $cookies, $log, $location, authenticationService, toaster, userService) {

  $scope.login = function (userData, loginForm) {
      if (loginForm.$valid) {
          authenticationService.login(userData, $scope.antiForgeryToken)
              .success(function (response) {
                 if (response.status) {
                    userService.user.username = response.data.userName;
                    userService.user.isLogged = response.data.isLogged;
                    toaster.pop('success', 'You are signed in!', '', 2000, true);
                    $location.path("/MembersPage");
                    } else

{
         toaster.pop('error', 'Invalid username or password!', '', 2000, true);}
}).error(function (data, status, headers, config) {
       $log.info(data);});}
  };
});


This is all it takes to have a rudimentary authentication implementation with AngularJS.

Tuesday, May 8, 2012

Your first WCF Service - Step by step

Today I'm gonna make a demo for those who want to step into the world of WCF. I'm not going into details about what is WCF. In short, it is a platform to build distributed applications using a unified modeling language.

Step 1. Create a new WCF Service Application
Open Visual Studio -> File-> New -> Project. Select from the WCF panel a WCF Service Application and give it a name. Mine is called Service1.


Step 2. Configure the service using the confiugration file
In the newly created project double click the Web.config file. Here we will have to add a service element an endpoint element and a binding. This step is not mandatory because Wcf creates by default an endpoint and a service, but for the sake of this exercise I will create new elements. 

The Binding - this is where we specify what protocol do we use (http, tcp, etc.), how our data is formatted, what security do we use for sending the message and other things. So first we create a bindings element where we will use a wsHttpBinding like so:
<bindings>
<wsHttpBinding>
<binding name="MyBinding">

<security mode="None">
</security>

</binding>
</wsHttpBinding>
</bindings>


The Service - here we add our endpoints and configure the service behavior if we have one
<services>
<service

</service>
</services>

The EndPoints - The endpoint is a structure where we have to specify the Address, Binding  and Contract.
Address - the location (url) where we find the endpoint
Binding - the protocol and other settings that are used to transport data
Contract - the interface (set of operations) that is exposed through this endpoint.
Inside the <service> tag add the definition of the endpoint:
<service name="WcfServiceBlog.Service1">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyBinding" contract="WcfServiceBlog.IService1">
</service>
</endpoint>

Our service is ready.

Step 3. Create a client that consumes the service
Create a new console application. Expand the project, Right click on References -> Add Service Reference
A popup should appear where you have to enter the url of the service. Because the service is in the same solution you can click the Discover button.

After your service is discovered, select it and click Ok. In thi moment the tools of visual studio would create the necessary proxy classes so that we can use the service.
In the Main program write the following code:
static void Main(string[] args)
{
using (ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client())
{
Console.WriteLine(proxy.GetData(10));
}
Console.ReadLine();
}

Set your client application as a startup project. Right click on project -> Set as startup project.
Run your first wcf service application! :)

Friday, February 24, 2012

WCF NetTcp in IIS

Today I will make a short demo about hosting wcf services with nettcpbinding in iis.
There are cases when is more suited for your service to use a nettcpbinding for different reasons: speed, reliability, etc.
But in this case you are limitted to choose the hosts of your service from console app, windows service. So what if you want to host your service in iis and still expose nettcpbindings ?

So here are a few stept that must be done before we can use our service. For a more in-depth description check this post IIS 7.0 and WAS

Step 1. Enable Non-Http protocols
Go to Control Panel->Programs->Turn Windows features on/off and under .NetFramework 3.5.1 be sure to tick "Non-Http activation" (remember that iis supports only http)


Step 2. Enable WAS and PortSharing.
The previous step will make available some services (wcf services by the way) that will help us. So go now in your services list: Task Manager->Services tab and be sure that the following services are running:

WAS - is the Windows process activation service
NetTcpPortSharing -  is the WCF TCP port sharing service. It implements a centralized TCP listener so that multiple processes can listen on the same TCP port. This service is available even if IIS 7.0 is not installed.
NetTcpActivator - is the WCF TCP Activation Service. It communicates TCP activation requests to WAS.
 
Step 3. Create a WCF Service with a NetTcpBinding and create the endpoints.

Create the binding in the bindings tag, and then create 2 endpoints. One for your contract and one mex.
Note: If you don't create the mex endpoint, you won't be able to add a reference in your project.
 
 
Step 4. Publish the service in iis and configure it

Right click on the service->Publish. Be sure to tick 'Mark as IIS application'
In IIS, expand your newly created application, go in content view and browse your service. You will get this error:
 
This tells us that currently we don't have support for tcp protocol so here is what you have to do in order to eneable it: in iis, right click on application->Manage Application->Advanced Settings and add "net.tcp" next to http and then click ok.
 Now the error should be gone
 
Step 5. Add a reference to your project
And that's it :).

Thursday, December 15, 2011

Working with EndPoint Behavior in WCF

Today I will make a short demo about how you can extend your Wcf service with custom behaviors. Wcf provides many ways of customizing the runtime behavior of your service. For a more detailed explanation please refer to msdn magazine .

First of all, let's find out who the players are. We will be working in the 'ServiceModelLayer' with the 'Dispatcher' in the context of the service host and the 'Proxy' in the context of a client. Their job is to translate between WCF Message Objects and .Net Method Calls.                              

WCF runtime


This pair dispatcher/proxy follow a sequence of steps during which you can insert your own code for message transformation, serialization, parameters inspection and so on.

Here is a list of 'points' where you can plug in and insert your code by implementing the following interfaces.


StageInterceptor InterfaceDescription
Parameter Inspection IParameterInspector Called before and after invocation to
inspect and modify parameter values.
Message Formatting IDispatchMessageFormatter
IClientFormatter
Called to perform serialization and
deserialization.
Message Inspection IDispatchMessageInspector
IClientMessageInspector
Called before send or after receive to
inspect and replace message contents.
Operation Selection IDispatchOperationSelector
IClientOperationSelector
Called to select the operation to invoke for the given message.
Operation Invoker IOperationInvoker Called to invoke the operation.


So now we know what kind of extensions we have and whom they apply to. In order to apply an extension (from the above list) we need to set up a behavior. There are 4 types of behaviors in wcf, each of them sharing this set of methods:
Validate - Called just before the runtime is built—allows you to perform custom validation on the service description.

AddBindingParameters - Called in the first step of building the runtime, before the underlying channel is constructed—allows you to add parameters to influence the underlying channel stack.
ApplyClientBehavior - Allows behavior to inject proxy (client) extensions. Note that this method is not present on IServiceBehavior.
ApplyDispatchBehavior - Allows behavior to inject dispatcher extensions.

One exception is that IServiceBehavior doesn't have an ApplyClientBehavior method because service behaviors can't be applied to clients.

Types of Behaviors


ScopeInterfacePotential Impact
ServiceEndpointContractOperation
ServiceIServiceBehavior✗✗✗✗
EndpointIEndpointBehavior✗✗✗
ContractIContractBehavior✗✗
OperationIOperationBehavior✗
Let's see now how the behavior and the extension get together.

My example comes from a silverlight application where I had to create a custom behavior in order to catch wcf exceptions. So to achieve this I used  IDispatchMessageInspector to change the status code of the reply to 200 (OK) and the IEndpointBehavior because I wanted to apply this extension only to this level.

Show me some code! :)

Step 1. Create the extension implementing IDispatchMessageInspector

public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
#region IDispatchMessageInspector Members

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
// Do nothing
return null;
}

public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
// Here the response code is changed to 200.
property.StatusCode = System.Net.HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
#endregion
}


Step 2. Create the behavior and apply the entension
public class FaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}


public void Validate(ServiceEndpoint endpoint)
{
}
public override Type BehaviorType
{
get { return typeof(FaultBehavior); }
}

protected override object CreateBehavior()
{
return new FaultBehavior();
}
#endregion
}


Step 3. Declare the behavior extension in the service config file

Inside the <system.serviceModel> create the <extensions> element if does not exist.

<extensions>
<behaviorExtensions>
  <add name="silverlightFaults" type="myservicename.FaultBehavior, myservicename, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>

NOTE: the type must be the fully qualified name of the assembly/class that you are using and must be declared on a single line, otherwise will not work (WCF known issue)

Step 4. Create an end point behavior and add the extension
<behavior name="myFaultBehavior">
   <silverlightFaults />
 </behavior>

Step 5. Crate an endpoint and assign behavior configuration attribute

<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="MyHttpBinding"
  contract="IMyContract"
behaviorConfiguration="myFaultBehavior">

</endpoint>

And that's it! You can inspect the exceptions that come from a wcf service by using e.Error property in the completed event handler. 

Friday, December 9, 2011

Streaming in WCF


There are scenarios when you must be able to send or receive large amount of data or files using a service in your application. WCF supports streaming and I will show you how to achieve that.

There are 4 types of TransferMode in WCF

using System;namespace System.ServiceModel
{
    public enum TransferMode    

    {
        Buffered = 0,
        Streamed = 1,
        StreamedRequest = 2,
        StreamedResponse = 3,
    }
}


The default one is Buffered. This means that the sender/receiver cannot process the message until the whole data is in one place. We must set our binding to Streamed to enable streaming.

Next thing is to add an operation contract that must satisfy 2 conditions:
1. The parameter that holds the data to be streamed must be the only parameter in the method.
2. At least one of the types of the parameter and return value must be either Stream, Message, or IXmlSerializable.  

In short, this means that the method must have only one parameter which is a Stream, otherwise the return type must be Stream,Message, etc...

Step 1. Create a WCF service application
In VisualStudio, File->New Project->Wcf->Wcf Service Application

Step 2. Add an operation contract with a Stream parameter
Here is my service contract:
[ServiceContract]
public interface IService1
{
    [OperationContract]
    bool SendStream(Stream stream);
}

Step 3. Create a binding in the configuration file, which supports streaming

We have to set the transferMode to Streamed and increase the message size attributes. I have used a regular basicHttpBinding.

<bindings>
      <basicHttpBinding>
        <binding name="streaming" maxReceivedMessageSize="67108864" transferMode="Streamed">         
        </binding>
      </basicHttpBinding>
    </bindings>


After the binding is created, add the endpoint and service tags like in the image above.

Step 4. Implement the operation contract in Service.svc

public bool SendStream(Stream stream) 
{
    try
    {
         using (FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "file", FileMode.Create))
         {
             stream.CopyTo(fs);
          }
          return true;
      }
      catch (Exception ex)
      {
          return false;
       } 
}


Step 5. Critical step. 

 I lost many hours trying to understand why this almost complete configuration doesn't work with files larger than 3-4 MBytes.

The reason is that even if we enable streaming and we increase the message size, ASP.NET doesn't know about WCF limitations. So the solution is to add httpRuntime in system.web element:
<httpRuntime maxRequestLength="67108864"/>


Step 6. Create the client and consume the service
Create a simple console application and add a service reference of the created service. You must have a file called 'largefile' without any extension in the bin\debug\ folder of your console application. Mine has ~20 MBytes.


Now consume the service:

static void Main(string[] args)
        {
            try
            {
                using (ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client())
                {
                    using (FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "largefile", FileMode.Open))
                    {
                        var result = proxy.SendStream(fs);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

The result should be true, which means that the streaming was successful.
Happy coding! :)
Download code