Saturday, 30 November 2013

A Look at the new Identity System in ASP.NET

One of the key features added to ASP.NET core with the release of Visual Studio 2013 is the new Identity System. If you create a new ASP.NET project, may it be a Web Forms or an MVC project, you will find the default authentication type selected as "Individual User Accounts".



The individual user authentication type creates authentication system based on the Identity system, which looks greatly simplified when compared with the Membership system we had in earlier version. The default project template includes the following references (also available via NuGet packages with same names):

  • Microsoft.AspNet.Identity.Core: Consists of the core classes and interfaces for identity system
  • Microsoft.AspNet.Identity.EntityFramework: Consists of classes implemented for Identity system using ADO.NET Entity Framework

The default templates make use of Entity Framework to persist the user’s information in a SQL Server database. The default database used is an MDF file.

Classes and Setup:
The project template includes Owin and Katana. In the authorization configuration, we see the following setings applied to setup cookie based authentication system on Owin:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

It makes the authentication system sharable across Web forms, MVC, Web API and SignalR without adding any additional code. The authentication configuration is called from Owin start-up class. In the models folder of the project, a file with following code is added for us:
public class ApplicationUser : IdentityUser
{
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }
}

As we see, this file includes two classes:

  • ApplicationUser: Inherited from Microsoft.AspNet.Identity.EntityFramework.IdentityUser. The IdentityUser class is inherited from the interface IUser. Any user class in the identity system must inherit from this interface. The class IdentityUser includes all necessary properties needed for a user account, like UserName, PasswordHash, SecurityStamp. This class allows us to add our own properties to a user’s profile. For example, if your web site needs to capture e-mail ID and phone number of the user, you can add them to this page. The IdentityUser class also includes navigation properties for UserRoles, UserClaims and UserLogins. The UserLogin entity is used to store information when a user is logged in using an external authentication provider, like Google, Microsoft, Twitter or Facebook.
  • ApplicationDbContext: It is the Entity Framework code-first DbContext class to create the database with necessary tables. It is extended from IdentityDbContext, the DbContext class defined in Microsoft.AspNet.Identity.EntityFramework namespace. It includes DbSets for User and Role. This class allows us to add our own DbSets to the database being created.

Once the application is executed, a SQL server MDF file is created with the following tables:




User management:
To manage the users and their data, the application uses the following two classes:

  • UserStore: A class in Microsoft.AspNet.Identity.EntityFramework namespace. It is responsible for all database operations related to managing users. It needs a DbContext for its work; we generally pass in an instance of the IdentityDbContext. This class implements six interfaces: IUserStore, IUserPasswordStore, IUserLoginStore, IUserClaimStore, IUserRoleStore and IUserSecurityStampStore. Each of them has a specific purpose. IUserStore is for creating, finding, updating and deleting the user information; IUserPasswordStore is for managing password and so on. While writing a custom Identity system, IUserStore is the least interface to be implemented. All methods declared in all of these interfaces are asynchronous and they return Task.
  • UserManager: This class is defined in the Microsoft.AspNet.Identity.Core assembly. It needs an instance of IUserStore type. The UserManager can be viewed as a repository that calls specific methods of UserStore to manage users for the application. As in UserStore, methods of UserManager are also asynchronous.
The UserManager is instantiated as follows:
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

Let’s see how a new user registration works. In the AccountController of the MVC project, we find the following code in the Register action method (Similar code can be found in Register.aspx.cs of Web Forms project):
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
    await SignInAsync(user, isPersistent: false);
    return RedirectToAction("Index", "Home");
}

The UserManager.CreateAsync() method calls UserStore.CreateAsync to store the user information in Database. Once the registration is succeeded, a call to SignInAsync is made to authenticate the user. Following is the code inside SignInAsync method:
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

The AuthenticationManager used here is the Authentication object of the current Owin context. The first statement clears any external cookies in the current application context. Then it asks the UserManager to create a claims-based identity for the current user and then the obtained claims-based identity object is set to the current Owin context.

The Login action method differs by just one statement, it is shown below:

var user = await UserManager.FindAsync(model.UserName, model.Password);

The FindAsync method returns null if the user’s credentials are not valid. If credentials are valid, it returns all information about the user. Once the user is found, a claims-based identity object of the user is set to the Owin context.

LogOff is a straight forward implementation. It just calls the SignOut method of the Authentication object of the Owin context:

Context.GetOwinContext().Authentication.SignOut();

Similarly, the template also generates code for changing password, removing user account and to handle external login accounts. We will see how the identity system manages external logins in a future post.

Happy coding!

Tuesday, 19 November 2013

“Controller as” Syntax in Angular JS 1.2

Angular JS 1.2 was released around 10 days back and 1.2.1 was released last week with a few fixes. The new release includes a number of significant features. One of them is the controller as syntax.

The classic way of creating a controller in Angular JS is by injecting $scope into it. It creates a new scope corresponding to the controller by inheriting from the parent scope. Angular 1.2 makes it possible to create a controller without injecting $scope into it. Objects and functions of the view are added to controller itself and they are referred in the view using an alias. The scope still exists; it is created and maintained behind the scenes for us. So, we still get the two-way data binding on all objects added to the controller.

Following is a simple controller and the page using it:

function HomeCtrl(){
    this.name="Ravi";
}

<div ng-app ng-controller="HomeCtrl as vm">
 <input type="text" ng-model="vm.name" />
 <br  />
 <span>{{vm.name}}</span>
</div>


We don’t see our good friend $scope in the controller, but the controller looks clean and independent now.

Using controller as with routing
To use controller as with routing in multiple views, we need to specify a parameter while configuring the route. Following snippet shows the syntax:

app.config(function($routeProvider){
    $routeProvider.when('/first', { templateUrl: 'first.html', controller: 'FirstCtrl', controllerAs:'vm' })
        .when('/second', { templateUrl: 'second.html' , controller: 'FirstCtrl', controllerAs:'vm' })
        .otherwise({ redirectTo: '/first' });
});

The views can use vm.<object-name> in the data binding expressions.

Using controller as in directives

A directive can have a own controller of its own. To use controller as in directives, we need to specify an additional property just as in case of routing. The alias can be used in data binding expressions in template of the directive. It is shown below:
app.directive("helloDir", function(){
    return{
        restrict:'A',
        template:"<span>{{dir.message}}</span>",
        controller:function(){
            this.message="Good Morning!";
        },
        controllerAs:"dir"
    }
});
This directive would render the message "Good Morning" when used in a view.
Happy coding!

Friday, 1 November 2013

Using Breeze JS to Consume ASP.NET Web API OData in an Angular JS Application

In last post, we saw how Breeze JS eases the job of querying OData services. It will be a lot of fun to use this great library with our favourite SPA framework, Angular JS. In this post, we will see how to hook up these two libraries to create data rich applications.

As stated in previous post, Breeze required data.js for to understand OData conventions. All functions performing CRUD operations in Breeze return a Q promise. Any changes made to properties of $scope inside then method of Q are not watched automatically by Angular, as 
callbacks hooked up to Q are executed in non-angular world. If the same thing can be done using $q, we don’t have to call $scope.$apply to make the changes visible to Angular’s dirty checking. For this purpose, Breeze team has created a module (use$q). This module can be installed in the project via NuGet: Breeze.Angular.Q. This package adds a JavaScript file to the application, breeze.angular.q.js. Once this file is included and the module is loaded, we don’t need q.js anymore.

Following is the list of scripts to be included on the page:

<script src="Scripts/angular.js"></script>
<script src="Scripts/datajs-1.1.1.js"></script>
<script src="Scripts/breeze.min.js"></script>
<script src="Scripts/breeze.angular.q.js"></script>

We don’t need jQuery anymore as Breeze detects presence of Angular and configures its AJAX adapter to use $http. (Check release notes of Breeze 1.4.4)

As both Angular and Breeze are JavaScript libraries, they can be easily used together. But we can’t enjoy the usage unless we follow the architectural constraints of Angular JS. The moment we include Breeze.js in an HTML page, the JS object “breeze” is available in the global scope. It can be used directly in any of the JavaScript components, Angular controllers and services are no exceptions. Best way to use an object in any Angular component is through Dependency Injection. Any global object can be made injectable by creating a value.
var app=angular.module(‘myApp’, []);
app.value(‘breeze’, breeze);
app.service(‘breezeDataSvc’, function($q, breeze){
 //logic in the service
});

We need to ask breeze to use $q as soon as the Angular JS application kicks off. For this, we need to register the following run block:
app.run(['$q','use$q', function ($q, use$q) {
    use$q($q);
}]);
Breeze has to be configured to work with OData service and use Angular’s AJAX API instead of jQuery. It is done by the following statement:
breeze.config.initializeAdapterInstances({ dataService: "OData" });

Now all we need to do is instantiate an EntityManager and start querying. Following is the complete implementation of the service including a function that does a basic OData request:
app.service('breezeDataSvc', function (breeze, $q) {
    breeze.config.initializeAdapterInstances({ dataService: "OData" });
            
    var manager = new breeze.EntityManager("/odata/");
    var entityQuery = new breeze.EntityQuery();
            
    this.basicCustomerQuery = function () {
        var deferred = $q.defer();
        manager.executeQuery(entityQuery.from("Customers").where("FirstName", "contains", "M")) .then(function (data) {
            deferred.resolve(data.results);
        }, function (error) {
            deferred.reject(error);
        });
        return deferred.promise;
    };
});

Following is a simple controller that uses the above service and sets the obtained results to a property in scope:
app.controller('SampleCtrl', function ($scope, breezeDataSvc) {
    function initialize() {
        breezeDataSvc.basicCustomerQuery().then(function (data) {
            $scope.customers = data.results;
        }, function (err) {
            alert(err.message);
        });
    };

    initialize();
});

Run this page on browser and see the behaviour.

Update: This post was updated on 11th January 2014 as per Breeze Angular Q-Promises page in documentation of Breeze

Happy coding!