We are having an Azure AD Protect API which is hosted on prem. We have a requirement to call this API from Logic App. We have currently created or registered a new client App in App Registration for this logic App and have provided the necessary permissions and have called API passing the Bearer Token.
My question, is there a way we can leverage Managed Identity for Logic App (either User Assigned or System Assigned) for calling the API?
Yes there is.
I wrote an article on the topic (though it is not specific to Logic Apps): https://joonasw.net/view/calling-your-apis-with-aad-msi-using-app-permissions.
You will need to create an appRoleAssignment that gives an application permission to your managed identity service principal.
To do this, we must use PowerShell or Microsoft Graph API.
With Azure AD PowerShell, we can do this:
Connect-AzureAD
New-AzureADServiceAppRoleAssignment -ObjectId $miSpId -Id $appRoleId -PrincipalId $miSpId -ResourceId $targetApiSpId
There we have 3 arguments you need to find:
miSpId: The objectId of the Managed Identity (easy, we can find this from the Identity blade in the Logic App)
appRoleId: The id of the appRole defined on your API's manifest (this should be easy to find as well, it's in your API's manifest)
If you haven't defined an appRole (app permission) on your API, you will need to do that first (https://joonasw.net/view/defining-permissions-and-roles-in-aad)
targetApiSpId: The objectId of the target API service principal (this one you can get by going to Enterprise Applications and finding your API there)
Related
I've done some reading in regards to Azure AD, but I still can't wrap my head around it. The confusion might be there also because of how my company tries to standarize how a azure project should look like.
Imagine I have two things: SPA app (served by App Service) and API (on this App Service, ASP.NET). The approach that the company is suggesting is that both of those should have their App Registrations.
Now, I'd like the API to have access to Ms Graph. In order to do that, looking at other projects, I updated my AppRegistration to request for Ms Graph roles, Admin gave consent, and in API I used ConfidentialClient to reuse my Client Id/Secret to get token and then access MsGraph.
Why the hustle? Why not just use Managed Identity of my API and grant needed permissions using New-AzureAdServiceAppRoleAssignment?
Why do I need App Registration here? Do I need both? Should I access Ms Graph using my App Registration and confidential client in my API? How does my App Service relate to my App Registration in code?
Let's take a step back and define a few things that will make things easy to understand:
Your app service: this is just a compute environment, just as Azure Functions, Logic apps or VMs. This is where your code executes.
Azure AD App registration: this is an identity that you can use in your code to identify your service and get access to resources you need. The Azure AD app registration has several capabilities:
build an app in one tenant and used in multiple tenants (multi-tenant app)
consent framework, allowing you to request permissions and the owner to grant it
define roles and permissions, so that you can configure who is allowed to call your API
3-legged OAuth flows which allows you to act on behalf of the user
confidential client flows which allow the app to act on its own (like a service account)
Azure Managed Identities: this is also an identity that you can use to identify your service and get access to resources you need. It only has a subset of the capabilities of Azure AD app.
confidential client flow which allows the identity to act on its own (like a service account)
credentials managed for you by the platform
Depending on what you are trying to do, you can use one or the other identity: rarely if ever you will need both.
In your case, you need an identity to act on its own. So either app registration or managed identity will work. Your API may benefit from using an app registration if you want to define roles and permissions. The primary advantage of using an app registration in your scenario is that the consent model is simpler to use and understand. The disadvantage is that you need to manage credentials for the app. This pro/con is reversed when using a managed identity.
You don’t need both at a time. These are two ways to get the access of MS graph for your API. They are used for different purpose.
Managed Identity (Using System Identity)
· Use the Managed Identity if you don’t require your API to be authenticate from any provider.
· A managed identity from Azure Active Directory allows App Service to access resources through role-based access control (RBAC), without requiring app credentials
· It known as safe way to give your web app access to data is to use a system-assigned managed identity
· Currently, there's no option to assign any permissions(MS graph) through the Azure portal for Managed Identity
· When we do Manged Identity of any application its show only for Enterprise application.
Reference : Tutorial - Web app accesses Microsoft Graph as the app - Azure App Service | Microsoft Docs
App Registration.
· To set the authentication and authorization of your app from different provider its need your app registration id.
· It’s required to configure a service and get a token from the Microsoft identity platform endpoint that service can use to call Microsoft Graph under its own identity.
·In this using portal you can add permission (MS Graph) for your application.
Reference : https://learn.microsoft.com/en-us/graph/auth-v2-service
Right now I'm using AAD app to make Service A => Service B calls. This includes:
AAD app
KeyVault which keeps a secret/certificate for AAD app
Managed Identity with access to KeyVault
The flow looks like this:
Service A: Get token from Managed Identity
Service A: Go to KeyVault, present a token and get a secret for AAD app
Service A: Go to AAD, present a secret and request a token for a particular resource
Service A: Make a call to Service B
Service B: Validate a token and a resource
I wonder whether it is possible to register a managed identity with my service, so if a Managed Identity token is presented then Service B can trust Service A. Something like this:
Service A: Get token from Managed Identity
Service A: Make a call to Service B
Service B: Validate that token comes from registered Managed Identity
Is it feasible? Does it violate any security best practices?
Update: beside below answer, the following stack overflow post describes how to make Managed Identity in one tenant to get a role claim for an app in another tenant
Grant service principal access to application in other tenant
I've written a blog article on this topic: https://joonasw.net/view/calling-your-apis-with-aad-msi-using-app-permissions.
You can definitely do it,
it'll mean you don't need to use any secrets to call Service B from Service A :)
You'll need to assign application permissions to the managed identity service principal using PowerShell / Graph API though.
There is no UI for this.
Example PowerShell command:
New-AzureADServiceAppRoleAssignment -ObjectId 1606ffaf-7293-4c5b-b971-41ae9122bcfb -Id 32028ccd-3212-4f39-3212-beabd6787d81 -PrincipalId 1606ffaf-7293-4c5b-b971-41ae9122bcfb -ResourceId c3ccaf5a-47d6-4f11-9925-45ec0d833dec
The ObjectId and PrincipalId are both the MSI-generated service principal's id. Id is the id of the role. ResourceId is the id for the API service principal.
This is using the AzureAD PowerShell module.
After the permission is assigned, your Managed Identity should be able to get you a token for Service B.
Your local development environment will need a different approach though, since there is no Managed Identity there.
You might for example use a client secret in there to test calls to Service B.
Sorry, I can't comment to juunas's reply as I don't have enough reputation to comment. Just wanted to say that the solution recommended by juunas worked for me only after I rebooted the VM from where I was trying to acquire the token using user-assigned managed identity. The idea to reboot the VM came from below article. This article also recommends exact same solution as juunas' but also mentions about rebooting VM to clear cache in case token still doesn't show roles after following the recommended steps. https://www.jasonfritts.me/2019/07/15/assigning-azure-ad-graph-api-permissions-to-a-managed-service-identity-msi/
I'm trying to call an Azure function from an API Management instance by using Managed Identity.
I have set a System Managed Identity to my APIM instance.
I have granted the Contributor role to this identity on the Azure Function App.
I have also change the App Service Authentication to AD.
Now I'm trying to call the function from an API.
I have two issues:
First One: when I use the authentication-managed-identity policy to get a token, I got an error when I use the audience https://myfunctionapp.azurewebsites.net. AD tells me that this app is not registered in the tenant
Second: If I retrieve a token for https://management.azure.com, I got a token but I received a 401 Unauthorized error from the Azure Function.
Maybe I'm just trying to get a token on the wrong audience, but unfortunately the audience of functions is not listed in the document (for service bus for example, there is a common URI to use, also for KeyVault, ...).
I think that I probably missed something in the picture...
Thanks.
You need to use the authentication-managed-identity policy to authenticate with a backend service using the managed identity of the API Management service.
https://learn.microsoft.com/en-us/azure/api-management/api-management-authentication-policies#ManagedIdentity
EDIT
1-In your APIM application on Azure AD,
grab the Application ID assigned for enterprise application.
2-Then go to Platform features in your Azure Function App, and click on Authentication / Authorization.
3-Select Azure Active Directory as the authentication provider, and the management mode "express".
4-Back to authentication-managed-identity policy, set the Application ID from step 1 as the resource.
you need to add the url in apim required resource. If you're planning to use delegated flow. To check if the issue is with the url registration you can use the AppId instead. This will at least tell you if the token can be retrieved.
All of the examples on the microsoft azure site having to do with a client application or a service principal having access to azure apis all show the graph apis as the example.
I got those to work, but what I need to do is access the azure service management apis.
If I take an auth token that works for the graph api and use it for the service management api, I get an "Authentication failed." error.
I have added the api permission for "azure service management" and the user_impersonation delegated permission type to my public client app, but the management apis still fail.
Am I going about this all wrong?
I get the idea that the service management apis are authenticated a different way since there's absolutely no mention of using them anywhere in any of the auth examples.
I suppose you are using the client application or a service principal to access azure resources. If so, you are using the client credential flow, but the user_impersonation of Azure Service Management API is a delegated permission, it will not take effect in this flow.
The permission is used to be consent by the user who login to the AD App e.g. in the auth code flow, when it has been consent by the user, the App will be able to represent the user to access the azure resources, note the permission is from the user, not the app. So if you want to use this flow, the user should have a role in the subscription or specific resources.
To access the azure resources with the client application or a service principal, you just need to add the service principal as an RBAC role in the Access control (IAM) of your subscription or specific resource, no need to add any API permission in Azure AD, see this link. Then the service principal will be able to access the azure resources.
When you getting the token to access the azure resources, e.g. call the REST APIs, the scope should be https://management.azure.com/.default, not the https://graph.microsoft.com/.default, you can just get the token for one resource in one time.
To run applications in Azure, I need to create an Application in Azure AD and a corresponding Service Principal. Then my application authenticates against this App/Principal pair. To authenticate, I can create an application key in the App registration, or I can create a password in the Service Principal (among other options). What's the difference from a practial standpoint?
For example, this code runs exactly the same (from the outside) whether the $key is the App's key or the Service Principal's password:
$key = ConvertTo-SecureString $authKeyOrPassword -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($appID, $key)
Add-AzureRmAccount -Credential $cred -TenantId $tenantID -ServicePrincipal
When should I authenticate against the App, and when should I use the Service Principal?
First, let me explain why it has both Applications and service principals in Azure AD. Here is the explanation from Mordent Authentication with Azure AD for Web App by Vittorio Bertocci.
Azure AD defines a new entity, the Application, which is meant to
describe an application as an abstract entity: a template, if you
will. As a developer, you work with Applications. At deployment time a
given Application object can be used as a blueprint to create a
ServicePrincipal representing a concrete instance of an application in
a directory. It’s that ServicePrincipal that is used to define what
the app can actually do in that specific target directory, who can use
it, what resources it has access to, and so on.
Bear with me just a
little longer, the abstract part is almost over. The main way through
which Azure AD creates a ServicePrincipal from an Application is
consent. Here’s a simplified description of the flow: Say that you
create an Application object in directory A, supplying all the
protocol coordinates we’ve discussed so far in earlier chapters. Say
that a user from tenant B navigates to the app’s pages and triggers
an authentication flow. Azure AD authenticates the user from B against
its home directory, B. In so doing, it sees that there is no
ServicePrincipal for the app in B; hence, it prompts the user about
whether he or she wants to consent for that app to have access to the
directory B (you’ll see later in what capacity). If the user grants
consent, Azure AD uses the Application object in A as a blueprint for
creating a ServicePrincipal in B. Along with that, B records that the current user consented to the use of this application (expect lots of details on this later on). Once that’s done, the user receives a token for accessing the app.
If you want to know the difference between Azure AD App key and service principle Password, you'd better know the relationship of Application and service principal. I will copy&paste here some extracts from this page of the documentation
When you register an Azure AD application in the Azure portal, two objects are created in your Azure AD tenant: an application object, and a service principal object.
Consider the application object as the global representation of your application for use across all tenants, and the service principal as the local representation for use in a specific tenant. The application object serves as the template from which common and default properties are derived for use in creating corresponding service principal objects.
An application object therefore has a 1:1 relationship with the software application, and a 1:many relationships with its corresponding service principal object(s).A service principal must be created in each tenant where the application is used, enabling it to establish an identity for sign-in and/or access to resources being secured by the tenant.
Example diagram
Summary
Now, we can know the difference between Azure AD App key and service principle password. They belong to different objects. The password to be associated with the service principal. This is just for the application tenant to login azure. However, you can provide the App key value with the application ID to log in as the application with all tenants.
To see more details about Application and service principal objects in Azure Active Directory , you can refer to this document.