How to create Teams Message via REST from an Application properly - azure

I have a c# service, the service is running somewhere in the azure cloud without an user interface. some specific events should trigger new messages to a team channel.
According to this documentation, the Create Message https://learn.microsoft.com/en-us/graph/api/channel-post-messages?view=graph-rest-1.0&tabs=http is only supported by delegated account, not by the application tokens.
How can i create a delegated token for my service application without specific user account and without a login interface in the cloud?
Which Authentication Provider is the right one? https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?context=graph%2Fapi%2F1.0&view=graph-rest-1.0&tabs=CS

As you mentioned in the question : chatMessage , supports only the Delegated Permission type.
What exactly is Delegated Permission Type?
A permission which specify scope-based access using delegated authorization from the signed-in.
The reason on the emphasis of the above point is being that - for Delegated permission we would need the context of a user account
Coming back to your questions :
How can i create a delegated token for my service application without specific user account
You can obtain a token without a specific user account but this will not help your cause.In order to overcome this, I would suggest a creation of service account - this account has permission over the teams.Part 2 of this questions suggests which provider can help without the login prompt.
The steps include :
Register your app.
Configure permissions for Microsoft Graph on your app.
Get administrator consent.
Get an access token.
Use the access token to call Microsoft Graph.
Detailing of the steps is included in the article here : https://learn.microsoft.com/en-us/graph/auth-v2-service
without a login interface in the cloud
Now you could use the below option :
Microsoft identity platform and OAuth 2.0 Resource Owner Password Credentials
In this provider, you will be passing the creds of the service account.
POST {tenant}/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=<YOUR CLIENT ID>
&scope=user.read%20openid%20profile%20offline_access
&username=<YOUR USERNAME>
&password=<YOUR PASSWORD>
&grant_type=password
You can generate the token for your service account by above request and application can consume the chatMessage API.

Related

Azure Function Call Services On Behalf Of User

I want to create an Azure Function that accesses Cosmos DB Containers and Key Vault Scopes. Function calls require Active Directory sign in and users are granted access to resources via Groups.
Azure resources should be accessed or denied based on the signed in user's permissions or group memberships.
How can the Azure Function access other Azure Resources on behalf of the authenticated caller?
It's pretty complex unfortunately, you'd need to have a new OAuth2 access token scoped to cosmosdb resource to be able to access it.
Please check OAuth2 On-Behalf-Of flow:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
When I used it 2 years ago, there was no SDK support for this flow, I simply used http request against https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
In your case, you would also have to add https://cosmos.azure.com/user_impersonation delegated API permission to your app registration and users will be asked for a consent when they try to access your API.

MS Graph Daemon App - Obtaining Bearer Token

I’m creating a daemon app, e.g. a 'non-user interactive' app, authentication will be performed on behalf of end-users using a ‘service account’. So the no sign in prompt required.
The 'service account' has the relevant Delegated Permissions and Admin Approval is consented for the app, the app permissions are set as 'Application Permissions'.
Company policy forbids the Client Credential flow, so no access to the 'client_secret'. If I try using the ROPC flow with the service account username/password the POST request returns the 'Invalid Grant' error.
I’m confused as to what flow I’d use/can use to obtain a bearer token, that will enable the app to call MS Graph API?
The question is similar to this, though I cannot use Client Flow: Can a MS Graph background/daemon app impersonate a user account without user interaction
To impersonate a user (i.e. delegated access, using delegated permissions) and access Microsoft Graph on behalf of the user, the user must have signed in to the application at some point (or to an upstream application).
The alternative is for the service to authenticate as itself (i.e. using the Client Credentials flow) and access Microsoft Graph directly.
The Microsoft Identity platform does not support impersonation of arbitrary users who have not actually signed in to the app.
In general, using the Resource Owner Password Credential (ROPC) flow to impersonate a user account using that account's username and password is strongly discouraged.

The approval framework is not displayed for users in Azure AD B2C. (User Consent)

i am currently implementing a "System-of-Systems" authentication architecture in Azure Active Directory B2C (AAD B2C). In these scenario there is an initial SSO application that redirects the user to a general dashboard. The dashboard should enable the user to use additional services (service applications). (For example a tile view)
To use these additional services, the user must grant explicit permission for each external service. With this delegated permissions, the user authorizes the service to access certain data (for example, IoT data or personal data).
These AAD B2C application is characterized in this scenario by a client and backend application (api) (for each service). The client application contains scopes (delegated permissions) from the backend application, which are stored as a JWT validation - Policy in each Azure API Management endpoint.
Authentication against these assigned backend scopes already works with the Microsoft Login Provider (Identity Provider), but not with the local Identity Provider (for E-Mail).
Here: My Scenario
I changed the access level from Admin to User in the application manifest: (Here)
Microsoft Access Panel (works here)
My Problem the Local Idenitity Access Panel for users (that doesn't works) -> should look like this: Microsoft Docs (consent dialog)
For the following request:
https://[tenant].b2clogin.com/[tenant].onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_SignUpAndSignIn&client_id=xxxxx-xxx-xxxxxx&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid https://[tenant].onmicrosoft.com/backend/Backend.Read&response_type=id_token token&prompt=login
... I always get the following error message:
AADB2C90205: This application does not have sufficient permissions against this web resource to perform the operation.
The approval framework is not displayed for the user, therefore the request is rejected by insufficient permissions.
Do you know how to solve this problem? Are there any walkarounds or configuration options?
Thank u & Best regards
You missed some scopes of your application. Navigate to Applications (Legacy) -> API access, the scope need to add all scopes that you select.
The scopes that you defined are in Published scopes, you could add Full Scope Value in the URL.
This is my URL, and it works well:
https://[tenant].b2clogin.com/[tenant].onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_SignupSignin&client_id=xxxx&nonce=defaultNonce&redirect_uri=https://jwt.ms&scope=openid offline_access https://[tenant].onmicrosoft.com/api/demo.write https://[tenant].onmicrosoft.com/api/demo.read https://[tenant].onmicrosoft.com/api/user_impersonation
&response_type=id_token token&prompt=login
For more details, you could see a tutorial and implicit flow.

Azure Resource Management API without user_impersonation, is it possible?

I am trying to find security best practice on App permissions in the context of azure resource management.
Currently, there is only one permission listed for management.azure.com and it is
management.azure.com/user_impersonation (preview). This delegated user impersonation can be a serious problem and it can led to account takeover by malicious app.
Think about a scenario where a user with global administrator role consent and authorize an access token to the app. App can use the token and do whatever it wants with the azure tenant.
Another scenario where a privileged user assigned contributor role to multiple subscriptions. Token authorized by this user can be misused by app to modify resources in any of the subscriptions.
Unlike graph (graph.microsoft.com) api where you can handpick the permission (user.read), resource management api has only one option - user_impersonation!
You may argue why would a privileged user authorize the action but people make mistakes. Our job is to stop or minimize such risk by design. So, what's the best way to allow app to manage resources in azure and minimize the security risk?
Thanks to #juunas for outline and tips. Thanks to #Gaurav for attempting to address my question. I was able to modify azure resources on a subscription without having to grant user_impersonation on management.azure.com api. Here are the steps-
1) Register an app (TestPermissions in my case)
2) Add API Permissions (optional). You don't need to add management.azure.com.
3) Go the Azure resource (subscription, resource group or management group level based on your requirement) and add IAM/RBAC role to the registered app. I assigned Contributor role to TestPermissions app at the subscription level.
4) Request a oauth2 access token following client credential grant flow. You can provide client_id and client_secret in the body of the POST request or you can provide it as Authorization Basic base64 encoded header (that's what I did). Save the access token for future use (until it expires).
Note: I could not add multiple audience (scope) at the same time. If you would like to get a token for graph api, you can request a separate token by changing the scope to http://graph.microsoft.com/.default
5) Use the access token captured in the previous step to interact with azure resource manager. You will need to add the jwt bearer token in the Authorization header (not shown here) on every request to https://management.azure.com. In this example, I am creating a new resource group named TestCreateRG003 to one of my Pay-as-you-go subscription.
6) Let's validate/verify that the resource is created or updated in Azure. Bingo, there they are! App can read/modify (based on RBAC) azure resources w/o having to grant impersonation permission.
It is true that by granting that permission you are allowing the app to act as you, with all the permissions that brings.
The main way I've seen used when limitations are desired is that you:
Register an app in your Azure AD
Grant the service principal the necessary roles (e.g. Reader on specific resources)
Set the tenant id, client id, client secret etc. in the app
This of course requires that the app itself supports this approach.
If it only allows usage through impersonation, then you'll need to either trust or not use it.
Let me see if I can answer this question.
When a user requests a token for management.azure.com, all is done at that time is that the user has permission to execute Azure ARM API. That doesn't mean that they can do everything that's possible with Azure ARM API.
The things that they can do is controlled by Azure Role Based Access Control (RBAC). So if a user is in the Reader role, the token got on behalf of the user can only read information about resources in their Azure Subscription. They will not be allowed to create, update or delete resources in their Azure Subscription.
What you will need to do is grant users appropriate RBAC role to minimize the risks of misuse.

Credentials prompt for access to Azure management APIs

I've been using the Azure fluent management APIs (https://github.com/Azure/azure-libraries-for-net) with some success in .NET Core.
However, I want to prompt the user to enter some credentials for a Microsoft account. Those credentials would have access to one or more Azure tenants / subscriptions, so I'd like to be able to use the result to browse and manage resources there.
This is something very close to what I would believe Azure Data Studio does: you can enter some Azure creds, and your resources will appear in the app.
I'm trying to understand the best approach for this. There seem to be a billion sites out there when you talk about Azure AD app registrations, but I haven't found a fruitful specific search query yet. I know I can register an app, get a client ID and client secret. I know I can set it to be usable by organisational accounts in the current tenant, or all tenants.
I can add the "Azure Service Management (delegated permissions : user_impersonation)" permission to my API permissions section for the app, but what's next?
If I use Microsoft.Identity.Client (as in https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon), I run into some questions:
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync! Nope, AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
I don't know what scope I want. https://management.azure.com/user_impersonation is apparently invalid.. https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs.. and my account (for instance) is associated with 3 tenants or 5 different tenants / directories - so how do I choose?
That's just what I've tried, the appropriate route might be a different one. In summary: I want a .NET Core Console app to request user credentials, and then get access to the Azure resources they have access to, in order to perform some resource management.
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
You are using the OAuth 2.0 client credentials grant to access web-hosted resources by using the identity of an application. This type of grant commonly is used for server-to-server interactions that must run in the background, without immediate interaction with a user .
AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
Azure AD provide two service : Azure AD V1.0 and Azure AD V2.0 . Please refer to Comparing the Azure AD v2.0 endpoint with the v1.0 endpoint . You can't use v1 token to acquire v2's token in a on-behalf-of flow .
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync
AS pointed above , That function is used to acquire an access token for this application (usually a Web API) from the authority configured in the application, in order to access another downstream protected Web API on behalf of a user using the OAuth 2.0 On-Behalf-Of flow. So you can't use app token which acquire using Client Credential flow .
https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
You are using the Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow , when sending a POST request to the /token v2.0 endpoint ,the scope should be :
The value passed for the scope parameter in this request should be the resource identifier (Application ID URI) of the resource you want, affixed with the .default suffix. For the Microsoft Graph example, the value is https://graph.microsoft.com/.default. This value informs the v2.0 endpoint that of all the direct application permissions you have configured for your app, it should issue a token for the ones associated with the resource you want to use.
Please check the Get a tokensection in above document .
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs..
AFAIK , currently Azure AD V2.0 apps can use:
Its own API
Microsoft Outlook APIs
Microsoft Graph API
Azure AD V2.0 currently doesn't support Azure management APIs .
So you problem is you need to allows work and school accounts from Azure AD and personal Microsoft accounts (MSA) which works with Azure AD V2.0 , but you can't use Azure management APIs . You can use Azure management APIs in Azure AD V1.0 but it allows only work and school accounts to sign in to your application , unless you invite Microsoft accounts as guest user in Azure AD V1.0 ,but you need to configure to point to the tenant-specific endpoint :https://login.microsoftonline.com/{TenantId_or_Name}). during authentication if you want to login with MSA in v1.0 apps.
Update:
You can use Code flow and azure ad v1.0 endpoint , user will be redirect to AAD's login page and enter their credential. Here is code sample for .net Core .
With Azure AD V1.0 endpoint , requests are sent to an endpoint that multiplexes across all Azure AD tenants: https://login.microsoftonline.com/common . When Azure AD receives a request on the /common endpoint, it signs the user in and, as a consequence, discovers which tenant the user is from. See document here . But in this scenerio ,you can only use work and school accounts(AAD) account to login .
The code sample in your link is using Azure Service Principal for Authentication , no interactive user login . You can use OpenID Connect Owin Middleware for authentication in .net Core applications as shown here .

Resources