How to protect your MVC web app using ACS & OAuth2 bearer tokens
Disclaimer
ACS & HttpModules are no longer the de facto tools to achieve this sort of business. Please refer to AAD and OWIN Security Components if you have the freedom to do so.
TL;DR
Securing your MVC application using ACS is a simple task nowadays. The same doesn't apply for securing your REST endpoints with OAuth2 bearer tokens against third party applications, like command line tools. Using AcsOAuth2, this post will guide you through configuring your app such that it can handle OAuth2 Bearer tokens - emitted by ACS - sent from the client via the Authorization
HTTP header.
Introduction
We want to be able to authenticate requests between a command line application and an ACS protected web application. We will use OAuth2. This will be the overall flow:
- Given an authenticated user, the web application generates an authorization code, scoped to the user and a predefined identity.
- A third party application can reach Azure ACS and use the predefined identity to exchange the authorization code for OAuth2 access and refresh tokens.
- The third party application talks to the web application using the access token. It will be authenticated as the predefined identity, but carrying all the claims the original user's identity carried.
Create an application protected by ACS
In order to create your app, I will ask you to follow the official guide, which is very straightforward. What you should get out of it is an auth-capable web application.
Once you application is secure with ACS, follow the Using the JWT Handler With WIF Applications section of that Cloud Identity blog post. It will guide you through configuring JWT tokens for the authentication process. After importing the service's certificate into Local Machine / Trusted People, please do it again into the Local Machine / Personal certificate store.
Now, if you try to make an HTTP request to it using a simple web client (e.g. curl), you will notice the application will always respond with a 302
code, asking you to authenticate with whatever ACS namespace you have configured it. We want to be able to recognize requests that might have the Authorization
HTTP header set with a valid OAuth2 bearer token.
Create ACS Service Identity
We need to configure an identity on ACS which will serve as the service identity between your HTTP clients and your web application.
On the ACS management interface, under Service settings, click Service identities. Click Add. Pick a name for the service identity and click Generate to create a key for that identity. Click Save.
Update Identity Redirect Address
In order to enable ACS to emit OAuth2 access tokens for your app, you must configure the redirect address used for the previously created service identity.
First, create a new console application in Visual Studio. Add AcsOAuth2 as a NuGet dependency: Install-Package AcsOAuth2 -Pre
. Then simply run the following code to set up the redirect address. The actual value is irrelevant, but remember it for you will need to use it later. As a rule of thumb, use the realm value you used before for your relying party application.
You need to do this only once, per app & per service identity.
Use the JwtBearerAuthenticationModule
Let's plug in the JwtBearerAuthenticationModule
to your web application's request pipeline.
Just like the command line application, add AcsOAuth2 as a NuGet dependency: Install-Package AcsOAuth2 -Pre
to your web application.
Then, open your web app's Global.asax.cs and make the following modifications:
You should match AUDIENCE_URI with the relying party's audience uri. ACS_NAMESPACE should simply be the name of your ACS namespace. You can find the value for CERTIFICATE_THUMBPRINT by going back to the ACS management portal, clicking on Certificates and keys, under Service settings, then Service Namespace (X.509 Certificate) and copying the thumbprint of the shown certificate.
Generate Authorization Codes
Your web application is now able to understand OAuth2 access tokens emitted by your ACS namespace. A third party application can get a hold of an access token by trading in an authorization token against ACS. Your web application can create authorization codes by using the AcsOAuth2.anagementService
class:
The USERNAME value should be the Name property on the ClaimsIdentity object of the authenticated user.
Authenticating
Once generated, an authorization code can be given to the third party application and used for the authentication process: