Authentication for Micro-services using Azure AD

In today's interconnected world, securing access to resources is a fundamental requirement for any application. OAuth is a popular open standard for authorization that enables applications to securely access user resources. However, implementing OAuth can be complex, especially in microservices architectures where multiple services need to communicate with each other securely. This is where Azure AD comes in - a cloud-based identity and access management platform provided by Microsoft that allows organizations to authenticate and authorize users and applications. We will discuss the benefits of using Azure AD for OAuth, how to set up an Azure AD tenant and register an application, and how to use OAuth to authenticate users and authorize access to Web APIs representing the entry point to those Micro-services.

Registering a Web API in Azure AD

A Web API requires a URI scope. That is a unique ID for identifying the API. It could be the URL where the API is hosted or any other URN. Keep in mind two things when assigning this scope to an API. 

  • It should be unique across all the APIs in your Azure AD tenant and something you can easily recognize and associate with the API. The latter is important as the client application will use that ID as scope for requesting an Access Token for the Web API to Azure AD. 
  • You can use something like a GUID, but it will be hard to correlate/associate to a Web API by simply looking at the code or script used for getting a new access token. 

You can associate Roles to an App Registration representing a Web API. Those roles are not OAuth scopes because they are not requested or consented to by the users. They are assigned by the owner of the Web API in Azure AD to one or more users or other app registrations. Azure AD can evaluate who is the caller application or user and assign the corresponding roles in the Web API. When that happens, Azure AD injects the roles in the access token (JWT) using the roles attribute.

You can define two types of Roles, Application Roles and User Roles, also known as Delegated Roles.

Application Roles only work for the Client Credentials flow where Authorization is performed in the context of the caller application. The Delegated Roles are used for the rest of OAuth flows and OpenID Connect. For Micro-Services, we are only interested in the former.

Many of the roles that Microsoft defined for the Azure APIs use the following naming convention, <resource>.<action>, which permits you to do <action> on <resource>. For instance, Users.ReadWrite on the Graph API allows any client application to read or update users with that API.

Roles are not global. As we said before, they are defined in the context of a Web API. Users.Write does not mean anything for Azure if it is not passed in the context of the Graph API. Azure AD uses the URI scope to identify the API, and then looks for the requested role in that API only.

  • Go to Azure Active Directory in your Azure Subscription to create a new App Registration for a Web API.
  • Go to the App Registrations option on the left menu for Azure Active Directory and click on "New Registration"

No alt text provided for this image

  • Complete the name of your Web API and click on "Register".

No alt text provided for this image

  • Go to the "Expose an API" option on the left menu for this App Registration. Click on the "Set" link for the Application ID URI. That will set the URI Scope for the API. Configure the following value as URI "api://myapis/mywebapi".

No alt text provided for this image

  • Go to the App roles option on the left menu for this App Registration. 
  • Click on "Create App Role". 
  • Fill out the following details:

Display Name: Admin Role

Allowed member types: Applications

Value: Admin

Description: Allows executing any operation on the web api

  • Click on "Create App Role". 
  • Fill out the following details:

Display Name: Read-Only Role

Allowed member types: Applications

Value: ReadOnly

Description: Allows read-only access on the web api

After following all these steps, you should have a new Web API that supports two roles, Admin and ReadOnly.

Registering a Client Application in Azure AD for your Web API

A client application is the counter part of a Web API. It is another App Registration, but used for requesting an access token for a Web API.

You must provide the following details for a client application.

  • The authentication credentials, which could be a pair of client id and secret, or a client certificate.
  • The roles/permissions required on a Web API. This part if optional. If you don't define any authorization role for a Web API, any client application registered in Azure AD gets an access token for your Web API with an empty list of roles.
  • Go to Azure Active Directory in your Azure Subscription to create a new App Registration for the client application.
  • Go to the App Registrations option on the left menu for Azure Active Directory and click on "New Registration".
  • Complete the name of your client application and click on "Register".
  • Go to API permissions on the left menu for this App Registration. 
  • Click on the "Add a permission" link.

