Do you develop REST APIs for your personal projects or for internal business applications? Do you want to protect them from attacks but do not have enough time to develop the required infrastructure? Then this blog post is for you.
There are several ways to protect your REST APIs and provide granular access rights. This article focuses on the scenario where there are limited number of known users. The users are not allowed to self-register. Different users can have rights on certain functionality, but are not authorized to access other functions.
This scenario would be applicable for use cases such as internal applications in business and your personal web API hosted in the cloud.
There are different ways to achieve this:
- API Keys
The REST APIs can be accessed by passing certain API Keys in the header. This approach can be used to perform authorization when one REST API calls another REST API.
It is easy to implement. However, this does not provide user authentication mechanism. Also, if API Keys are supplied in the client application, they need to be obfuscated. It can carry the risk of leakage and hacking.
- Add user names to config file
In this, you store the user ids in a config file. When a request is received, authentication is performed using external resources and authorization can be done by checking the settings for the user id.
This can provide equivalent of group based authorization. However, it will require lot of maintenance overheads to maintain the list of user ids and groups in that file.
- Create database of users
Several apps perform authentication using a database of users. There are several templates available that can provide the boilerplate code. However, this will be development overhead as well as IT overhead when there are limited number of users.
- Azure Active Directory
Azure Active directory provides a way to authenticate the users as well as ability to add them to groups. The access rights can be granted as per group membership. Effectively, it provides the functionality of having your user database and removing the overheads. It also provides additional built in functionality such as two-factor authentication, forgot password etc.
In business scenario, it can save IT efforts to maintain users in additional resource. Users can be assigned rights based on the group.
In home automation scenario, you give certain access rights to kids (e.g. turn light on/off) and certain rights to adults (e.g. vault keys).
The consumer of the REST API can request token from active directory. This token is passed to the REST API. The custom authorization attribute(s) on the rest API can validate the token as well as the group membership. The authorization can be performed based on the group membership. The rest of the blog explains you how to do it.
The example (GitHub) provides a scenario where you have HomeHubService as REST API and there are multiple client applications. That includes HomeHubClient as the desktop application and Xamarin Forms based application as cross-platform mobile application on iOS and Android.
The walkthrough is in two parts:
1. Configuring the Active Directory
The backbone of this example is the Active Directory (AD). At the time of writing this blog, the classic portal has better support for AD than the preview in the new portal. So the walkthrough will be based on the classic portal.
- Go to the Active Directory in the classic portal. Note the default domain that it provides e.g. contoso.onmicrosoft.com. This will be the value for “ida:Tenant” settings in the Web.Config file.
- From the Groups tab, create two groups in it Level1 and SecretLevel. In the Configure tab for each group, note the object IDs for both the groups. These values will be added to the config file.
- Select Applications Tab and click on Add Application at the bottom. Select “Add an application my organization is developing”.
- Create one “Web Application and/or WebAPI” application and
- One Native Client Application
Application tab will look as follows:
- Select HomeHub Service -> Configure tab. Note the APP ID Url for the service. Copy this to “ida:Audience” in the Web.config
- Select HomeHub Service -> Click on Manage manifest and download it.
This is a JSON file. Set value of “groupMembershipClaims” to “SecurityGroup”. This is essential as this privilege allows the service to query groups from the active directory. Upload the updated manifest.
- In the permissions to other applications, provide permissions to Active Directory as follows:
In the “Application Permissions”, select “Read directory data”.
In the “Delegated Permissions”, select “Sign in and read user profile” and “Read all groups”
- Now select the client application -> Configure Tab. Note the client Id.
This is used in the app.config for “ida:ClientId”. In Xamarin, it corresponds to Constants.ClientId
- Give permission to the service in the app
Select permissions to other Applications. Select the following permission:
Windows Active Directory -> Sign in and read the user profile
HomeHubService -> Access HomeHubService
You can add users to Active Directory as desired. They can be made members of group to provide corresponding permission to functionality.
This configures the required active directory users, groups and permissions. It is time to open Visual Studio.
2. Visual Studio Solution
You can either obtain code from the GitHub repository or create a new solution. I’ll quickly explain how to create the new service, but rest will be focused on the example code from the GitHub.
- In the Visual Studio, create a blank solution e.g. HomeHub
- Add an ASP.NET Web API project to the solution e.g. HomeHubService
- When adding the project, select WebAPI and Change Authentication.
- Select Work and School Account as option and paste the value for default domain in it.
- Update the web.config with the values that you obtained while configuring the active directory. The fields can be found by searching TODO values.
- You can easily add WPF application or Xamarin mobile application to the solution. The values to be set in app.config (for WPF application) and in Constants.cs (for Xamarin Mobile App) are documented in the GitHub samples.
The GitHub repository consists of a service, a WPF application and a Xamarin Forms application.
The service consists of two controllers:
• LightsController – This demonstrates access at Anonymous level, Authorized level and at “Level1” Group.
• VaultController – This demonstrated access at “SecretLevel” Group.
The authorization is done through two custom authorization attributes. The attributes read the groups of the current user. Each attribute reads its level Id from the configuration file If the user belongs to the group, access is authorized.
This can be extended with more groups and attributes as desired.
WPF Client application
This application uses ActiveDirectory nuget package to perform authentication. The package has built in functionality for user to sign-in an obtain the token.
The application uses the client library to make calls to the service. The client library passes the token in the header. The results are displayed as simple message box.
The client library and the model library are both PCL libraries. So they can be shared across platforms.
Xamarin Forms application
This application is very similar to the WPF application in functionality. They both share the client library and the model library.
However ActiveDirectory nuget package is not available as “PCL” NuGet package. So it cannot be used directly in the portable project. The package is available on iOS and Android platforms.
So the mobile App uses IOC pattern to perform the required authentication functionality such as SignIn, GetToken and SignOut. It is done using IADAuthenticator interface that is implemented separately on both iOS and Android platforms.
This sample application can be utilized as boilerplate code to create internal applications in a business. So you can provide different access levels to different groups of users.
It can also be used to protect REST APIs in your personal projects such as home automation or other hobby software projects. So only the authorized users (i.e. you and your friends/family) can access it.
In spite taking all the above steps, if you are getting Unauthorized error, it can be due to the following cause(s):
1. AuthSettings may need update
Open Azure Resource Explorer – https://resources.azure.com/. Drill down to Site/Slot->Config->AuthSettings. If “allowedAudiences” is null or pointing to incorrect URL, authorization will not be allowed. You can type it there as JSON array.
Alternatively, go to https://portal.azure.com. Navigate to Site/Slot -> Authorization/Authentication. Make sure that App Service Authentication is “On”. Select Azure Active Directory as Authentication Provider. Click on the Advanced tab. Add url of your service to Allowed Tokens Audiences.
2. Global Admin may need to authorize
When you are launching the app for the first time, you may get an error “AADSTS90093: Calling principal cannot consent due to lack of permissions”.
If this happens, let your Global Admin login. S/he will be presented a dialog asking him/her to allow the app to access the services and the data. When Admin accepts it the app is usable to any permitted user.