Protect ASP.NET Core Web API resources with Azure Active Directory.
31 May 2017In this article I will show you how to protect your ASP.NET Core Web API resources with Azure Active Directory through a real scenario.
Scenario
We currently have REST API resources written in ASP.NET Core Web API. These resources are hosted on Azure and are consumed by IOS, Android and various backend clients. At the same time, Azure Active Directory (AAD) is configured on the our Azure subscription. Unfortunately, there is no security in the our REST API right now. Anyone can access these resources with POST or GET requests easily. So, we want to protect resources from public and this should be done in safest and shortest way.
Possible Solutions
- You can write your own security system for this scenario. However, this is a time-consuming and unsecured solution.
- You can purchase a third party software. So, this option will be costly.
- You can use, your already configured and ready Azure Active Directory (AAD) Service!
Using AAD service, you can control access and protect your resources with JSON Web Token (JWT).
What We Need?
- ASP.NET Core Web API
- Azure Active Directory
ASP.NET Core Web API
In this phase, we will create a sample REST API with the ASP.NET Core Web API and publish it as App Service on the Azure. I will create the project with Visual Studio 2017.
Firstly, start Visual Studio 2017
-
Select File menu.
-
Move your mouse to New menu.
-
Click the Project… menu item.
-
Select .NET Core from the left menu.
-
From the options, mark ASP.NET Core Web Application (.NET Core).
-
Type the name of project. I call it CorpAPI.
-
Click OK to continue.
-
Select ASP.NET Core 1.1.
-
Select project type as Web API.
-
We make sure that Authentication is No Authentication. If not, click Change Authentication button for change it.
-
Click OK to create project.
After we have create our project, a screen image will be similar to below image.
Now, we will configure Azure App Service from Azure Portal.
-
Select New from left menu.
-
In this blade select Web + Mobile.
-
Select Web App.
-
In App Name field, type corpapi as our project name. If Azure does not accept the name you typed, you can type different name. This should be Azurewide unique.
-
Select suitable Azure Subscription.
-
We wanted to create a new Resource Group. Select Create new and type Resource Group name. Name it like RG-CorpApi.
-
We chose the free App Service Plan because it is demo scenario. This can be change according to the scenario.
-
Click Create button to start operation.
We are opening App Service that we have created.
-
From the left menu select Resource groups.
-
Click RG-CorpApi resource group.
-
In this blade click Overview.
-
Find corpapi and click on it.
We have to publish our project to Azure as App Service. So , we need to publish settings.
-
Select Overview.
-
Click Get publish profile button.
-
Our browser will be download publish profile file. My publish file name is corpapi.PublishSettings, yours might be different according to your AppService name.
-
Right click CoreAPI project.
-
Click Publish… menu item.
-
Select Import profile option.
-
Click Publish button.
-
On the Import Publish Settings File window, we select the file we downloaded from Azure Portal. The file name corpapi.PublishSettings may be different for you.
-
Click Open button.
-
Our project while being sent to Azure. On the Output window you can see similar informations.
-
You should see Publish: 1 succeeded… on the Output window when the publish operation is finished.
Open your browser.
-
At the address line type https://corpapi.azurewebsites.net/api/values and press enter. This address can be change according to your app service name.
-
If the API is working, it will be a JSON output like on screen.
Our API is ready now. 😄 However, as I mentioned before, It is public and that is not we want to. 💀
Azure Active Directory
After this phase we will create Azur Active Directory Applications on Azure Active Directory and will be use them for protect our API.
-
From the left menu, we select Azure Active Directory. If you do not find this option, you can find it in More services.
-
In this blade we click App registrations item.
-
To register for the new AAD Application, click on the New application registration button.
-
Type the name of the AAD application in the Name field. I called it CorpAPI.
-
Leave Application type as Web app / API. We specify this app type as a Web app or API application.
-
For the Sign-on URL section, we currently type our API address.
-
Click Create button for create our aad application.
-
In AAD blade, click App registrations
-
Search for CorpAPI application.
-
Click on it for open.
When our application opens, you will see a screen similar to the one below.
- Important point on this screen is Application ID. This ID is our application unique ID. Automatically generated and assigned to our application by AAD. We’d better copy it to a somewhere. 😄
Let’s set aad application permissions.
-
We select Required Permissions in current blade.
-
Click Add button.
-
Select Select an API item.
-
In Select an API blade, mark Microsoft Graph item.
-
Click Select button.
-
Select Select permissions item.
-
Choose the Read and write directory data permission found in Application Permissions and Delegated Permissions. More specifically, choose permissions for Read and write directory data under Application Permissions and Read and write directory data under Delegated Permissions. If we have selected other than these permissions, just uncheck these permissions.
-
Click on Select button.
- We have chosen our API and permissions. Now click on the Done button.
-
In Required permission blade, as you can see on the screen we added Microsoft Graph. There is one Application Permission and one Delegated Permission permission.
-
We click on Windows Azure Active Directory, which is come by default.
-
As we did before, we choose the Read and write directory data permission under Application Permissions.
-
We choose permissions for Read and write directory data under Delegated Permissions.
-
If we have selected other than these permissions, remove these permissions and than click on the Save button.
After granting the permissions, Required permissions blade will appear as below.
We will add a native AAD application in a similar way. This time the type of our application will be Native Application.
-
From the left menu, select Azure Active Directory.
-
In this blade click App registrations item.
-
To register for the new AAD Application, click on the New application registration button.
-
We type the name of the AAD application in the Name field. I called it CorpNativeAPI.
-
This time we select the Application type as Native application.
-
For, Sign-on URL type https://corpnativeapi.azure-mobile.net . This might be different according to your native app name.
-
Click Create button for create our native aad application.
- We are searching for CorpNativeAPI application and click on it.
- Again, important point on this screen is Application ID. This ID is our application unique ID. Automatically generated and assigned to our application by AAD. We’d better copy it to a somewhere. 😄
-
We select Required Permissions in current blade.
-
In this blade click on Required permissions.
-
Select Select an API item.
-
In Select an API blade, Search CorpAPI AAD Application.
-
Mark the CorpAPI.
-
Click the Select button.
-
Select Select permissions item.
-
Select Access CorpAPI permission.
-
Click the Select button.
- Click the Done button.
If everything ok, you should see a Required permissions screen similar to the one below.
- Lastly we need to do is click on the Grant Permissions button and answer the question Yes. Thus, we have given the necessary permissions to account.
Take a look at what we have done on the AAD so far:
- We created a Web Application / Web API in the AAD and added the necessary permissions.
- We created a Native application in the AAD and added the necessary permissions.
Here a unique Application ID is created for each application we create on the AAD. The AAD is responsible for the creation of these unique application identities.
We have completed the Azure AD configuration “least liked” section.. 😄
Now we will generate JSON Web Token and try our API using Postman application.
First of all we need to find our Endpoint address to generate token.
-
From the left menu, we select Azure Active Directory.
-
On this blade we click App registrations item.
-
Click on Endpoints button.
- In blade, OAUTH 2.0 TOKEN ENDPOINT is our endpoint address. In my scenario, the endpoint address is https://login.windows.net/64114426-b4a0-4e3a-8efb-9ea15136cd2e/oauth2/token Your endpoint address will be different.
Briefly we will do our POST requests to this address for generate token.
-
From the left menu, we select Azure Active Directory.
-
On this blade we click App registrations item.
-
Click our CorpNativeAPI native application.
- We take note of the Application ID of our native application.
-
From the left menu, we select Azure Active Directory.
-
On this blade we click App registrations item.
-
Click our CorpAPI.
- On this blade, click Manifest button.
- In the manifest file we search for identifierUris. This is the name of our resource. My resource name is https://cevizbilgi.com.tr/c97dc3f7-7ae6-4b3d-87c4-ab728339e0ac. Yours will be different.
Now we have all informations, we need to generate the token. Let’s do it! 😄
Open Postman application. By the way, you can choose a different application such as Fiddler. That is your own choice.
-
We select our request type as POST
-
Type address we have taken from Endpoints
For me it is https://login.windows.net/64114426-b4a0-4e3a-8efb-9ea15136cd2e/oauth2/token this will change for you.
-
Click Body tab.
-
Select x-www-form-urlencoded option.
-
We add a key named resource. Value is the url we got from the manifest file. My url is https://cevizbilgi.com.tr/c97dc3f7-7ae6-4b3d-87c4-ab728339e0ac .
-
We add a key named grant_type. Value is a password
-
We add a key named client_id. Value is our Native AAD Application Id. This value for me, 74f671cc-e205-48bc-8d68-a3fec58cd0bd
-
We add a key named username. Value is your account name. My account name is mehmet.kut@cevizbilgi.com.tr
-
We add a key named password. Value is your account password.
-
Click Send button for send our request.
-
If the request is successful, it will be displayed as on screen. We will use this access_token to access our resources. 👍
-
Please notice that, access token is a token that is valid for a certain period of time. We can regenerate a new access token using refresh token instead of asking username and password every time.
Now, we will try to access the ASP.NET Core Web API project with Postman. In beginning of article we published this project to Azure as an App Service
-
We select our request type as GET
-
Type our API address for request.
-
Click Send button for send our request.
-
As you can see, we went through the API without any authentication.
Let’s go back to Visual Studio CorpAPI application. Now, we are making our WebAPI application safe.😄
- Open Package manager Console. We need Microsoft.AspNetCore.Authentication.JwtBearer package. Type Install-Package Microsoft.AspNetCore.Authentication.JwtBearer command to add the package to the project.
-
Open appsettings.json configuration file.
-
We will add AzureAd section.
"AzureAd": {
"AadInstance": "https://login.microsoftonline.com/{0}",
"Tenant": "64114426-b4a0-4e3a-8efb-9ea15136cd2e",
"Audience": "https://cevizbilgi.com.tr/c97dc3f7-7ae6-4b3d-87c4-ab728339e0ac"
}
AadInstance You do not need to change this value. Tenant You can find this value in your Token Endpoint address. Audience This value is in the manifest file. We had taken that value before.
-
Open Startup.cs file.
-
In the ConfigureServices method, we add the following code.
services.AddAuthentication();
- We add the following code in the Configure method.
// Configure the app to use Jwt Bearer Authentication
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAD:Tenant"]),
Audience = Configuration["AzureAd:Audience"],
});
-
We open the ValuesController.cs file under the Controllers folder.
- We are adding the following code
using Microsoft.AspNetCore.Authorization;
- For security we add the following attribute to our class.
[Authorize]
Publish project to Azure
-
Right click CoreAPI project.
-
Click Publish… menu item.
-
We publish the application by clicking Publish button on the screen to be opened.
Let’s look at the API we’re protecting now 😄
-
We select our request type as GET
-
Type our API address for request.
-
Click Send button for send our request.
-
As you can see, the API is now protected. We received a 401 Unauthorized error because we did not provide the necessary security information for access. 👍
Now let’s see how to access the API with access token that we have already generated.
-
We select our request type as GET
-
Type our API address for request.
-
We are adding Authorization key to header section with value “bearer accesstoken”. The important point here is access token lifetime when it is expired you have to use refresh token or username and password to generate new access token again.
-
Click Send button for send our request.
-
Voilà! Our token has been verified by AAD and we accessed our resource securely. 👍
We have reached our goal. 😄
I’ve shown you so far:
- We have seen how to build a project in the ASP.NET Core Web API.
- We published the WEB API as Azure App Service on Azure.
- Configured a Web App / Web API application in AAD
- Configured a Native application in AAD
- We protect the WEB API with the JWT package.
- We were able to access it with our access token
In fact, there are a few more things that I have wrote in this article but those are not in real scope. This topic is easy but if you missed few step it won’t work. Do not hesitate to send me an e-mail if you have any problems
In addition, with AAD as an enlightenment point, you can add protection not only with the ASP.NET Core Web API but also with APIs written in different technologies such as NodeJS, PHP and others so this is cool 😎