Interacting with Azure Service from Azure Function from Client app on behalf of the user (user impersonation) - authentication

Context
I have a client app, represented through an Azure Active Directory app that needs to send a HTTP request to a HTTP trigger Azure Function on behalf of the user that is logged in to the client app. To achieve that I followed https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad. Doing so I am successfully able to execute the function on behalf of the user.
Goal
From this triggered Azure Function on behalf of the user I want now to achieve that I can interact with another Azure Service (let's say an Azure Storage Account) on behalf of the user. The user can do on this Storage Account what is allowed by the roles the user has on the Storage Account.
Problem
I don't get it working. I tried the approaches described in How to impersonate logged in user to manage other Azure service and https://blog.brooksjc.com/2020/06/21/accessing-graph-api-with-an-azure-function-through-impersonation/ And in this context I also don't get it working for Azure Data Factory respective Graph as described in the posts. For instance, when I call .auth/me I just get an empty array.
Question
Given this context how can I achieve my goal of interacting with the Storage Account on behalf of the user via the Azure Function that has been triggered on behalf of the user?
Thanks
EDIT
I am aware of the OAuth 2.0 On-Behalf-Of flow (see https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) and this one works (i.e., I am able to authenticate the user, retrieve another token and use this one to interact with the Storage Account on the users behalf). What I would like to achieve is similar to the posts shared above that the user authenticates against the app and by doing so already a token is made available for the interaction with the Storage Account, so that I don't have to make the additional request to https://login.microsoftonline.com/{{tenant_id}}/oauth2/v2.0/token to get that token using e.g. client credentials. And this is not about specific code (e.g. C#) but about the general set up. Is this possible?

Related

MSGraph Delegated permissions given from an administrator

We have a problem consenting permissions and obtaining access tokens to call MSGraph API. Our product is like follows:
We have an API that works with MSGraph. Until now, we have been using Aplication permissions to access resources as mail and calendar.
We would like to start using Task To-Do API and it only supports Delegated permissions.
Our API works with multiple tenant and multiple users in each tenant.
We use admin consent to give all necesary permissions and generate a token aftewards to make requests to MSGraph (Aplication permissions endpoints). With these new changes, is there a way to generate a token valid for To-Do API directly from an administrator, or is mandatory that each user signs in to create a personal auth token valid for this API? We would like to avoid the proccess of user sign in as our API is meant to work behind another application we do not develop after administrator has given consent.
Thank you in advance
In your case, you are using client credentials flow and with that you can not have signed in user or delegated permissions as MS Graph Todo APIs only support delegated permissions.
For you to use the To-Do Graph APIs, you have to can incorporate user signin. If this not possible in your scenario, then you can upvote this feature request - Allow Graph API calls to work with both todo tasks and plannerTasks using application permissions

What is the difference between the two use cases of using OpenID Connect in Keycloak? (Client vs Application)

I am very new to the concepts of SSO and Keycloak. I am trying to read the official documentation of Keycloak. In the "Supported Protocols" part (https://www.keycloak.org/docs/latest/securing_apps/index.html), the documentation talks about the two use cases of using OIDC like this:
"The first is an application that asks the Keycloak server to authenticate a user for them. After a successful login, the application will receive an identity token and an access token. The identity token contains information about the user such as username, email, and other profile information. The access token is digitally signed by the realm and contains access information (like user role mappings) that the application can use to determine what resources the user is allowed to access on the application.
The second type of use cases is that of a client that wants to gain access to remote services. In this case, the client asks Keycloak to obtain an access token it can use to invoke on other remote services on behalf of the user. Keycloak authenticates the user then asks the user for consent to grant access to the client requesting it. The client then receives the access token. This access token is digitally signed by the realm. The client can make REST invocations on remote services using this access token. The REST service extracts the access token, verifies the signature of the token, then decides based on access information within the token whether or not to process the request."
What I do not understand is this: In the first paragraph it talks about an application making a request and in the second one it talks about a client. But aren't applications counted as clients? Why the specific differentiation? And can anyone given an example of the remote services that is talked about in the second part?
Thank you.
But aren't applications counted as clients? Why the specific differentiation? And can anyone given an example of the remote services that is talked about in the second part?
Yes exactly it. The reason for the differentiation is because there could be many applications more than just this one client. And the client, that the user is authed against may want to access all those other applications' data.
For example take the google ecosystem. Does google email have access to drive, and photos, etc... While it could out the box, it doesn't. You need to explicitly allow email "offline access" to those other applications, even though they are all part of the same platform.
Keycloak understands this and provides that terminology. But it is a bit confusing because this isn't the best way to think about it. Instead a better explanation is that there is just the user and service clients. The service clients all talk to each other and ask for a user's data. While a user may want their data by going straight to one application, other applications may want that user's data too.
Assuming you want to actually allow one service to ask for user data from another service, you want to be using something that supports authorization as a service and not just authentication. There are some examples of this, such as PolicyServer and Authress.

How would an API call another API with oauth2 if both APIs use different identity providers?

In the past, I have had 2 APIs, both secured with Azure AD. The first API would take the access token and request another access token for the second API with the following param: requested_token_use=on_behalf_of
Info source: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
However, this is due to both APIs being on Azure AD. Controlled in the same directory.
If the first API was Azure AD and the second was auth0, how would the second API get an access token without the user being able to login to a authorization screen?
In that case you can use Password Grant Flow or Client Credentials Flow.
You can read more about service to service authentication on Microsoft or Google pages.
Does this give you everything you had with on behalf flow? No. With on behalf flow you had token with user's claims for both systems. This way you access service B with service A credentials and if you have fine-grained per user permissions you need to implement logic in service A.

Authorization for API Gateway to service already storing user credentials

I have a web service that users can sign into and so forth. I'd like to setup AWS API Gateway to allow the users to interact with the service via APIs. As the user management / password management is already in the system I don't want the user to have to go to another system.
I first looked at Cognito user pools but I couldn't automate fully the user creation / verification process, AWS in a support ticket said the user would have to verify the email separately. They then suggested to use a Lambda function to setup authorisation.
I've created a Lambda function and the API Gateway is authorizing however it looks like only one variable is sent for authorization, the Identity token. If I did this my Lambda function could find from my service that the key is valid but it's not really associated for a user.
What I'm after is a way to provide a user with a client id and passkey from my system (I can generate all of that), the user then does a request to the API Gateway end point with the client id and passkey, gateway sends the client id and passkey to the lambda function that calls my system for verification, Lambda returns the valid policy, API Gateway then sends the request to my service with either the client ID or some other identifier thats come back from the policy so my system knows the requesting client.
What would be the best way to achieve this without taking the user to a seperate system (Cognito)?
Turns out that your timing might have just been a Day or so early. What you would have experienced with custom authorizers before is the TOKEN authorizer. Today they noticed expanded support for custom authorizers with a new REQUEST authorizer type. The new REQUEST type supports a much expanded dataset for authorizing requests, such as request parameters, headers, query strings, and more. Check out the Custom authorizer types for further information.

Adding Applications programmatically in Azure AD using Client Credentials Flow

For use with the Azure API Management, I am trying to add Applications to an Azure Active Directory (AAD) programmatically, in my case by using the Graph API.
My scenario is the following: In order to secure a Web API I want to manage with Azure API Management, I want to leverage AAD's OAuth functionality to do the heavy lifting regarding authentication and issuing JWT Tokens, and then just use the validate-jwt policy to verify everything is okay in Azure API Management. This has the advantage I can more or less omit authentication in my backend service.
This works fine, as long as I have created an application in the Azure AD for the consuming web application, but this has to be done manually from the Azure Portal; Azure APIm does not do it automatically.
Now for what I am trying to do to get the done automatically: I wanted to delegate the subscription to APIs in APIm to some other web app I am writing, and from there I want to leverage the Graph API to create an Application in the Azure AD and grant permissions to the Application of the API.
The first thing I tried to do was to have a third application (my service application) to have full application permissions to the Windows Azure Active Directory application in the Azure AD; this lets my application access AAD using the Graph REST API. I manage to get an Access Token using the client_credentials grant (from login.microsoft.com), but this Token does not let me do a POST on https://graph.windows.net/(my AAD ID)/applications?api-version=1.5:
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
}
}
}
I found (https://msdn.microsoft.com/Library/Azure/Ad/Graph/howto/azure-ad-graph-api-permission-scopes) that even if I grant the Directory.ReadWrite.All permission, the application (app-only) will not be able to create or update Applications:
Note: Specifically excludes create or update for entities not listed above.
This includes: Application, Oauth2PermissionGrant, AppRoleAssignment, Device,
ServicePrincipal, TenantDetail, domains, etc.
The next thing I tried was the Resource Owner Password Grant (grant_type=password), passing my own credentials additionally, so that I can impersonate myself in the Graph API. Now, my POST to the applications end point succeeds.
My bottom-of-the-line question is: Can I grant sufficient permissions to my application so that I can add applications programmatically using the client credentials flow, and not any flow which acts on behalf of a user? And if so, how is it done?
Sorry Don. We don't currently have any permission scopes for the client credential flow (app-only) that can be used to create applications or service principals or create any oauth2 permission grants (or any of the other entities that you mentioned above through the Directory.ReadWrite.All permission). We are working on additional app-only permissions that will enable you to light up this scenario, but I don't have an ETA that I can give you.
This operation should be possible if you use the app+user (code flow) and grant the app the Directory.AccessAsUser.All permission - as long as there is a user using your app AND that they are a tenant admin. Not sure if this is an acceptable workaround for you (and I guess is similar to what you are using with the password flow - although I would recommend you use the code flow here).
UPDATE: There are a couple of new app only permissions we added for AAD Graph. Application.ReadWrite.OwnedBy (which allows an app to create/own another app - but only update the apps it created - it won't be able to touch any other apps it doesn't own) AND Application.ReadWrite.All (which allows an app to create/manage ALL apps in a tenant). Seems like the first one would be appropriate. You can see these show in the Azure Portal for the AAD Graph resource.