No alt text provided for this image

  • Go to the tab "APIs my organization uses" and look for the Web API previously registered.
  • The roles for the Web API will be listed, those are "Admin" and "ReadOnly". Select the role you want to grant to this client application.

No alt text provided for this image

  • Application Roles assigned to an App Registration are not automatically granted. The administrator for the Azure AD tenant must approve them first. That can be done by clicking on the option "Grant Admin consent". Azure AD won't inject any role into the access token if this step is not completed.
  • Go to "Certificates & Secrets" option on the left menu for this App Registration. 
  • Click on "New client secret". Enter a description to identify the secret and an expiration.

No alt text provided for this image

Take note of the "Value" for the new secret, as you won't be able to retrieve in the future.

"Value" is the new client secret. The client id is the App ID associated with the App Registration. Ignore the Secret ID, which is not really used at all for authentication.

Getting an access token for the Web API

Getting a new fresh access token or JWT from Azure AD with client credentials requires an HTTP POST with the following details,

URL: https://login.microsoftonline.com/{tenant}//oauth2/v2.0/toke
Content-Type:  application/x-www-form-urlencoded
Body: 

client_id={client id}
&scope={web api uri scope}/.default
&client_secret={client secret}
&grant_type=client_credentials
        

Tenant: It's the tenant ID where the App Registration for the Web API and Client were created. 

Client Id: It's the App Id assigned to the App Registration created for the client.

Scope: It's the Web API URI scope assigned to the Web API. Azure AD uses a strange convention for this. When you use client credentials, "/.default" must be appended to the URI scope. No other value is allowed. This scope is used by Azure AD to determine which API the client application wants to consume and generate an access token for it. This will drive the generation of the JWT and how some of its attributes are set. For instance, the audience or AUD attribute will be the set with the App ID for the Web API, and roles attribute with all the roles assigned to the client in that given API. For our example, the complete value would be api://myapis/MyWebAPI/.default 

Client Secret: It's the secret assigned to the App Registration for the client.

An access token for a Web API looks as follow.

{
  "aud": "api://myapis/MyWebAPI",
  "iss": "https://sts.windows.net/f6aba1d9-da41-4ea3-8f30-4970725586b9/",
  "iat": 1672924530,
  "nbf": 1672924530,
  "exp": 1672928430,
  "aio": "E2ZgYHD9N/XE5ot5He2iV1Z1VfAyAAA=",
  "appid": "55b2a7ec-73f3-45c2-af08-21ecc33dc40e",
  "appidacr": "1",
  "idp": "https://sts.windows.net/f6aba1d9-da41-4ea3-8f30-4970725586b9/",
  "oid": "1f3086f6-9164-45f2-b479-a93f64d1006a",
  "rh": "0.AX0A2aGr9kHao06PMElwclWGqGL1t9EZOxJMkZf3CB4gW3ucAAA.",
  "roles": [
    "Admin"
  ],
  "sub": "1f3086f6-9164-45f2-b479-a93f64d1007a",
  "tid": "f6aba1d9-da41-4ea3-8f30-4970725586a8",
  "uti": "G-1ZiIhWbkKJdvkZfawxAA",
  "ver": "1.0"
}        

aud: The audience for the access token. This is used by the Web API to validate that the token was actually issued for it. 

iss: The issuer ID. This is an unique identifier for the Azure AD tenant.

sub: The client ID

roles: The roles assigned to the client on the Web API.

Wrapping Up

At this point, you should have a solid understanding of how OAuth and Azure AD can be used to secure your micro-services architecture using the OAuth client credentials flow, and be equipped with the knowledge to implement it in your own projects.

To view or add a comment, sign in

More articles by Pablo Cibraro

Others also viewed

Explore content categories