DPS907 WSA500 Lab 8

Security-aware web service. Hosted on Azure.

Read/skim all of this document before you begin work.

 

DPS907 WSA500 Lab 8 – Due Mon Nov 23

Due date: Monday, November 23, 2015, at 8:00am ET

Grade value: 12% of your final course grade

If you wish to submit the lab before the due date and time, you can do that.

Yes, your project can earn part marks if a feature is missing. 

 

Objective(s)

Add security-aware features to an existing web service. Handle claims correctly.

 

Introduction to the problem to be solved

A web service has been created that enables users to create hobby or craft “projects”. Each project can have associated media items (e.g. photo, video, etc.). For inspiration, check out Pinterest or Trello.

A user’s project can be private, public, or shared.

A shared project can have a collection of users, who can contribute media items to the project.

The web service trusts an Identity Server, which will perform identity management tasks, and authentication. A user of the web service must obtain an access token from the Identity Server before they can access secured resources. The web service performs authorization, and because it trusts an access token that’s generated by the Identity Server, it is able to do this task.

Your work will be hosted publicly on Microsoft Azure Services.

 

Specifications and work plan

The following specifications apply to all of your work:

  • Follows best practices
  • Implements the recommended system design guidance
  • Uses Entity Framework and Code First technology
  • Deployed to Microsoft Azure Services

For this assignment, here’s what we’re looking for:

  • New entity that supports shared projects
  • Modified entities, ditto
  • New functionality, described below

 

Getting started

On My.Seneca/Blackboard, in the Assignments area, there are two zip file assets.

  1. IdentityServerV2 is the claims-aware version of our Identity Server.
  2. Lab8Base is a fully-working web service that you can use for your Lab 8 work.

Get them, and use both as you work on this assignment. The Identity Server will need a small change (described later) to support a new custom claim. Also, as you learned in the last assignment, you will have to configure a machine key and Code First Migrations before it can be deployed to Azure.

Open the Lab8Base project, and run it. It has two entities in its design model. Click the image to open it full-size in its own tab/window.

DesignModelClasses

 

In the base project, two “Project” objects were created by user1@example.com (standard initial password was Password123!). One “Media” object was created. The Lab8Base project includes a Fiddler archive. Open it to inspect the requests that created these objects.

Oops. The base project is missing a small feature.

What’s missing?

The “get one” project is supposed to deliver a project, with a collection of media items (metadata only). However, it does not do that, because the “ProjectWithLink” class inherits from the wrong class (ProjectBase).

How to fix? Two actions:

First, add another AutoMapper definition in the WebApiApplication class…
…from ProjectWithMediaInfo
…to ProjectWithLink

Second, change the base class (aka superclass) of ProjectWithLink to ProjectWithMediaInfo.

This fix will now deliver media items (metadata only) with a “get one” project request.

 

In Visual Studio, use the Task List to inspect the code that’s been highlighted with the “Attention” comment token. Study the features of the app.

Notice that the app currently works in a similar way to the Lab 7 app, in that a user can work only with objects they have created. However, you will make a small change (described later) to that functionality.

Media items are defined by their own class, named “Media”. Adding a media item is a two-step process:

  1. First, the media item is created, with metadata
  2. Then, the media item’s byte-oriented content is uploaded/set/configured

Inspect the logic chain that implements this, including the controller methods, and repository (and other) methods.

 

Use cases and scenarios

When the app is complete, it will support the following additional functionality:

  • Each user account includes a claim named “Access”
  • A single (i.e. “get one”) Shared project (and its Media items) is available to the owner and to users it has been shared with (do not modify the “get all” projects methods)
  • A user in a Shared project, with an Access claim with the value “Contribute”, can add new media items to the project

Before you begin coding, plan your query and data access strategy. Each of these use cases will be enabled by a specific combination of query terms.

How can you think about the use cases and object relationships? Well, consider this example. Remember, the app is designed to enable a user to create a hobby or craft project.

The app enables many human users to register for an account. Each user is able to create (zero or more) projects. Each project can have (zero or more) media items associated with it.

Assume that the user named Peter created a new project named “Raptors Game November 13 2015”. It was created as a “Shared” project. The project will initially be visible only to Peter (because Peter created the project).

Workflow visualizations 1

.

Two photos were added, associated with the project. Maybe they’re game action or selfies; whatever.

Workflow visualizations 2

.

Later, Peter talks to another user named Marie, and learns that Marie also went to the game, and has some photos. Peter decides to share the project with Marie, so that she can view the project and its media, and also contribute her photos.

Workflow visualizations 3

.

Next, Marie adds two photos, associated with the project. The project, and its media, is visible to Peter and Marie. Both can add photos and other media items.

Workflow visualizations 4

 

Work plan

There are several tasks that must be done to complete this assignment:

  1. Plan and implement the claims configuration
  2. Add a new entity to support shared projects
  3. Modify existing entities to support shared projects
  4. Modify existing logic

 

Plan and implement the claims configuration

Your app will need some new users. Each will include a new custom claim named “Access”. It can have a value of “View” or “Contribute”.

Before you create new users, the Identity Server needs to be changed, to support this new custom claim. Where do you do this work? At a minimum, modify the ApiAccountController, and its Register method. The RegisterBindingModel must also be edited (by adding another property to hold the custom claim), so that the request can include data for this new claim. Look at the work to be done, and plan before writing code. If you have questions, ask.

Do you need to modify both the web service interface (ApiAccountController + its view model) and the web app browser interface (AccountController + its view + its view model)?

No, but it is your decision whether you do both. It is less work to modify only the web service interface.

 

Then, add some users. We suggest that you use real names. Use your own name, and names of friends. This will make it easier to visualize the people involved, and what they are doing in the app.

What about the existing users, admin, user1, and user2? They will not have an Access claim. As a result, the three sample objects that were created by user1 will not be accessible after you make changes to your query logic.

Can this be fixed? Yes.

In our simple app design, a project or media item indicates ownership with a username. Therefore, you could remove all the existing users, and add new users – with the same username – who will have the Access claim. Follow this sequence to remove and replace the existing users:

  1. Open/run the Identity Server app in a browser, and in Fiddler.
  2. Using the browser, add a new admin-type user, maybe named “administrator”
  3. Then (still using the browser), login as that new user
  4. Show the “Maintenance tasks” page; delete all the old users
  5. Using Fiddler, add new users (admin, user1, user2) who have the Access claim

 

Design and implement project-sharing entities

As noted above, a project owner can decide to share a project with other users. For each user, the project owner determines the kind of access the user has to the project. Initially, the two access levels will be “View”, which should be self-explanatory, and “Contribute”, which indicates that the user can contribute a media item to the project.

A new entity (perhaps named Sharer) is needed to store the user name and access level. Both will be string properties. A project will have a to-many association with Sharer, which means that a project can be shared with zero or more users. At the other end of the association, Sharer has a required to-one association with Project. It should also have a date-time property, perhaps named DateUpdated. You should be able to figure out whether its date-and-time value is supplied in the request or set by the app’s logic.

Next, the Media entity needs to be modified. It needs a “Contributor” string property, holding the user name of the user who created the media item.

Here’s what the updated design model could look like. Click to open it full-size in its own tab/window.

DesignModelClasses

 

At this point in time, it will probably be a good idea to configure Code First Migrations (how to info is in the October 1 class notes). As a result of the change to the entities, you will need to do the full 3-step sequence of tasks:

  1. Enable migrations
  2. Add migration
  3. Update database

Next: After you modify the Media entity, consider whether its resource models need modification. Yeah, you should probably do that work now, before moving on.

 

Complete the entity-related tasks

As you know, there’s a set of entity-related tasks that must be done after adding a new entity class to the app’s design model. Plan on completing them now, by following this list of reminders:

  1. Add DbSet property to the data context class
  2. Write/create resource model classes
  3. Write/create the AutoMapper maps in the WebApiApplication class
  4. Add a new repository to manage the new entity
  5. Modify the Worker class, so that includes a property for the just-added repository class

 

Modify the existing media-handling logic

As noted above, one of the first modifications you should do to the existing logic is the “add new” media item handling.

Notice that the base version of the project uses the security context to write data to the “Owner” property in the Media object. That needs to change. The project’s owner will always be the media item’s owner.

However, the media item’s contributor will use the security context to get the username.

Next, plan the logic of the “add new” media item, to enable a “contributor” to add a media item to a project that is owned by a different user. How would you do that? With a carefully-planned sequence of tests, which validates whether the task can be successfully completed. Consider this reasoning, using the Peter – Marie scenario described above:

Test 1: If the project owner (e.g. Peter) matches the security context username (e.g. Peter), then we can continue, because the project owner is simply adding another media item to their project.

Test 2: If they don’t match (e.g. Marie or some other user is attempting to add a media item to Peter’s project), we need to check whether the user is a sharer of the project (i.e. whether Marie is a sharer of Peter’s project). Look in the Sharers collection for a match (all three properties – username, access level, and project identifier). If a sharer is found, then we can continue the attempt to add a media item.

If the result of Test 2 is false, then the request is simply an unsuccessful request, and must be rejected. The Test 2 result could be false for any of at least two reasons:

  1. The query cannot locate a sharer object that matches the security context username
  2. A matching sharer object was located, but its Access property value is not “Contribute”

