I'm working to send a message to Teams by using Graph API.
my application is a daemon application that sends a message automatically in the background.
I have written code like an official reference link below:
https://learn.microsoft.com/en-gb/graph/sdks/choose-authentication-providers?tabs=CS#client-credentials-provider
in my case, I use the client-credentials-provider but, I still can't send a message, and always get the below error message.
surely I have already registered my application in Azure and set for the grant of scope
How can I fix this?
Following this api document, you need to give Application api permission Teamwork.Migrate.All, and try this code below:
using Azure.Identity;
using Microsoft.Graph;
public void sendMesgAsync()
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var chatMessage = new ChatMessage
{
Body = new ItemBody
{
Content = "Hello World"
}
};
await graphClient.Teams["{team-id}"].Channels["{channel-id}"].Messages
.Request()
.AddAsync(chatMessage);
}
Related
I tried to use MS Graph API to implement a backend API to access other users email setting (for getting out-of-office message). As it is backend API, client credential flow is used. I already granted the permissions "MailboxSettings.Read" and "MailboxSettings.ReadWrite" with application type.
I used my free Azure account for testing. Assume my login account is test#hotmail.com, then my Azure domain is testhotmail.onmicrosoft.com.
I created one more user client#testhotmail.onmicrosoft.com
I can get the result using Graph Explorer as below
https://graph.microsoft.com/v1.0/users/test#hotmail.com
https://graph.microsoft.com/v1.0/users/test#hotmail.com/mailboxSettings
https://graph.microsoft.com/v1.0/users/client#testhotmail.onmicrosoft.com
But it return error for below using Graph Explorer
{
"error": {
"code": "ErrorInvalidUser",
"message": "The requested user 'client#testhotmail.onmicrosoft.com' is invalid."
} }
https://graph.microsoft.com/v1.0/users/client#testhotmail.onmicrosoft.com/mailboxSettings
3a. If call by MS Graph SDK to get the user info for client#testhotmail.onmicrosoft.com as below, it is success
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var user = await graphClient.Users["client#testhotmail.onmicrosoft.com"].Request().GetAsync();
3b. If call by MS Graph SDK to get the user info for test#hotmail.com, it returns error
Microsoft.Graph.ServiceException: 'Code: Request_ResourceNotFound
Message: Resource 'test#hotmail.com' does not exist or one of its
queried reference-property objects are not present.
var user = await graphClient.Users["test#hotmail.com"].Request().GetAsync();
If call by MS Graph SDK to get the mailbox setting as below, it returned error
Microsoft.Graph.ServiceException: 'Code: ErrorInvalidUser Message: The
requested user 'test#hotmail.com' is invalid.
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var mail = await graphClient.Users["test#hotmail.com"].Request().Select("MailboxSettings").GetAsync();
Or returned error for below
Microsoft.Graph.ServiceException: 'Code: ResourceNotFound Message:
Resource could not be discovered.
var mail = await graphClient.Users["client#testhotmail.onmicrosoft.com"].Request().Select("MailboxSettings").GetAsync();
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "aad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var user = await graphClient.Users["xx#xx.onmicrosoft.com"]
.Request()
.Select("MailboxSettings")
.GetAsync();
var automaticRepliesSetting = user.MailboxSettings.AutomaticRepliesSetting;
Could you pls try this? By the way you may also try to add the 2 application permissions which mentioned in the document: MailboxSettings.Read, MailboxSettings.ReadWrite. And the most important is, your error message is invalid user, so I'm afraid you can use user_PrincipalName instead of myuser#hotmail.com. You can try to get the user_id in Azure AD potal or from the result for await graphClient.Users["myuser#hotmail.com"].Request().GetAsync();.
You are using hotmail.com , as per the doc you should also have either a personal Microsoft account with a mailbox on Outlook.com, or a Microsoft work or school account.
Hope this helps
Thanks
I am using the C# package to Microsoft Graph API. I can read messages from the Graph API. Now I'd like to translate the message IDs like shown here:
https://learn.microsoft.com/de-de/graph/api/user-translateexchangeids?view=graph-rest-1.0&tabs=csharp
var translatedIds = client.Users[firstMailboxElement.SourcePostbox]
.TranslateExchangeIds(toBeTranslated, ExchangeIdFormat.RestImmutableEntryId, ExchangeIdFormat.RestId)
.Request()
.PostAsync()
.Result;
When I do so I get the following Exception:
System.AggregateException
One or more errors occurred.
(Code: Request_BadRequest Message: Specified HTTP method is not allowed for the request target.
Inner error: AdditionalData: date: 2021-12-15T06:52:45 [...])
Which does not seem to make sense, since I cant change the HTTP Method.
Any ideas how to fix this?
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret";
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var inputIds = new List<String>()
{
"asdf"
};
var sourceIdType = ExchangeIdFormat.RestId;
var targetIdType = ExchangeIdFormat.RestImmutableEntryId;
var res = graphClient.Users["user_id"].TranslateExchangeIds(inputIds, targetIdType, sourceIdType).Request().PostAsync();
var a = res.Result;
I figured out, that the firstMailboxElement.SourcePostbox was null, when the exception occoured.
So the call went to client.Users[null], so the request URL was incomplete.
I'm trying to call an Azure Machine Learning Pipeline Endpoint I've set up using C# & the Machine Learning REST api.
I am certain that I have the Service Principal configured correctly, as I can successfully authenticate & hit the endpoint using the azureml-core python sdk:
sp = ServicePrincipalAuthentication(
tenant_id=tenant_id,
service_principal_id=service_principal_id,
service_principal_password=service_principal_password)
ws =Workspace.get(
name=workspace_name,
resource_group=resource_group,
subscription_id=subscription_id,
auth=sp)
endpoint = PipelineEndpoint.get(ws, name='MyEndpoint')
endpoint.submit('Test_Experiment')
I'm using the following example in C# to attempt to run my endpoint: https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-pipelines#run-a-published-pipeline-using-c
I'm attempting to fill auth_key with the following code:
var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
var cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
var auth_key = cred.GetToken(new Azure.Core.TokenRequestContext(new string[] {".default" }));
I receive a 401 (unauthorized).
What am I am doing wrong?
UPDATE *
I changed the 'scopes' param in the TokenRequestContext to look like:
var auth_key = cred.GetToken(new Azure.Core.TokenRequestContext(new string[] { "http://DataTriggerApp/.default" }));
http://DataTriggerApp is one of the servicePrincipalNames that shows up when i query my Service Principal from the azure CLI.
Now, when I attempt to use the returned token to call the Machine Learning Pipeline Endpoint, I receive a 403 instead of a 401. Maybe some progress?
Ok, through a lot of trial-and-error I was able to come up with two ways of acquiring a token that allows me to hit my Azure Machine Learning Pipeline Endpoint through the REST api. One uses Microsoft.Identity.Client & one uses Azure.Identity.
using Microsoft.Identity.Client;
...
public static async Task<string> GetAccessToken()
{
var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
var app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(AzureCloudInstance.AzurePublic, tenantId)
.Build();
var result = await app.AcquireTokenForClient(new string[] { "https://ml.azure.com/.default" }).ExecuteAsync();
return result.AccessToken;
}
Or:
using Azure.Identity;
...
public static async Task<string> GetAccessToken()
{
var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
var cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
var token = await cred.GetTokenAsync(new Azure.Core.TokenRequestContext(new string[] { "https://ml.azure.com/.default" }));
return token.Token;
}
I have been trying to get the members of a specific securitygroup from Azure AD with the following code from Graph api
var members = await graphClient.Groups["{group-id}"].Members
.Request()
.GetAsync();
I followed the following link which says to give the following permission to the registered app link: https://learn.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=csharp
and the permission for the application has been granted by the Admin;
But I keep getting the following error
ServiceException: Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation
I Using a client secret to create graphClient. And I grant permission like below, it works for me. You also can use other provider to do that.
My test code
public async Task<JsonResult> test()
{
// Values from app registration
var clientId = "fb2****-29ee-****-ab90-********0c7e1";
var clientSecret = "w7N*******........***yO8ig";
var scopes = new[] { "https://graph.microsoft.com/.default" };
// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "e4c9ab4e-****-40d5-****-230****57fb";
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
try
{
var members = await graphClient.Groups["13ad4665-****-43e9-9b0f-ca****eb"].Members.Request().GetAsync();
return Json(members);
}
catch (Exception e)
{
return Json("");
throw;
}
}
My test result
1st step : you will have to register an AD app and give permission on graph to read users and groups, please check this stackoverflow answer
I am trying to create Online Meeting using microsoft graph api without login into AzureActiveDirectory with asp.net web application.For this my app has below permissions which are required as per documentation https://learn.microsoft.com/en-us/graph/api/application-post-onlinemeetings?view=graph-rest-1.0&tabs=csharp with client credential auth flow https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow without immediate interaction with a user.I am able to retrive access token successfully as per client-creds-grant-flow.
I tried Micosoft.Graph and Micosoft.Graph.Beta still getting 404 error.
Create online meeting code
var graphClient = GetAuthenticatedClientCredential();
var onlineMeeting = new OnlineMeeting
{
StartDateTime = DateTimeOffset.Parse("2020-10-01T10:30:34.2444915+00:00"),
EndDateTime = DateTimeOffset.Parse("2020-10-01T11:00:34.2464912+00:00"),
Subject = "Create Online Meeting-Without user login to Office 365"
};
return await graphClient.Me.OnlineMeetings
.Request()
.AddAsync(onlineMeeting);
Access Token code
public static async Task<string> GetUserAccessTokenAsyncByCc()
{
IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder.Create(appId)
.WithTenantId(appTenantId)
.WithClientSecret(appSecret)
.Build();
string[] scopes1 = new string[] { "https://graph.microsoft.com/.default" };
//string[] scopes1 = new string[] { "https://graph.microsoft.com/OnlineMeetings.ReadWrite.All" };
// string[] scopes1 = new string[] { "https://graph.microsoft.com/beta/OnlineMeetings.Read.All" };
//string[] scopes1 = new string[] { "https://graph.microsoft.com/beta/.default" };
var result = await cca.AcquireTokenForClient(scopes1).ExecuteAsync();
return result.AccessToken;
}
and Auth Provider code
public static GraphServiceClient GetAuthenticatedClientCredential()
{
DelegateAuthenticationProvider provider = new DelegateAuthenticationProvider(
async (requestMessage) =>
{
string accessToken = await GetUserAccessTokenAsyncByCc();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
});
GraphServiceClient graphClient = new GraphServiceClient(provider);
return graphClient;
}
app permission image
below are the necessary app permission
You can only use delegated permissions to create an onlineMeeting, so you must log in as a user, and you cannot use the client credential flow. You need to use the auth code flow to obtain the token.