DPS907 notes – Thu Nov 5

Test 7 is today

Test 7 is today. We’ll probably do that closer to the end of the class/session. Example answers will be posted within hours.

Designing security to enable modularity and scale

In the web apps programming courses, you learned how to embed security functionality in a web app. In addition, your initial study of security functionality in a web service project enabled you to conclude that it looked similar to that in a web app.

The problem here is that an app is tied to its security components. If you wanted to create a second app with security, then the second app had its own security components, and could not share credentials and so on.

How do you fix this? By separating the security components from the apps. In Lab 7, you are implementing this fix. Let’s learn more about security functionality.

Security functionality

While there’s a long list of security definitions and terms (presented formally in a later section), the text below introduces the vitally-important foundational items.

ASP.NET Identity includes identity management components. These enable the creation, storage, and management of user accounts. The IdentityModels.cs source code file includes a data context class that inherits from IdentityDbContext<TUser>. When the database is accessed for the first time, the Entity Framework infrastructure creates a number of tables in the database which support identity management. All of the tables begin with the prefix “AspNet”. If we were to look at a diagram of the classes that are represented in the data store, it would look like the following. Click to open full-size in its own tab/window.

ASP.NET Identity also includes a token issuer. This component will handle requests to the “/token” endpoint. A requestor sends a POST request, with credentials, and the component creates and issues a token. The token is encrypted, using a server-configured or programmer-configured signature. Next, the token is encoded into a format that can be sent on the web. Finally, the token is delivered to the requestor.

Finally, ASP.NET Identity includes an authorization module. When handling a request that includes a token, its work is split into two phases.

In the first phase, the token is decoded. Then, it is decrypted, using a server-configured or programmer-configured signature. Next, it is validated, to ensure that it has not expired.

In the second phase, a security principal object is created, and attached to the request thread. If the request is for a resource that requires authorization, the security principal object is inspected, and matched to the authorization specification. If it matches, the request proceeds. If not, an appropriate HTTP response can be returned.

If unauthorized, what is the correct response?

401, 403, or 404?

In our app design, a repository method will return an object or collection, or null. So, if the repository method detects an unauthorized state, what can it return? Its only choice is null. Otherwise, you must add more logic to the controller method, to detect, filter, and respond appropriately (or create a message handler or filter, a topic beyond the scope of this course).

As a result, null from the repository will become 404 in the controller response. Is that technically correct? Maybe not. However…

It could be argued that returning 401 or 403 would “leak” information, by implying that a resource exists, but we do not have access to it.

It could also be argued this way: From the perspective of the request, the requested resource simply does not exist. If you read RFC 7231 section on 404 (it is always a good idea to go back to the RFCs), it states:

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

Also, at the end of the 403 explanation, it states:

An origin server that wishes to “hide” the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

Interesting, yes? In summary, returning 404 in the controller response is probably OK.

Can we separate these components?

Yes.

In Lab 7, the Identity Server project does the first two tasks. The Instruments project does the third task.

In the Identity Server, in its Startup class, it has the following statement, which creates the token issuer:

app.UseOAuthBearerTokens(OAuthOptions);

In the Instruments project, you will add this statement to the Startup class, which configures the app to process and validate incoming tokens:

Configuring, running, and interacting with your apps

When you are working with a separated apps (Identity Server and Instruments), each app’s project is loaded in Visual Studio. That means you have two instances of Visual Studio running.

Then, you run/execute the apps. Each will be configured on its own customized TCP port, and run on your computer’s IIS Express developer web server.

Interact with your apps using Fiddler.

In Fiddler, compose requests to the Identity Server app for these reasons:

Register a new user account (to /api/account/register)

Request an access token (to /token)

In Fiddler, compose requests to the Instruments app (or any resource server app) for this reason:

Request a resource (GET, POST, etc.), and include the access token in the request

Compose a typical GET request that includes a token

The image below shows a typical GET request that includes a token. The request needs an “Authorization” request header, in addition to whatever else gets configured.

Click to open it full-size in a new tab/window.

Compose a typical POST request that includes a token

The image below shows a typical POST request that includes a token. The request needs an “Authorization” request header, in addition to whatever else gets configured.

Separated apps and security components need special configuration

When you are developing your separated projects, you are also testing them on your localhost instance of the IIS Express web server. As a result, both projects are running on the same computer.

What this means is that the token issuer – the Identity Server app on your computer – is using the computer’s digital certificate to sign (encrypt) the token.

Then, the token validator – the Instruments app on your computer – is using the same digital certificate to decrypt the token.

When you deploy the Identity Server app and the Instruments app to Azure, they will likely end up being deployed to different computers (or virtual machines). What will happen then?

Your separated projects will not work. Why? The digital certificates will not match.

How can this be fixed? By generating a custom “machine key”, and saving it with each app that participates in a shared security environment.

Configuring a solution

In the Week_08 folder of the GitHub repository, there is a new source code file, for a controller named GenerateMachineKey. Download it, and temporarily add it to one of your projects. (Its project namespace must be changed to match your project’s namespace.)

Next, request the resource /generatemachine key. A “text/plain” result will be delivered, and will look similar to the following. (Each time you request the resource, the values change. Why? Look at the controller code.)

Then, add this as the last entry in the system.web section of the app’s Web.config. Do this for BOTH the Identity Server app and the Instruments app. Test on your local machine, before deploying to Azure.

Definitions and terminology

In the sections that follow, a number of very important security definitions and terms are presented. Read, study, and understand. If you have questions, ask. We’ll use some of these this week, and continue using them next week.

Actor / user / requestor

An actor – or a user, or a requestor – is an entity that will interact with the web service.

Can be a human.

Can also be a programmed component in the web service itself. For example, an exception logger (which creates persistent objects).

Can also be a third-party programmed component, external to the web service. For example, an iPhone app.

Account (for an actor/user/requestor)

In a security context, an account is an object that represents the identity of an actor (user, requestor).

The object includes credentials, which minimally consists of an identifier, and a secret that’s shared between the actor and the identity management service.

Identity server

An account or identity management service is a programmed component that stores and enables the management of accounts. It also performs authentication.

In simple apps – for example, the web apps you created in your second-year web app programming course – the identity server is embedded in the app.

Soon, you will learn to separate (or decouple) the identity management service from an app. This will enable you to create distinct apps that can use the services offered by a shared identity server.

Account registration

Account registration is the process of requesting an account from the identity management service, using a registration process.

Almost always, a human is involved in the request. A human will always be involved if the account is for a human. If the account is for a third-party programmed component, then it is typical that the human that is responsible for the component performs the registration task.

Authentication

Authentication is the process of validating the credentials of an account. It is a task that’s done by the identity management service.

If authentication is successful, the result can vary:

1. In an app that includes an embedded identity management service, a security principal object is attached to the execution context.

2. In a web app with a browser interface, result #1 above happens. In addition, an HTTP cookie is generated, and returned in the response.

3. In a web service, result #1 above happens. In addition, an access token is generated, and returned in the response.

Security principal

A security principal is an “object that represents the security context under which the code is running.” (MSDN)

It can be inspected by your program code, so that you have decision-making information in your code path.

Resource

A digital asset on the web. Identified by a URI. Available in a predetermined representation, and/or in a negotiated representation.

Resource owner

A resource owner is the “owner” (or originator, creator) of a digital asset. Logically, an actor (user, requestor).

Outside of an execution context, a resource owner is an account. While code is executing, a resource owner is the security principal.

Resource server

A resource server:

Is a web service (has an HTTP API, aka web API)

Can also be a web app (has a browser-accessible interface)

A resource server enables access to resources.

From a security perspective, a resource could be:

Private, for the exclusive use of the resource owner (e.g. an email server)

Access-controlled, perhaps determined by a resource owner (e.g. a social network app)