DPS907 notes – week 10 – Nov 16 and Nov 19

Resource ownership, and security considerations.


Agenda for the Friday class

We revisit the task of getting access to identity information in the controller and manager, at runtime. We look at a way to make that a better experience. Next, we look at resource ownership, where we allow access to the owner of a piece of data, and deny others.

Here is the agenda for the Friday class:

  • Get identity info at runtime
  • Resource ownership
  • More discussion about the assignment


Code examples

In the GitHub code example repository for this week, you will see several interesting assets.

RequestUser class – Add this to any project for easy access to information about the security principal

ObjectOwner – Shows how to work with an entity collection that offers privacy to an object’s owner


Get identity info at runtime

In the week 7 notes, you learned how to get access to the security principal – information about the identity – at runtime, in the User property.

In a controller, it’s simply the top-level User property. Also, if you want to determine whether a request is authenticated, the Request.IsAuthenticated property will tell you.

In a manager module, it’s the HttpContext.Current.User property. Also, if you want to determine whether a request is authenticated, the HttpContext.Current.Request.IsAuthenticated property will tell you.


User data type is ClaimsPrincipal

In either situation, the best practice is to cast the security principal to a ClaimsPrincipal object, which exposes these top-level properties:

  • Claims (collection)
  • Identity, and its properties Name (user name) and IsAuthenticated


We must inspect the Claims collection to learn about surname, given name(s), role claims, and custom claims.

// Assume that we are in the Manager class...
var user = HttpContext.Current.User as ClaimsPrincipal;

// Various values...
var userName = user.Identity.Name;
var isStudent = user.IsInRole("Student");
var surname = user.Claims
  .SingleOrDefault(c => c.Type == ClaimTypes.Surname)
if (string.IsNullOrEmpty(surname)) { surname = "(empty surname)"; }


Make it easier to access User information

That’s a lot of code. Can we make it easier to access User information? Yes.

The GitHub code example repository has a source code file with a custom RequestUser class that you can add to the Controllers folder, or to the bottom of the Manager.cs source code file. Then, as its code comment states, you can add and initialize a property in the Manager class. The result will be easy-to-access information about the current security principal.

The new top-level property in the Manager class is “User”.  The code from above is now improved. Compare the following with the previous code block. Much clearer, and better to work with:

// Various values...
var userName = User.Name;
var isStudent = User.HasRoleClaim("Student");
var surname = User.Surname;


It gets even better when you need to need a full name (given name(s) and surname). Study the class to learn about all its properties and methods.


However, we must carefully configure the property’s value

Another topic that was in the week 7 notes was the “Request-processing pipeline in a secure scenario” topic. In it, you learned that the controller was initialized in step 6. In step 8, authentication happens. Finally, in step 11, the controller action is invoked/executed.

Problem? Maybe, if we attempt to set/initialize the value of the User property too early. To explain:

In step 6, the controller was initialized. Look at the controller code – it declares a Manager field (“m”), and initializes it. Therefore, when the controller is initialized, the Manager is also initialized.

Do we know the security principal at this point in time? No.

We learn later – in step 8 – what it is.

Therefore, if we attempt to set the User property value when the Manager class is initialized, the security principal will be based on the “anonymous” user. So, let’s defer the setter task. This means that we must write a standard property block, with a body for the getter code. We do not need a setter – we’ll do that task in the getter. Here’s the code:

// Backing field for the property
private RequestUser _user;

// Getter only, no setter
public RequestUser User
    // On first use, it will be null, so set its value
    if (_user == null)
      _user = new RequestUser(HttpContext.Current.User as ClaimsPrincipal);
    return _user;


User info in a controller? Yes

You can use this new object in a controller too:

// Assume that the following code is in a controller method...
// ...and that "m" is the reference to the manager object...
var fullname = m.User.NamesFirstLast;
var isICTStudent = m.User.HasClaim("OU", "SICT");


The concept of resource ownership in an app

You may be familiar with this topic from your web apps programming course. If not, or if you need a refresher, continue reading…

Sometimes, an app has data that is “owned” by the app itself. In other words, if you have a user account for the app, then you can typically get access to its data.

Yes, it’s possible that you must meet authorization tests. In other words, you may still need to have a specific role claim, or a specific custom claim (e.g. OU = SICT). But if you do meet the authorization test, you have access to all the data.


Shared data store, but allow a user to work only with their own data

Assume that we have an app that has many entity collections, just like the code samples that we have been working with. Some entity collections are shared, and available to all authorized users. Then, maybe some entity collections have user-specific data, which is (or should be / must be) private to the user.

note-classFor example, assume that an app enables a user to add notes (or diary entries, or journal entries).

See an example “Note” class diagram to the right.

To enable privacy, simply add an “Owner” string property.

When a new Note object is created, the logic in the manager “add new” method will write the user name into the Owner property. It gets that from the security principal.

The Identity.Name property in the security principal – which is surfaced simply as the “Name” property in the new “User” property in the Manager class – is guaranteed to be unique.


Fetching a user’s own data from the persistent store

In many of the manager methods that fetch data, there’s often a query condition.

For example, “get one” will use the Find() or SingleOrDefault() methods to fetch the object.

To fetch a user’s own data, add one more condition. For example:

var o = ds.Notes.SingleOrDefault(n => n.Id == id && n.Owner == User.Name);


The result will be an object, or null. Null will bubble up through the controller and then to the user/requestor as HTTP 404 “not found”. That may be the best answer to give, because it will not leak information about the data store. (There’s a big difference between “not found” and “unauthorized” when asking for a specific object. “Not found” will likely end the fetch attempt. In contrast, “unauthorized” may invite additional attempts to bypass security measures.)

Can you ever return HTTP 401 “unauthorized”? Maybe. How can you do it, if the situation is right? From a manager method:

throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);


Related objects? They need an Owner property too

In this scenario, it is possible that an object could have related or associated objects. For example, a Note object could have a collection of attachments (photos, PDFs, etc.)

When there are related objects, and they need to be protected, add an Owner property to their classes. Doing this will enable an easier query strategy. Continuing with this example, Note one-to-many with Attachment, we can fetch a note, with its associated Attachments. Because of the Owner check on the get-one Note, we can be assured that the associated Attachments will also be the Owner’s.

Alternatively, if we need to query the Attachments first, the presence of the Owner property makes it much easier to do this directly with the Attachments entity collection. If it wasn’t there, we would have to use an awkward query strategy, which would need to fetch its associated Note object to do the Owner check.


Strive to do all identity checks in the Manager class

For best results, and to centralize logic, you should strive to do all the identity checks in the Manager class methods. The manager object is one step away from a controller, and therefore farther away from the user/requestor. Doing this also will keep your controller code simpler.


( end of Friday content; Monday content is next )



Agenda for the Monday class

The Monday class is a work period. Work on your assignment. Your professor will be available in class.





























%d bloggers like this: