BTI420 notes – Tue Mar 24

Security for ASP.NET MVC web apps, introduction. More about entity associations. Assignment 2 introduction.

.

Security topics introduction and terminology

Web apps that you create with Visual Studio 2013 Update 4 (and later) use a security system named ASP.NET Identity. Its components provide identity management (i.e. user account creation and maintenance), authentication, and authorization.

In this course, in our web apps, we will use the Individual User Accounts scheme.

A User Account is an object that represents a human user of a web app. A user account includes identification and description properties, including user name, a shared secret (i.e. a password), email address, etc. We can also add our own properties, by editing the ApplicationUser class in the IdentityModels.cs source code file.

Authentication is the process of presenting and validating credentials. A web app that’s configured to use ASP.NET Identity includes the components needed for authentication, including a login page. The word authentication is often abbreviated to AuthN (or authN).

Also, after authentication, the ASP.NET Identity system creates a security principal object, and attaches it to the execution context. Among other data, this object includes claims, which (as you’ll learn more about soon) are descriptive pieces of information about the user. The web app returns an authentication cookie in the response to the browser. By convention, the browser will include the cookie in every subsequent request to the web app.

How can you inspect this cookie?

Ask your professor to show you.

.

After a user authenticates successfully (i.e. logs in), the user’s claims determine whether they are authorized to perform tasks and access resources in the web app. This is the definition of Authorization. The word authorization is often abbreviated to AuthZ (or authZ).

ASP.NET Identity is an implementation of standards-based approaches to web app security (OAuth 2, and OpenID Connect).

.

ASP.NET Identity components, and recognizing them

A web app that’s configured with “Individual User Accounts” includes a number of components. Some you can see in source code files, while others are components that are linked to your project (and are visible if you look at the References branch of your project in Solution Explorer).

.

The visible and obvious components include…

Classes in the Models folder:

IdentityModels.cs – Includes the ApplicationUser class, which we can extend by adding our own descriptive properties. Before doing so, check the list of existing properties, which you can see in its superclass, IdentityUser<TKey, TLogin, TRole, TClaim>. (Use ‘Go To Definition’, F12, in the code editor to help with this.)

Also includes the ApplicationDbContext class. This class provides the data store context for our web app. We extend this class by adding our own DbSet<TEntity> properties for our web app’s entity collections (that we define in the DesignModelClasses.cs source code file). If you examine its superclass, you will see that ApplicationDbContext is an identity-aware class, that ultimately inherits from DbContext.

AccountViewModels.cs – Includes the classes needed by the ‘Account’ controller for the user interface views, such as register, login, forgot password, and so on. Typically used for tasks done by unauthenticated users.

ManageViewModels.cs – Includes the classes needed by the ‘Manage’ controller for the user interface views, such as change password, etc. Typically used for tasks done by authenticated users.

Classes in the Controllers folder:

As suggested above, the Account controller is for tasks done by unauthenticated users.

And, the Manage controller is for tasks done by authenticated users.

Other:

In the project’s root, the Startup class configures the app for ASP.NET Identity.

In the App_Start folder, the Startup.Auth class configures the authentication features. As you would expect, authN is configurable, but the initial settings will suit our needs in this BTI420 course.

In the upper-right corner of every page, you will see links for account registration, or login, or info.

.

Other components include…

Most appear as “assemblies” (i.e. code libraries) under the Reference node in your project’s Solution Explorer.

Notable assemblies include a number of Microsoft.AspNet.Identity assemblies, and others in the Microsoft.Owin.Security group.

.

Code example, and customizations

A code example named Security Intro has been posted to this course’s GitHub code repository.

It includes a number of customizations, briefly described below. You are permitted to use this code as-is in your web apps. You can simply copy the source code files – or the code – into an existing app.

The Account controller includes a new ‘details’ method (and view). It also includes modifications to the ‘register’ methods, to support the use of claims.

The IdentityModels.cs file includes new properties for the ApplicationUser class.

The AccountViewModels.cs file includes modified ‘register’ classes, and a new ‘details’ class (used by the above Account controller).

The view source code in the Views > Account folder adds the register-based features to the user interface.

.

An introduction to claims

What is a claim? An often-used definition:

A claim is a a statement that one subject makes about itself or another subject.

Therefore, a statement is descriptive information about a subject.

A subject is a participant in the lifetime of an application. A subject could be a human user, or a corporate body, or a programmable object (e.g. a security provider).

.

Claim examples

What does a claim (statement) look like?

Here are some examples. For these examples, assume that the subject is a user (and your professor), Peter McIntyre.

The user name is pmcintyr.
username = “pmcintyr”

The user’s full (readable) name (e.g. first name, and last name) is Peter McIntyre.
name = “Peter McIntyre”

The user’s birth date is May 15, 1980 (yeah, right).
dateofbirth = “1980-05-15″

The user’s email address is peter.mcintyre@senecacollege.ca.
email = “peter.mcintyre@senecacollege.ca”

The user’s roles are: employee, faculty, coordinator.
role = “employee”
role = “faculty”
role = “coordinator”

Custom claim example:
The user’s driver’s license number is M12345809515.
driverlicense = “M12345809515″

Custom claim example:
Is an administrator of the course outline system.
courseoutlinesystem = “administrator”

etc.

.

Claims management and issuance

While a claim is a statement about a subject, claims are managed and issued by an identity authority (which is the ASP.NET Identity system in our web app).

Then, a claim can be used by an application to authorize a user to access resources and/or perform tasks.

For our web app, claims are packaged in an authentication cookie, after a user successfully authenticates. Therefore, the result of a successful authentication is a cookie that (among other data) includes claims.

Our web app must trust the identity authority. (That is done by sharing a cryptographically-strong ‘machine key’ value between among the identity authority and your app. If you separate the identity authority and web app, you may – or will -have to configure this value. Although we do not do this in this BTI420 course, you may want to do it in the future, for work in other courses.)

.

Claims in the code example

As noted above, the code example includes claims management. Let’s see how this is implemented.

First, the user sees the name, identity, and role-oriented claims on the ‘Register’ page:

register-with-claims

.

In your design, you may not want to allow the new user to choose their roles. In that situation, you can still gather their intentions, and in your program code, defer the role claims configuration until a trusted user (e.g. an admin, or a manager) looks at the request.

How would you do this?

That would be an excellent question for Test 2.

.

In the Account controller Register() method (that handles the post request), you will see some new code that adds the claims to the new user account object.

// After 'if (result.Succeeded)...

// Add name and identity claims
await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Email, model.Email));
await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.GivenName, model.FirstName));
await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Surname, model.LastName));
await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Role, "User"));

// Add role claims
foreach (var role in model.Roles)
{
    await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Role, role));
}

.

After a user authenticates, they can view the page at ~/account/details:

account-details

.

How can you control access to your web app’s resources and functionality?

By using the Authorize attribute, usually in controllers.

In the request-handling pipeline, authorization happens before controller actions (methods) run. Your ASP.NET MVC web app includes a built-in authorization filter, which enables you to authorize a request, based on any of these conditions:

  • Authorize any user, or any role (because the request is authenticated)
  • Authorize specific users (that match a list)
  • Authorize specific roles (that match a list)
  • Authorize specific users or roles

.

To restrict access for a specific controller, add the filter as an attribute to the controller, just before the controller class declaration.

To restrict access for specific actions, add the attribute to the action method (again, just before the method declaration).

Alternatively, you can restrict the controller and then allow anonymous access to specific actions, by using the [AllowAnonymous] attribute (again, placed just before the method declaration; see the Account controller’s Login and Register methods for examples).

In the code example’s Test controller, notice the usage of the Authorize attributes:


[Authorize]
public ActionResult AccountRoleAny()
{
    return Content("Any account works correctly");
}

[Authorize(Roles = "User")]
public ActionResult AccountRoleUser()
{
    return Content("Role 'User' works correctly");
}

[Authorize(Roles = "Student")]
public ActionResult AccountRoleStudent()
{
    return Content("Role 'Student' works correctly");
}

[Authorize(Roles = "Teacher")]
public ActionResult AccountRoleTeacher()
{
    return Content("Role 'Teacher' works correctly");
}

[Authorize(Roles = "Coordinator")]
public ActionResult AccountRoleCoordinator()
{
    return Content("Role 'Coordinator' works correctly");
}

[Authorize(Roles = "Teacher,Coordinator")]
public ActionResult AccountRoleTeacherCoordinator()
{
    return Content("Role 'Teacher, Coordinator' works correctly");
}

.

ASP.NET Identity and security learning resources

ASP.NET team: Creating ASP.NET Web Projects in Visual Studio 2013

ASP.NET team: Introduction to ASP.NET Identity

OAuth 2 Authorization Framework (and in Wikipedia) (skim/read)

OpenID Connect (and in Wikipedia) (skim/read)

Microsoft Katana project (and a ‘getting started‘ with OWIN and Katana) (skim only, because we use the components differently)

Wikipedia article on claims-based identity

MSDN article on Claims-Based Identity Term Definitions

ASP.NET Identity: ClaimType Fields

ASP.NET Identity: How to: Create a Custom Claim

Textbook (Professional ASP.NET MVC 5): Chapter 7

  • Ignore the part on “Windows Authentication”
  • Ignore any content on “roles”, “RoleManager”, and so on
  • Ignore – for now – discussion about external security providers

.

More about entity associations

In this course, you have worked with one-to-many associations between objects, several times.

Recently, you learned how to work with many-to-many associations.

Today, we will introduce two other kinds of associations that are commonly used. To help understand these associations, we will use a family (or family tree) as a problem domain. A family has Person objects. A person is related to another person, as a parent or child.

.

person-with-relations

.

Self-referencing one to one, to the same entity 

A Person has a father and mother, who are also Person objects.

In our situation, the association will not be required – it will be optional. That is typical for almost all to-one self situations.

When writing the Person entity class, you must know the following, and be aware of some rules:

  • Two properties are required
  • One property type is a nullable int – int? – it will hold the identifier of the associated object
  • The other property type is the class data type (i.e. Person)

.

// Self-referencing one-to-one
// Both properties must be included
public int? FatherId { get; set; }
public Person Father { get; set; }

.

Self-referencing one to many, to the same entity 

A father or mother Person has a collection of zero or more Person objects as children.

This is actually easy, as you may speculate. Simply add a collection property; its data type is the class data type.

.

Code example highlights

The “Family Tree” code example, in this course’s GitHub code repository, can be studied. Here are the highlights:

Generating test data, using mockaroo.com.

Strategy for loading data from a CSV file.

Strategy for designing the classes, design model, and view model.

In the user interface (UI), how to specify the to-one association (father, mother).

Also in the UI, how to specify the to-many association (children).

Indicating current (persisted) selections on an ‘edit’ form.

Displaying associated content in an appropriate manner.

.

Assignment 2 introduction

We will introduce and briefly discuss Assignment 2.

.

.

.

.

.

.

.

.

.

.

.

.

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: