DPS907 notes – Tue Nov 8

Another look at authentication. Introducing IA Server and the concept of a shared security environment.

 

Test today

The weekly test will be done at the beginning of the class timeslot at 11:40am.

 

Theme for today, and code examples

We have learned the foundations of identity management (including user accounts and claims), and authentication. Last week (and in Assignment 8) you built upon the identity management foundations.

This week, we will look again at the authentication process. Then, we will be able to design a system that will enable scale and flexibility, to support multiple apps that share the same security environment.

Code examples for today include:

IAServer (version 1) – A server app that’s dedicated to identity management and authentication tasks

SecuredCustomer – A secured web service that uses the security environment that’s managed by the app above

 

Revisit: How a security-aware app loads (starts up)

Last week, you learned a “simplified sequence” of steps/actions that happen when an app loads into server memory. Today, we add more detail, so that we can make progress.

Here is a more-detailed sequence of actions that happen when the app is loaded:

1. In the HttpApplication subclass (WebApiApplication), the Application_Start method runs

2. (for a Web API project…) In the WebApiConfig class, the Register method runs

3. The ASP.NET runtime scans the project, looking for evidence of an OWIN configuration

4. In the Startup class, the Configuration method is run (which in turn calls the ConfigureAuth method)

5. The user accounts database is initialized

6. The user manager component is loaded into memory – it is the API to the ASP.NET Identity system

7. (if we are authenticating browser users…) The sign in manager is loaded into memory
The sign in manager’s job is to validate credentials, and issue a cookie that is included in the response

8. Cookie characteristics/properties are configured

9. Load the cookie validation component…
A CookieAuthenticationProvider object is loaded by the UseCookieAuthentication method
If a request includes a cookie, this component will decrypt/decode it, and if valid, create an IPrincipal object and attach it to the request

10. Access token characteristics/properties are configured

11. Load the access token components (token-issuing and token-validating)…
Token-issuing component:
ApplicationOAuthProvider object (inherits from OAuthAuthorizationServerProvider, loaded by UseOAuthAuthorizationServer method, which is called by UseOAuthBearerTokens method)
This object will validate credentials, and issue an access token as the response
Token-validating component:
OAuthBearerAuthenticationMiddleware (loaded by UseOAuthBearerAuthentication method, which is also called by UseOAuthBearerTokens method)
If a request includes an access token, this component will decrypt/decode it, and if valid, create an IPrincipal object and attach it to the request

 

How do we know all this? Well, here are the links that have more information about each numbered action:

1. ASP.NET Application Life Cycle overview for IIS 7.0 – web

2. Statements in the HttpApplication subclass, verified by debug breakpoints

3, 4. OWIN Middleware in the IIS integrated pipeline – web
OWIN Startup Class Detection – web

5, 6, 7, 8, 10. Statements in the Startup class ConfigureAuth method, verified by debug breakpoints

9. Statements (as above), verified (as above)
A primer on OWIN cookie authentication middleware for the ASP.NET developer – web

11. Statements (as above), verified (as above), and…
MSDN OAuthBearerAuthenticationMiddleware Class doc – web
MSDN OAuthBearerAuthenticationExtensions Class doc – web
MSDN OAuthBearerAuthenticationOptions Class doc – webdd
SO UseOAuthBearerTokens vs. UseOAuthBearerAuthentication – web

 

These information sources were also useful. You can read/skim these to learn more:

OWIN OAuth 2.0 Authorization Server – web

ASP.NET Web API 2: HTTP Message Lifecycle (poster) – pdf

Lifecycle of an ASP.NET MVC 5 Application – webpdf

Web API v2 Security Architecture – part of a Pluralsight online course (free) – web

Authentication Filters in ASP.NET Web API 2 – web

A selection of articles that cover the scenario where a request includes a bearer access token in the Authorization request header. Bottom line, the AuthenticateAsync method, in OAuthBearerAuthenticationHandler validates the token. Sources: SO post, MSDN doc, MSDN blog post

 

Why do we care about this?

Security is hard. For programmers who are new to the ASP.NET Identity system, it can appear to be large and complex. Yes, it does provide a ready-to-use solution for what we care about (identity management, authentication, authorization).

However, we must know more about this solution, to answer real-world questions like these:

How can we modify the system, so that we can perform additional tasks after a successful authentication? (For example save/record the login date-and-time.)

How can we add another separate app (web app or web service) to the server, and share or re-use the existing identity management and authentication parts? It would be annoying for everyone – us as programmers, and our users – to require another user account etc.

Answers to these and related questions are presented below.

 

Understanding more about the authentication process

You already know that authentication is one of the three tasks done by any security system (the others are identity management and authorization).

Let’s take another look at authentication. It can actually be divided into two distinct sub-tasks:

  1. User account credential validation
  2. Cookie/token validation

 

User account credential validation

In a web app, where the request comes from a browser, a user will enter their credentials on an HTML Form. In an ASP.NET MVC web app, the request is typically processed by the Account controller, specifically its Login method. The resource URI is typically host.example.com/account/login.

Look at the sequence of steps/actions above.

This is done by 7 and 8.

In a web service, where the request comes from an HTTP client, a user’s app will gather a user’s credentials by using its own native user interface. In an ASP.NET Web API web service, the request is typically processed by the ApplicationOAuthProvider class, specifically its GrantResourceOwnerCredentials method. The resource URI is typically host.example.com/token.

Look at the sequence of steps/actions above.

This is done by 10 and 11.

During this user account credential validation process, the following happens:

  1. The method validates the credentials, by attempting to match them to a user account in the identity store
  2. If successful, a cookie or access token is created and “issued”

The web app method creates a cookie, which gets returned with the response. Often the response will redirect the just-authenticated user to another web page (resource). As you have learned before, the user’s browser stores the cookie, and then includes it with each subsequent request back to the web app.

The web service method creates an access token, which gets returned as the response. As you have learned before, the user’s HTTP client must do whatever’s necessary to save/store the access token, and then include it (in a request header) with each subsequent request back to the web service.

 

Cookie/token validation

In the web app scenario, assume that the incoming request – to any page (resource) in the web app – includes a cookie.

In the web service scenario, assume that the incoming request – to any resource in the web service – includes an access token.

During this cookie/token validation process, the following happens:

  1. The cookie/token is decrypted, and validated
  2. If successful, an IPrincipal object – specifically a ClaimsPrincipal – is created, using the user account and claims data that is found in the cookie/token; the IPrincipal object is then attached to the request thread

How is the cookie/token decrypted by the server? Using a value known as a “machine key”. This is a secret and cryptographically unique value, that is created when the server operating system is installed, and is then securely stored by the operating system. The machine key is used to encrypt identity data into a cookie/token. At the browser or HTTP client, the cookie/token cannot be decrypted, as neither has the machine key. In a single isolated web app or web service scenario, the server is both the token issuer, and the token validator.

How is the cookie/token “validated”? Well, a number of things are done:

  • Was it issued by a trusted authority (yes, the issuer and validator are the same app on the same server)
  • Is it valid from a date-and-time perspective (it has an “expiry date” value)
  • Can the identity data be correctly transformed into an identity object (ClaimsPrincipal)

If all this works, then (as stated above) a ClaimsPrincipal object is created, using the user account and claims data that is found in the cookie/token. The object is then attached to the request thread, and functions that happen later in the request-processing pipleline can query the security principal and perform authorization tasks.

Look at the sequence of steps/actions above.

In a web app, this is done by 9.

In a web service, this is done by 11.

 

Maybe we can split the authentication process…

After learning more about the authentication process, one could conclude that it is possible to split the authentication process – credential validation, and cookie/token validation – into separate apps.

Yes, we could.

This would enable us to have an app dedicated only to identity management and authentication (the credential validation part).

Then, we could create a separate app, with the authentication part it needs (cookie/token validation), as well as the ability to perform resource authorization. (To perform resource authorization, an app only needs access to the security principal on the request thread.)

Additionally, we could create more apps that could use the services of the identity management and authentication server. This enables us to create a portfolio of apps that share the same security environment.

 

Introducing the IA Server

One of today’s code examples is IAServerV1. Its name – IA Server – means “identity and authentication server”. It has the following features:

  • Identity management (user accounts, claims)
  • Authentication for browser clients, and cookie issuing
  • Authentication for HTTP clients, and access token issuing

 

Please note that the IAServerV1 code example in the week 9 folder is a “version 1” product.

Soon, a “version 2” product will be posted, and will include the user account and claims management features that you are currently working on in Assignment 8.

 

How to use IA Server

IA Server is intended to be used with another app. IA Server will take care of identity management and authentication, so you do not have to add those features to the other app.

When you are programming and testing your app, you will have two instances of Visual Studio running. One will have (and run) the IA Server, and the other will have (and run) your app. Therefore, both will be running on your computer’s localhost instance of the IIS Express web server.

 

Configuring all your apps with a “machine key”

As discussed earlier, the encryption and decryption process for cookies or access tokens uses a “machine key”, which is a secret and cryptographically unique value, that is created when the server operating system is installed, and is then securely stored by the operating system.

The access token issuer – which is the IA Server app – uses the machine key to encrypt the access token.

Then, the access token validator – which is your app – uses the same machine key to decrypt the access token.

Both apps are running on the same computer, so they will be using the same machine key. It all works fine.

However, when you deploy the IA Server app and your other app to a real public web host (e.g. Azure), they will likely end up being deployed to different computers (or virtual machines). What will happen then?

Your app will not work. Why? The machine keys – on different computers (or virtual machines) 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. The IA Server has a controller that will do this task. Request the resource:
/generatemachinekey

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 – the values get regenerated.)

<machineKey validationKey="7F6CB937...(snipped)...E1625114" decryptionKey="B74EFD4D...(snipped)...40D1AC26" validation="SHA1"/>

Then, in the IA Server, and in each app that will share the same security environment, add this as the last entry in the system.web element of the app’s Web.config source code file.

 

Keep it clean – do not add app domain logic to IA Server

Before moving on, we urge you to dedicate the IA Server to identity management and authentication (cookie/token issuing) only. Please do not add any app domain logic to the IA Server.

 

Building a web service that can use the IA Server

At this point, let us state a few reminders:

A security system – like our ASP.NET Identity system – includes identity management, authentication, and authorization.

The authentication process is divided into two distinct sub-tasks, credential validation, and cookie/token validation.

The IA Server is an app that includes identity management, and the credential validation part of authentication.

So… how can we ensure that one of our web service apps is configured with the access token validation and authorization parts?

Well, every app that we create already is configured to handle the authorization task. (It’s built in, and loads when the app loads.)

That leaves access token validation. How can we add that? Continue reading below.

 

Adding access token validation to a web service

To add access token validation to a web service project, there are four tasks to be done:

  1. Using the NuGet Package Manager, add some packages
  2. Create a “startup” class that loads the access token validation component
  3. Configure the app to use the just-loaded component
  4. Add a new “machine key” value to the app’s Web.config file

 

Before continuing, make sure that your project does NOT already use a security environment. In other words, the app’s project template must NOT use any of the authentication settings (e.g. “Individual User Accounts”). The “Web service project v2” template can be used, because it includes a ready-to-use data-rich environment (the Chinook sample database), but it is NOT configured for a security environment.

 

Using the NuGet Package Manager, add some packages

Using the NuGet Package Manager, add these packages:

  • Microsoft.Owin.Security.OAuth
  • Microsoft.AspNet.WebApi.Owin
  • Microsoft.Owin.Host.SystemWeb

 

Create a “startup” class that loads the access token validation component 

Create (or copy from an existing security-aware project) a Startup.cs source code file, in the project root folder. It will load the access token validation component, using the following code:

[assembly: OwinStartup(typeof(ProjectName.Startup))]

namespace ProjectName
{
  public class Startup
  {
    public void Configuration(IAppBuilder app)
    {
      // This app does NOT create (issue) bearer tokens, but understands how to read (decrypt) and use them
      app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
    }
  }
}

 

Configure the app to use the just-loaded component

In the App_Start > WebApiConfig.cs source code file, the Register method of the WebApiConfig class needs some additional statements to configure the app to use the just-loaded access token validation component. Just before the statement that configures attribute routing, add these statements:

  // Configure Web API to use only bearer token authentication.
  config.SuppressDefaultHostAuthentication();
  config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

 

Add a new “machine key” value to the app’s Web.config file

Using the procedure that you learned above, generate a new machine key, by using the IA Server app.

Then, add it to that IA Server app, and to your app.

 

At this point in time, your app will be able to perform access token validation. As a result, whenever you use the [Authorize] attribute in your controllers (or use any other code that accesses the security principal), the app will be able to make authorization decisions.

 

Working with the IA Server and your app

As noted earlier, when you are working with a separated apps (IA Server and your app), 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. Yes, you still interact with your apps using Fiddler.

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

  1. Register a new user account (to the /api/account/register endpoint)
  2. Request an access token (to the /token endpoint)

In Fiddler, compose requests to the your app for this reason:

  1. 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.

fiddler-how-to-get-with-token

 

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.

fiddler-how-to-post-with-token

 

Summary

Today, you learned more about the way in which an app loads/starts.

This information was useful, because it helped us identify the components involved in the authentication process.

Then, we learned that the authentication process has two distinct sub-tasks, each of which can be done in separated apps.

Finally, we learned more about separated apps, including a dedicated and sharable identity management and authentication (issuer) server, and an app that can use a shared security environment.

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
%d bloggers like this: