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.
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.
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.ActiveDirectory” and “Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms” under the references node in the Solution Explorer in Visual Studio of ShipperClient and “System.IdentityModel.Tokens.Jwt” in 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:
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:
This has the same meaning as in the ShipperClient
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.
Now you can run the sample with your ACS namespace.
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
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: