Introduction to forms based authentication in ASP.NET MVC5 Part 5: Claims

Introduction

Claims in authorisation have received a lot of attention recently. Claims are simply key-value pairs where the key describes the type of claim, such as “first name” and the value provides the value of that claim, e.g. “Elvis”. Think of a passport which usually has a page with the photo and lots of claims: first name, last name, maiden name, expiry date etc. Those are all key-value pairs that describe the owner of the passport and provide reliable evidence that the person is really the one they are claiming to be.

I have a long series on claims on this blog. If you don’t anything about them then I recommend you at least go through the basics starting here. That series takes up claims in MVC 4. MVC 5 brings a couple of new features as far as claims are concerned.

Demo

We’ll be using the same demo application as before in this series so have it open in Visual Studio 2013.

As we said before authentication in MVC 5 is built using Katana components which are activated with extension methods on the incoming IAppBuilder object. These Katana components work independently of each other: e.g. you can turn on Google authentication at will as we saw in the previous part. At the same time you can even turn off the traditional cookie authentication, it won’t affect the call to app.UseGoogleAuthentication().

When we turned on Google authentication the consent screen stated that the application, i.e. the demo web app, will have access to the user’s email. That’s in fact a type of claim where the key is “email” or most probably some more complete namespace. Where’s that email? How can we read it?

Locate the method called ExternalLoginCallback in the AccountController. That method is fired when the user has successfully logged in using an external auth provider like Google or Facebook. The method will first need to extract the login information using…

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();	

This login information contains the tokens, expiry dates, claims etc. As the login is taken care of by OWIN, MVC will need to tap into the corresponding Katana component to read those values. This is an example of a piece of logic outside OWIN that needs to find out something from it. The AccountController will need this information to handle other scenarios such as signing out. The key object here is the AuthenticationManager.

The AuthenticationManager which is of type IAuthenticationManager is extracted using the following private property accessor in AccountController:

private IAuthenticationManager AuthenticationManager
{
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
}

The interface lies in the Microsoft.Owin.Security namespace. The AuthenticationManager is retrieved from the current OWIN context. The GetOwinContext extension method provides a gateway into OWIN from ASP.NET. It allows you to retrieve the request environment dictionary we saw in the series on OWIN:

HttpContext.GetOwinContext().Request.Environment;

I encourage you to type ‘HttpContext.GetOwinContext().’ in the editor and look through the available choices with IntelliSense. The Authentication property exists so that ASP.NET can read authentication related information from the OWIN context as all that is now handled by Katana components.

If you look further down in the code you’ll see the SignInAsync method. The method body shows how to sign users in and out using an external cookie-based login:

AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

Now that we know a little bit about the authentication manager we can return to the ExternalLoginCallback method. Let’s see what the GetExternalLoginInfoAsync method returns in terms of login information. Add a breakpoint within the method and start the application. Click the Log in link and sign in with Google. Code execution stops within the method. Inspect the contents of the “loginInfo” variable. It doesn’t contain too much information: the user name, the provider name – Google – and a provider key. So there’s nothing about any provider specific related claims such as the user’s email address.

Note that the GetExternalLoginInfoAsync method only provides an object which includes properties common to all providers. The list is not too long as we’ve seen. However, the method cannot know in advance what the Google auth provider will provide in terms of claims. The list of available data will be different across providers. Some providers may provide a more generous list of claims than just an email: a URL to the user’s image, the user’s contacts, first and last names etc. Insert the following line of code above the call to GetExternalLoginInfoAsync:

AuthenticateResult authenticateResult = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

Leave the breakpoint as it is and restart the application. Sign in with Google and inspect the authenticateResult variable. You’ll see that it provides a lot more information than the login info above. The claims are found
within the Identity property:

Claims from Google authentication

You can see that the claim types are identified in the standard URI way we saw in the series on claims. You can query the Claims collection to see if it includes the email claim. If your application explicitly requires the email address of the user then make sure to indicate it when you set it up with Google or any other auth provider.

You can save the email of the user in at least two ways:

  • Temporarily in the session using the ExternalLoginConfirmationViewModel object further down in the ExternalLoginCallback method. That view model doesn’t by default include any property for emails, you’ll need to extend it
  • In the database using the UserManager object we saw before in this series

Let’s see how we can achieve these. Locate the ExternalLoginConfirmationViewModel object in AccountViewModels.cs and extend it as follows:

public class ExternalLoginConfirmationViewModel
{
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

	public string EmailFromProvider { get; set; }
}

Add the following method to AccountController.cs to read the email claim from the claims list:

private string ExtractEmailFromClaims(AuthenticateResult authenticateResult)
{
	string email = string.Empty;
	IEnumerable<Claim> claims = authenticateResult.Identity.Claims;
	Claim emailClaim = (from c in claims where c.Type == ClaimTypes.Email select c).FirstOrDefault();
	if (emailClaim != null)
	{
		email = emailClaim.Value;
	}
	return email;
}

You can read this value in the body of ExternalLoginCallback and store it in a ExternalLoginConfirmationViewModel like this:

public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
	AuthenticateResult authenticateResult = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();			
         if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);

			string emailClaimFromAuthResult = ExtractEmailFromClaims(authenticateResult);

            if (user != null)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
            else
            {
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel 
					{ UserName = loginInfo.DefaultUserName, EmailFromProvider = emailClaimFromAuthResult });
     }
}

This page redirects to a View called ExternalLoginConfirmation when the user first signs up in the “else” clause. Locate ExternalLoginConfirmation.cshtml in the Views/Account folder. You can use the incoming model to view the extracted email claim:

<p>
    We've found the following email from the login provider: @Model.EmailFromProvider
</p>

I’ve deleted all rows in the AspNetUsers table so that I can view this extra information. Also, clear the cookies in your browser otherwise Google will remember you. You can also run the application from a brand new browser window. The email was successfully retrieved:

Found Google email claim

We can store the email claim in the database within ExternalLoginCallback as follows:

if (user != null)
{
        await SignInAsync(user, isPersistent: false);
        IList<Claim> userClaimsInDatabase = UserManager.GetClaims<ApplicationUser>(user.Id);
	Claim emailClaim = (from c in userClaimsInDatabase where c.Type == ClaimTypes.Email select c).FirstOrDefault();
	if (emailClaim == null)
	{
        	IdentityResult identityResult = UserManager.AddClaim<ApplicationUser>(user.Id, new Claim(ClaimTypes.Email, emailClaimFromAuthResult));
	}
				
        return RedirectToLocal(returnUrl);
}

First we check the claims stored in the database using the UserManager.GetClaims method. Then we check if the email Claim is present. If not then we add it to the database. The identityResult helps you check the result of the operation through the Errors and Succeeded properties.

The claims by default end up in the AspNetUserClaims table:

Email claim saved in the aspnetuserclaims table

You can of course use the AspNetUserClaims table to store any kind of claim you can think of: standard claims found in the ClaimTypes list or your own custom ones, such as http://mycompany.com/claims/customer-type.

You can view the list of posts on Security and Cryptography here.

Building a uniform sequence using the Repeat operator in LINQ C#

Using the Repeat operator you can create sequences where the same input object is repeated a number of times.

Its usage is very simple. Say you need a list of integers with number 1 repeated 10 times:

IEnumerable<int> integers = Enumerable.Repeat<int>(1, 10);
foreach (int i in integers)
{
	Console.WriteLine(i);
}

…which simply prints “1” 10 times.

Be careful with reference types. If you want identical objects in the sequence that can be modified separately then use the new keyword directly in the Repeat method:

IEnumerable<Band> bands = Enumerable.Repeat<Band>(new Band() { Name = "Band" }, 10);

Otherwise all objects will have the same reference:

Band band = new Band() { Name = "Band" };
IEnumerable<Band> bands2 = Enumerable.Repeat<Band>(band, 10);

…and modifying one will modify all references.

View the list of posts on LINQ here.

Introduction to forms based authentication in ASP.NET MVC5 Part 4

Introduction

In the previous part of this series we looked at some key objects around the new Identity packages in .NET. We also identified the EntityFramework database context object which can be extended with your own entities. By default it only contains User-related entities. Then we tried to extend the default implementation of IUser, i.e. ApplicationUser which derives from the EF entity IdentityUser. We failed at first as there’s no mechanism that will update our database on the fly if we make a change to the underlying User model.

We’ll continue working on the same demo project as before so have it ready in Visual Studio 2013.

Database migrations and seeding

As hinted at in the previous post we’ll look at EntityFramework 6 and DB migration in the series after this one but we’ll need to solve the current issue somehow.

Open the Package Manager Console in Visual Studio: View, Other Windows, Package Manager Console. Run the following command:

Enable-Migrations

This is an EntityFramework specific command. After some console output you should see the following success message:

Code First Migrations enabled for project [your project name]

Also, a couple of new items will be created for you in VS. You’ll see a migration script in a new folder called Migrations. The migration script will have a name with a date stamp followed by _InitialCreate.cs. Also in the same folder you’ll see a file called Configuration.cs. An interesting property is called AutomaticMigrationsEnabled. It is set to false by default. If it’s set to true then whenever you change the structure of your entities then EF will reflect those in the database automatically. In an alpha testing environment this is probably a good idea but for the production environment you’ll want to set it to false. Set it to true for this exercise.

Another interesting element in Configuration.cs is the Seed method. The code is commented out but the purpose of the method is to make sure that there’s some data in the database when the database is updated. E.g. if want to run integration tests with real data in the database then you can use this method to populate the DB tables with some real data.

There are at least two strategies you can follow to populate the User database within the Seed method. The traditional EF context approach looks like this:

PasswordHasher passwordHasher = new PasswordHasher();
context.Users.AddOrUpdate(user => user.UserName
	, new ApplicationUser() { UserName = "andras", PasswordHash = passwordHasher.HashPassword("hello") });
context.SaveChanges();

We use PasswordHasher class built into the identity library to hash a password. The AddOrUpdate method takes a property selector where we define which property should be used for equality. If there’s already a user with the username “andras” then do an update. Otherwise insert the new user.

Another approach is to use the UserManager object in the Identity.EntityFramework assembly. Insert the following code into the Seed method:

if (!context.Users.Any(user => user.UserName == "andras"))
{
	UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(context);
	UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(userStore);
	ApplicationUser applicationUser = new ApplicationUser() { UserName = "andras" };
	userManager.Create<ApplicationUser>(applicationUser, "password");
}

We first check for the presence of any user with the username “andras” with the help of the Any extension method. If there’s none then we build up the UserManager object in a way that’s now familiar from the AccountController constructor. We then call the Create method of the UserManager and let it take care of the user creation behind the scenes.

Go back to the Package Manager Console and issue the following command:

Update-Database

The console output should say – among other things – the following:

Running Seed method.

Open the database file in the App_Data folder and then check the contents of the AspNetUsers table. The new user should be available and the table also includes the FavouriteProgrammingLanguage column:

User data migration success

Run the application and try to log in with the user you’ve just created in the Seed method. It should go fine. Then log off and register a new user and provide some programming language in the appropriate field. Then refresh the database in the Server Explorer and check the contents of AspNetUsers. You’ll see the new user with there with their favourite language.

If you’d like to create roles and add users to roles in the seed method then it’s a similar process:

string roleName = "IT";
RoleStore<IdentityRole> roleStore = new RoleStore<IdentityRole>(context);
RoleManager<IdentityRole> roleManager = new RoleManager<IdentityRole>(roleStore);
roleManager.Create(new IdentityRole() { Name = roleName });
userManager.AddToRole(applicationUser.Id, roleName);

Third party identity providers

We looked at Start.Auth.cs briefly in a previous part of this series. By default most of the code is commented out in that file and only the traditional login form is activated. However, if you look at the inactive code bits then you’ll see that you can quite quickly enable Microsoft, Twitter, Facebook and Google authentication.

You can take advantage of these external providers so that you don’t have to take care of storing your users’ passwords and all actions that come with it such as updating passwords. Instead, a proven and reliable service will tell your application that the person trying to log in is indeed an authenticated one. Also, your users won’t have to remember another set of username of password.

In order to use these platforms you’ll need to register your application with them with one exception: Google. E.g. for Facebook you’ll need to go to developers.facebook.com, sign in and register an application with a return URL. In return you’ll get an application ID and a secret:

Facebook application ID and secret

The Azure mobile URL is the callback URL for an application I registered before on each of those 4 providers. I hid the application ID and application secret values.

For Twitter you’ll need to go to dev.twitter.com and register your application in a similar fashion. You’ll get an API key and an API secret:

Twitter application keys

These providers will use OAuth2 and OpenId Connect to perform the login but the complex details are hidden behind the Katana extensions, like app.UseMicrosoftAccountAuthentication.

As you activate the external providers there will be new buttons on the Log in page for them:

External providers login buttons

Upon successful login your web app will receive an authentication token from the provider and that token will be used in all subsequent communication with your website. The token will tell your website that the user has authenticated herself along with details such as the expiry date of the token and maybe some user details depending on what your web app has requested.

As mentioned before there’s one exception to the client ID / client secret data requirement: Google. So comment out…

app.UseGoogleAuthentication();

…and run the application. Navigate to the Log in page and press the Google button. You’ll be directed to the standard Google login page. If you’re already logged on with Google then this step is skipped. Next you’ll be shown a consent page where you can read what data “localhost” will be able to read from you:

Google consent screen

If you implement the other providers at a later point then they’ll follow the same process, i.e. show the consent screen. Normally you can configure the kind of data your application will require from the user on the individual developer websites mentioned above.

Click Accept and then you can complete the registration in the last step:

Confirm registration with Google

This is where you create a local account which will be stored in the AspNetUserLogins table. Press Register and there you are, you’ve registered using Google.

Check the contents of AspNetUserLogins:

Google login data in DB

Also, the user is stored in the AspNetUsers table:

Google user

You’ll see that the password is not stored anywhere which is expected. The credentials are stored in the provider’s database.

Read the last part in this series here.

You can view the list of posts on Security and Cryptography here.

Getting the last element from a sequence with LINQ C#

Say you have the following object sequence:

public class Singer
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public int BirthYear { get; set; }
}

IEnumerable<Singer> singers = new List<Singer>() 
			{
				new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964}
				, new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954}
				, new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954}
				, new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950}
				, new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964}
			};

If you just want to get the very last element from this sequence with no query then you can use the Last operator:

Singer singer = singers.Last();
Console.WriteLine(singer.LastName);

This will select David Bowie from the list. You can also send an item selector to get the last element which matches the query:

Singer singer = singers.Last(s => s.BirthYear == 1954);
Console.WriteLine(singer.LastName);

…which returns Chuck Berry.

A caveat is that the Last operator throws an InvalidOperationException if there’s no single matching record:

Singer singer = singers.Last(s => s.BirthYear == 2000);

To avoid this scenario you can use the LastOrDefault operator which returns the default value of the required object if there’s no matching one. Therefore “singer” in the above example will be null:

Singer singer = singers.LastOrDefault(s => s.BirthYear == 2000);
Console.WriteLine(singer == null ? "No such singer" : singer.LastName);

…which yields “No such singer”.

You can view all LINQ-related posts on this blog here.

Convert a sequence of objects to a sequence of specific type in LINQ .NET

In the posts on LINQ on this blog we’ve seen some ways to convert a sequence of type A to a sequence of type B. This particular post deals with converting a sequence of objects to a sequence of some specific type.

Say that you have some old style collection such as this:

ArrayList stringList = new ArrayList() { "this", "is", "a", "string", "list" };

You can easily turn this into a proper string list using the Cast operator:

IEnumerable<string> stringListProper = stringList.Cast<string>();
foreach (string s in stringListProper)
{
	Console.WriteLine(s);
}

…which results in…

this
is
a
string
list

It works of course for any object type, even for your custom objects.

However, what if you have the following starting point?

ArrayList stringList = new ArrayList() { "this", "is", "a", "string", "list", 1, 3, new Band() };

The integers and the Band object are not of type string so the Cast operator will throw an InvalidCastException. This is where the OfType extension enters the picture. It does the same job as Cast but it ignores all objects that cannot be converted:

IEnumerable<string> stringListProper = stringList.OfType<string>();
foreach (string s in stringListProper)
{
	Console.WriteLine(s);
}

…which yields the same output as above without throwing any exception.

So in case you need to deal with sequences you don’t control and whose content type you cannot be sure of then you should probably use the OfType extension.

You can view all LINQ-related posts on this blog here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.