English 中文(简体)
Azure Active Directory - How to restrict Backend API App Registration to a specific client App Registration
原标题:

I could be completely off basis here on how this works, but this is what I m looking to achieve.

In AAD I have

  • an App Registration called backend-api that represents an HTTP API
  • an App Registration called frontend-app that represents some client (lets say a console app)
  • an App Registration called another-app that represents nothing related to my solution

I have a console application where I put my client ID and client secret in for frontend-app and I can request an access_token with the aud of backend-api. This is great, exactly what I want. However, I can litterally do the same thing from another-app if I have the client ID and client secret for that app. What I would like to accomplish is that only frontend-app is allowed to get an access_token for backend-api.

I m not quite sure how to go about configuring that specific requirement. I thought maybe I needed to add an appRoles entry for allowedMemberTypes Application on backend-api and then grant frontend-app that role but that didn t apply any restriction to another-app. Likewise I thought maybe backend-api needed to have its "Require User Signin" option checked under Enterprise Applications, but I couldn t find a way to add frontend-app as a "user" -- probably the wrong direction anyhow.

What s the way to tell AAD to only hand out access_tokens for backend-api (aud claim) if they are being requested via frontend-app only? Maybe that s a silly question, and it just doesn t work this way?

最佳回答

You are on the right path with your thinking about adding appRoles entry to backend-api and then assigning the role specifically to frontend-app.

Additionally, understand that enforcing this requirement that only applications coming in with this new role claim are allowed but others aren t is a responsibility of your API code.

I ll get to 2 specific approaches next. Both the approaches are explained on Microsoft Docs here - Microsoft identity platform and the OAuth 2.0 client credentials flow

Approach 1 - Use Application Permissions or Roles

Configure your API application to expose a set of application permissions (or roles).

This approach is a little more declarative, as you define an application permission that needs to be assigned to any application that can call your backend-api.

Navigate to Azure Active Directory > App Registrations > App registration for your backend-api app > Manifest

Add a new application role.. using json like this:

"appRoles": [
{
  "allowedMemberTypes": [
    "Application"
  ],
  "displayName": "Can invoke my API",
  "id": "fc803414-3c61-4ebc-a5e5-cd1675c14bbb",
  "isEnabled": true,
  "description": "Apps that have this role have the ability to invoke my backend API",
  "value": "MyAPIValidClient"
}]

Assign the app permission to your frontend app

New-AzureADServiceAppRoleAssignment -ObjectId <frontendapp.ObjectId> -PrincipalId <frontendapp.ObjectId> -Id "fc803414-3c61-4ebc-a5e5-cd1675c14bbb" -ResourceId <yourbackendapi.ObjectId>

Authenticate your frontend app to backend api using client credentials grant, i.e. using clientId and client secret.. as you re probably already doing.

Now, in the auth token received by your backend api, you can check that the role claims collection must contain a role named "MyAPIValidClient" otherwise you can reject the call with Unauthorized exception.

Approach 2 - Use Access Control Lists

When your backend API receives a token, it can decode the token and extract the client s application ID from the appid and iss claims. Then it compares the application against an access control list (ACL) that it maintains.

Depending on your requirement, API might grant only a subset of full permissions or all permissions to a specific client.

This 2nd approach may seem like a simpler one for some cases, although I like the first one better as it scales well when you have multiple application permissions/roles and different level of functionality to provide based on those roles.

Related SO Post and References

问题回答

It s possible to create scope(s) on the backend-api with consent set to "Admins only".

any app (e.g. another-app) which requests access to the scope should be blocked unless the permission is added and the admin grants permission.

Admin can revoke the permission at any time to prevent access to the backend-api scope.

To restrict the issuance of access tokens for the backend API (backend-api) to only the frontend-app and prevent other applications like another-app from requesting access tokens, you can utilize the concept of application permissions and role assignments in Azure Active Directory (AAD).

Here s an approach you can follow:

  1. In the Azure portal, go to the AAD section.
  2. Open the backend-api App Registration and navigate to the "API permissions" tab.
  3. Remove any existing application permissions that are not required for your scenario.
  4. Click on the "Add a permission" button and select the "Microsoft APIs" tab.
  5. Search for and select the API that represents your frontend application (frontend-app) and choose the necessary permissions.
  6. Once you have added the necessary permissions, click on the "Grant admin consent" button to ensure the permissions are granted.

At this point, you have established a permission relationship between backend-api and frontend-app. Now, you need to configure your backend API to validate the audience (aud) claim to ensure that it only accepts access tokens issued for itself.

The exact implementation depends on the technology stack you re using for your backend API. Generally, you would need to perform the following steps:

  1. When validating the access token received by the backend API, ensure that the aud claim matches the client ID of the backend-api application.
  2. Additionally, you can check the appid (or appidacr) claim to ensure it matches the client ID of the frontend-app application. This step ensures that the access token is issued for the specific frontend application you want to allow.

By performing these checks, you can ensure that only the frontend-app can obtain access tokens for the backend-api, and requests from other applications, like another-app, will fail the validation process.

Remember to configure the backend API s code to perform these validations according to your development language and framework.

It s worth noting that this approach assumes that the client secrets and other sensitive information are properly secured within the respective applications and not accessible by unauthorized parties.

First, make sure you have the msal library installed. You can install it using pip:

pip install msal

Here s an example Python code that demonstrates the authentication and authorization process:

import msal
import requests

# Define the Azure AD app and API details
tenant_id =  YOUR_TENANT_ID 
client_id =  YOUR_FRONTEND_APP_CLIENT_ID 
client_secret =  YOUR_FRONTEND_APP_CLIENT_SECRET 
api_resource =  YOUR_BACKEND_API_APP_ID_URI 

# Define the scope required to access the backend API
scope = [f {api_resource}/.default ]

# Create a PublicClientApplication object with frontend app credentials
app = msal.PublicClientApplication(client_id=client_id, 
authority=f https://login.microsoftonline.com/{tenant_id} )

# Acquire a token using client credentials flow
result = app.acquire_token_silent(scope, account=None)
if not result:
result = app.acquire_token_for_client(scopes=scope)

# Check if the token was successfully acquired
if "access_token" in result:
   access_token = result[ access_token ]
# Make a request to the backend API using the acquired token
headers = {
     Authorization :  Bearer   + access_token,
     Content-Type :  application/json 
}
response = requests.get( YOUR_BACKEND_API_ENDPOINT , headers=headers)
if response.status_code == 200:
    # Success, the backend API was accessed successfully
    print("Backend API response:", response.json())
else:
    # Failed to access the backend API
    print("Failed to access the Backend API:", response.text)
else:
    # Failed to acquire an access token
    print("Failed to acquire an access token:", 
result.get("error_description"))




相关问题
Microsoft partner API: can t authenticate

I ve created an app in Azure AD and followed this steps (Application and user access): https://github.com/MicrosoftDocs/partner-rest/blob/docs/partner-rest/develop/api-authentication.md From what I ...

Oath+Twitter IPhoneSDK

Does anyone know of a good example utilizing the twitter API and Oauth authentication for sending Twits iPhone SDK ........... I got stuck @ sending the twits .........I can make a successful login ...

Can t get user info from Facebook with OAuth 2.0

As soon as the user is logged in, I retrieve the user info using this code: [_facebook requestWithGraphPath:@"me" andDelegate:self]; It worked for the first few times, but it eventually returned an ...

热门标签