If the result of Test 2 is true (e.g. it was Marie who sent the request to add a media item to Peter’s project) , then we can continue.

Test 3: The final test must ensure that the security context includes the right claim. You’re looking for a claim type “Access”, with the value of “Contribute”. How can you do that? Look at the User property (in the repository class). It has a method named HasClaim.

 

 

Sharing a project with a user

Another task that must be done is to enable the owner of a project to share it with another user.

We suggest that you implement this as a command (i.e. a PUT request) in the Project controller. Place the username, the access level, and the project identifier in the request body. This implies that you need a new resource model to hold the username, the access level, and project identifier. The app logic will then cause a new Sharer object to be created. (It should check for an existing sharer object that has a matching username, access level, and project. Don’t create a duplicate.)

Note: We do not really need a Sharers controller in this assignment.

 

Wisely using the custom claim

The base project includes a new “authorize” attribute, that is based on the built-in version.

Its name is AuthorizeClaim, and it can be used to authorize, based on any claim type. (The built-in version tests only for specific claim types, username and/or role.) Sweet.

Here’s how you use it: On a method (or controller) that needs authorization based on a custom claim, add the attribute:

// For example...
[AuthorizeClaim(ClaimType = "GivenName", ClaimValue = "User")]

// ...or...
[AuthorizeClaim(ClaimType = "Access", ClaimValue = "Contribute")]

 

Testing your work

At this point in time, you have done most of the work needed to implement the vision of the assignment.

Test carefully and incrementally.

If you have questions, ask.

 

Deploy your work to Microsoft Azure Services

Having problems deploying to or running on Azure? Check this document.

There are a few tasks that must be done before your Azure-posted work will run correctly.

 

Custom machineKey value

Recently, you learned that apps that are separated from an Identity Server will need a special configuration, so that they are using the same “machineKey” value for encryption and decryption of tokens and cookies. This topic was introduced in the November 5 class notes.

At this point in time, use that information to 1) generate a custom “machineKey”, and 2) add it to BOTH apps (Identity Server and Lab 8).

 

Azure web app and database preparation for your Identity Server app

It appears that our Azure Pass limits us to ten (10) web apps, and two (2) database servers. Therefore, we suggest that you remove (delete) the existing web apps and databases in your account.

Notes about databases and database servers:

On the Azure Management Portal, when you view the list of databases, you will see a list that looks like the following:

list-of-databases

Although our Azure Pass limits us to two (2) database servers, that’s not a limitation for us. Why? A database server can hold multiple databases.

Therefore, when you create a new database, we suggest that you almost always choose to create it inside an existing database server.

Next, create a web app, with a database, for your Identity Server app. The suggested name is (substitute your Seneca account name for the “astudent” placeholder below):

astudent-ws2015-is.azurewebsites.net

You can now deploy your Identity Server app to this endpoint.

 

Azure web app and database preparation for your Lab 8 app

Now, create a web app, with a database, for your Lab 8 app. The suggested name is (substitute your Seneca account name for the “astudent” placeholder below):

astudent-ws2015-lab8.azurewebsites.net

You can now deploy your Lab 8 app to this endpoint.

 

Testing your work

Use Fiddler.

Ensure that it has been configured to save the message bodies in requests and responses. (A default installation does not do this.) If you are using a College computer, this has already been configured. If you installed Fiddler on your own computer, follow the instructions on this document.

Test all scenarios (use cases), using your Azure-hosted web site, if possible.

 

Saving – ‘exporting’ – your tests

On the left side list of requests, you can delete items that you don’t want included in the export.

When you’re ready to save, choose File > Export Sessions > All Sessions…

The export format will be “HTTPArchive v1.2″. Click the Next button to choose a save location (your project’s root, in the same folder as the “packages” and “lab8” folder) and specify a filename. Name the file by using the project name (e.g. “lab8.har”).

(You can test whether the export was successful. How? First, close then re-open Fiddler. Choose File > Import Sessions. Select “HTTPArchive” as the import format. Navigate to the folder that holds “lab8.har”, and select it. Finally, browse through the request-response sessions.)

 

Reminder about academic honesty

You must comply with the College’s academic honesty policy. Although you may interact and collaborate with others, you must submit your own work.

 

Submitting your work

Submit only your Lab 8 work. Do not submit the Identity Server.

At this point in time, you are familiar with the submission process:

  1. Copy your project
  2. Remove its packages, bin, and obj folders
  3. Zip and upload to the designated location on My.Seneca/Blackboard, before the due date

If you need more details, look at the info in assignments 1 through 4.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

%d bloggers like this: