Authentication via Browser Dialog - Readme

Overview

This sample demonstrates how to use the Windows Azure Active Directory Authentication

Library (ADAL) package to add user authentication capabilities to a WPF client. Furthermore, it demonstrates how to authenticate calls to a Web API REST service by leveraging the JSON Web Token Handler for Microsoft .Net Framework 4.5 (JWT handler).


ADAL is a library, built on .Net 4.0, offering a simple programming model for Windows
Azure Active Directory (AAD) in client applications. Its main purpose is to help developers easily obtain access tokens from Windows Azure Active Directory, to be used for requesting access to protected resources such as REST services.


The JSON Web Token Handler for Microsoft .Net Framework (JWT handler) is a library built on .NET 4.5 which adds the JSON Web token format as a first-class citizen in the .NET programming model. The JWT handler can be used both within the WIF pipeline, to secure existing Web sites and services with JWT tokens in addition to the formats supported out of the box (such as SAML1.1 and SAML2). The JWT handler can also be used standalone, with no direct dependencies on WIF configuration.

Prerequisites

Running the Sample

Open the solution in Visual Studio 2012.

The sample solution includes three projects:

The sample is configured to run the ShipperServiceWebAPI  in IIS Express on https. In order to get the sample working, please copy the localhost certificate with friendly name = “IIS Express Development Certificate” from Local Computer -> My store to Trusted Root store, otherwise the client complains that the https certificate is invalid.

To run the sample, hit F5.

The solution is configured to start multiple projects and will take care to put all the right

parts in motion. The sample is already configured to connect to a pre-provisioned ACS namespace which knows about the sample service and the identity providers it trusts.

 

In order to see the scenario in action, simply click on the “Display your shipments” button in the ShipperClient UI. Given that calling the corresponding service requires presenting a security token, the application will prompt you with a dialog displaying the list of Identity Providers configured in ACS that are trusted by the ShipperService. That dialog is provided by ShippingClient and populated according to the settings recorded by the pre-provisioned namespace.

You can authenticate using your own credentials to Google or Microsoft account, or sign in as one of the test users provided as part of the LocalSTS project. Upon successful authentication you will see shipments displayed in the form that are returned from the Shipper Service. 

Now that you have a token, you will see that subsequent calls to the service will no longer trigger an authentication prompt, as ADAL caches the tokens in the in-memory cache by default.

In order to demonstrate how to enforce authorization logic when invoking a service, the
sample scenario is configured to allow the creation of new shipments only to members of the group “Sales”. In our setup, that means “adam” from the Local STS and any user from Windows Live ID or Google. Choose “mary” from Local STS to go through the unauthorized code path.

When you want to stop debugging, hit the Stop button in Visual Studio.

Details

Let’s take a quick look at the structure of the solution. If you want more detailed information, please refer to the comments in the code.

As mentioned before, ShipperClient is a .Net 4.0 project using ADAL to display the Browser dialog and get a JWT token from ACS and ShipperServiceWebAPI is a .Net 4.5 project using the JWT handler to validate the JWT token received from the ShipperClient. ADAL is provided in the “Active Directory Authentication Library” NuGet package and JWTSecurityTokenHandler in the “JSON Web Token Handler for Microsoft .Net Framework 4.5” NuGet package. Notice the assemblies  "Microsoft.IdentityModel.Clients.ActiveDirectoryand “Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsFormsunder the references node in the Solution Explorer in Visual Studio of ShipperClient and “System.IdentityModel.Tokens.Jwtin ShipperServiceWebAPI.

Let’s start from the client side of the solution. Open the ShipperClient project and lookat the app.config. Here you will see some values that are used later by ADAL:

  1. Tenant
    This value represents the full URL identifying the Windows Azure Access Control
    (ACS) namespace. This sample comes with a pre-configured test ACS namespace.
    You will find instructions on how to re-configure the sample to connect to your
    own ACS namespace later in this document.
  2. ServiceRealm
    This is a
    security domain identifying the target service within the tenant.
  3. TargetService
    This is the endpoint of the REST service that the Client is targeting. In this
    example it is the service offered by the ShipperServiceWebAPI project.

Now open ShipperClient.xaml.cs. Here you will see that we have setup some application-level members, that include AuthenticationContext (a “proxy” for your tenant). On initialization the AuthenticationContext is set to the tenant specified in the app.config. When either Display or Create Shipments is clicked GetAuthorizationHeader() is called to get back a string containing an access token that could be added to the http request’s authorization header.

GetAuthorizationHeader() does the below :

You can see how the JWT token is utilized in the GetResponseFromService method, which is called by both the Display and Create Shipment methods. Here the authorization header (obtained by calling GetAuthorizationHeader() (which in turn calls CreateAuthorizationHeader method on the AuthenticationResult) is added to the HTTP Request.

Moving on to the service side: open the ShipperServiceWebAPI project and examine web.config. Here you will see two values:

  1. Tenant

 This has the same meaning as in the ShipperClient

      2. AllowedAudience

This contains the value of the service’s Audience URI, e.g. which security realm(s) should be present in an incoming token in order for it to be considered intended for the current service.

Now take a look at the Global.asax.cs. The most interesting class here is  TokenValidationHandler, an implementation of DelegatingHandler.   TokenValidationHandler‘s purpose is to process request messages before they reach the application code and enforce authentication requirements. The method TryRetrieveToken inspects incoming http requests to verify if the authorization header contains an OAuth2 header with a bearer token. If a bearer token is not found, the request is not authorized and an unauthorized status code is sent back to the Client. If the header contains a bearer token, it is validated through the JWT handler. A TokenValidationParameters object is created to set the expected properties, issuer, audience and signing token, on the token. The method JWT handler.ValidateToken is then called to validate the token and, upon successful validation, a new ClaimsPrincipal instance is set as the Principal of the current thread and as the Current user in HttpContext.

ShipmentController.cs contains some claims authorization logic, to enforce the constraints on shipment creation described earlier in this document. The sample places that code there for simplicity and clarity, however please note that nothing prevents you from moving that logic into the TokenValidationHandler if you want to keep your controller free from any access control code.

Configuring the Solution to Use Your Own ACS Namespace

The sample is pre-configured to run using a test tenant, https://humongousinsurance.accesscontrol.windows.net. You can change this sample to use your own ACS namespace as follows. 

Important: please do not use any namespace you would be using for production services as some of the required settings might require deletion of data.

  1. Add Identity Providers to the ACS tenant :
    Go to Identity
    Providers in your tenant and click Add under Identity Providers. You could add available Identity Providers like Google, Yahoo and Live. To add Local STS,
    choose WS-Federation Identity Provider under Add a custom identity provider. Click Next and upload the metadata from file; it can be found in the LocalSTS project under FederationMetadata\2005-07\FederationMetadata.xml.
  2. Add the service as a Relying Party : Go to Relying Party Applications in your tenant and choose Add under RelyingParty Applications. Choose to specify settings manually. Enter urn:shipperservice:interactiveauthentication for the Realm, http://localhost:34000/Interactive  for the Return URL and choose JWT for the token format. Choose your identity providers; allow it to create a rule group for you.
  3. Edit your rule group for the app. Add pass through rules for the LocalSTS for
    the following claim types; role, emailaddress and name.
  4. Change the Tenant in the app.config of the ShipperClient project and web.config of the ShipperServiceWebAPI project to match your own ACS namespace URL.

Now you can run the sample with your ACS namespace.

Deploying the Shipper Service to Windows Azure

The sample solution is designed to run from your local machine; you can explore the
scenario without having a Windows Azure subscription, and in fact you can choose to use ADAL to connect to Windows Azure Active Directory regardless of where you will run your services.

That said, here are detailed instructions you can follow if you want to deploy the ShipperServiceWebAPI to Windows Azure.

The steps below assume that you are using the October 2012 release of the Windows Azure SDK. Also note that to debug you will need to run VS in administrator mode.

 1. In the Solution Explorer, right click on the ShipperServiceWebAPI project and choose Add Windows Azure Cloud Service Project.  This will create a new project called ShipperServiceWebAPI.Azure.

2. Make sure that multiple startup projects are still enabled. The following should be marked as startup projects
now:

3. To test on the local simulation environment: open app.config in the ShipperClient project and change the TargetService value to http://127.0.0.1:81/.

4. To publish select Publish on the ShipperServiceWebAPI.Azure project. Select the Cloud Service where you would like to deploy to and choose Publish.

5. Once published open app.config in the ShipperClient project and change the TargetService value to the URL of the published service.

6. Once the deployment took place: before launching the debugger, change your startup projects settings so only the following projects are enabled:

Security Considerations

  1. The local STS is provided as an
    alternative to using your own ADFS instance, it does not demonstrate any ADAL
    or JWT handler capabilities and should not be used as a basis for creating your
    own STS.
  2. When a custom token cache is plugged
    into ADAL, make sure that the entries in the cache are encrypted so that they
    are secure.
  3. When the app receives tenant url and
    resource Id in 401 challenge, make sure to validate both of them. ADAL could do
    authority validation of AAD and ACS, but when the authority is ADFS, an out of
    band validation should be done. Similarly, an out of band validation should be
    performed on resource Id.
  4. Note that the browser dialog that is
    used for the authentication flow in ADAL does not have an address bar.
  5. The JWT Tokens issued by ACS are not
    encrypted and hence must be sent to the Service on a secure channel like https
    in order to prevent information disclosure, spoofing and other security
    attacks.
  6. The exceptions thrown by the JWT
    handler could contain sensitive information and it is up to the applications
    using it to make sure that this sensitive information is not sent to the
    Client.
  7. JWT handler could be configured to
    skip audience verification and Issuer verification. The security implications
    of turning off these checks should be understood.
  8. JWT handler does not log the token but
    application logging the tokens should be careful about information disclosure.