Microsoft Graph - Update mailbox settings with SDK - c#

I'm trying to set automatic replies for Microsoft users using the example here.
The difference from the docs is that I'm trying to do this not for me, but for another user using permissions. Getting error: The OData request is not supported
The issue is mentioned here and here. But both are closed.
The one solution mentioned is here but for this I'm getting the error Access is denied. Check credentials and try again.
Does anyone know of a way to set automatic replies / update mailbox settings in microsoft graph using the c# sdk using the users option - not me?

Using application api permission is right here and we may also refer to the workaround mentioned by OP which worked for him.
===========================================
According to the api document, it support Application permission,
So could you pls try this code:
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var mailboxSettings = new MailboxSettings
{
AutomaticRepliesSetting = new AutomaticRepliesSetting
{
Status = AutomaticRepliesStatus.Scheduled,
ScheduledStartDateTime = new DateTimeTimeZone
{
DateTime = "2022-07-03T18:00:00",
TimeZone = "UTC"
},
ScheduledEndDateTime = new DateTimeTimeZone
{
DateTime = "2022-07-07T18:00:00",
TimeZone = "UTC"
},
ExternalReplyMessage = "I'm on vacation.",
InternalReplyMessage = "I'm on vacation."
}
};
var user = new User();
user.MailboxSettings = mailboxSettings;
await graphClient.Users["user_id"].Request().UpdateAsync(user);
And pls don't forget to add Application api permission MailboxSettings.ReadWrite in Azure AD.

Related

Microsoft graph get user by email or Mail

I need to query get a single user details through Microsoft graph by email id, can anyone help me I couldn't find it in MS docs.
var users = graphServiceClient.Users.Request().GetAsync().GetAwaiter().GetResult();
this brings only 100 users
I need to get user by email so I can get specific user
Pls try this code.
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "hanxia.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var temp = await graphClient.Users.Request().Filter("mail eq 'tiny#outlook.com'").GetAsync();
When we want to do a filter in Ms graph api, we may firstly check if the target property support filter, for ms user api, mail is supported.

Code: BadRequest Message: /me request is only valid with delegated authentication flow

I am trying to upload file on onedrive by using microsoft graph onedrive api.
I am using the method for authentication
Client credentials provider
https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS#client-credentials-provider
Like:
// /.default scope, and preconfigure your permissions on the
// app registration in Azure. An administrator must grant consent
// to those permissions beforehand.
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 = "my-tenantid";
// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
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);
HttpPostedFileBase file = Request.Files;[0];
int fileSize = file.ContentLength;
string fileName = file.FileName;
string mimeType = file.ContentType;
Stream fileContent = file.InputStream;
var res = await graphClient.Me.Drive.Root.ItemWithPath(fileName).Content
.Request()
.PutAsync<DriveItem>(fileContent);
After executing this code then it gives an error in response.
Message: /me request is only valid with delegated authentication flow.
Inner error:
AdditionalData:
date: 2021-12-29T05:30:08
request-id: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
client-request-id: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
ClientRequestId: b51e50ea-4a62-4dc7-b8d2-b26d75268cdc
Client credential flow will generate the token on behalf the app itself, so in this scenario, users don't need to sign in first to generate the token stand for the user and then call the api. And because of the design,when you used Me in the graph SDK, your code/app don't know who is Me so it can't work. You should know the user_id first and use /users/{id | userPrincipalName} instead of /Me, in the SDK, that is graphClient.Users["your_user_id"] instead of graphClient.Me
In your scenario, there're 2 solutions, one way is using delegated authentication flow like what you said in your title, another way is get the user id before calling the graph api so that you can use Users["id"] but not Me
===================== Update=========================
I haven't finished the code yet but I found the correct solution now.
Firstly, we can upload file to one drive by this api, you may check the screenshot if this is one drive or sharepoint:
https://graph.microsoft.com/v1.0/users/user_id/drive/items/root:/testupload2.txt:/content
If it is, then the next is easy, using the code below to get an access token and send http request to calling the api:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "your_azuread_clientid";
var clientSecret = "corresponding_client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(scopes);
var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
I know it's complex because the api is not the same as this one which has SDK sample, but I think it also deserves to try if they are similar.

Microsoft Graph for reading my own calendar in C#?

I am not an expert on all things Azure, but I'd like to read my own calendar programmatically. I found some code to access Microsoft Graph and read my calendar, but it seems I have to create an App Registration first, is it possible to SKIP the app registration if I only need to read my OWN calendar? here's my starting point:
var scopes = new[] { "User.Read" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var userName = "myaccount#company.com";
var password = "pwdhere";
var userNamePasswordCredential = new UsernamePasswordCredential(
userName, password, tenantId, clientId, options);
var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);
var events = await graphClient.Me.Calendar.Events
.Request()
.Filter("startsWith(subject,'All')")
.GetAsync();
You need an app registration, otherwise you couldn't even log in. If it's an Azure AD you don't control, such as your employer, you'll need to get an admin to create that for you.

How to create a API scope using Azure AD Graph API

I'm trying to use the Azure AD Graph API to create an API Scope for an Azure AD B2C application. This is the operation performed using the "Expose an API" blade in the portal.
I've tried adding the scope directly to the application like so:
var current = await graphClient.Applications[appId].Request().GetAsync();
var currentList = current.Api.Oauth2PermissionScopes ?? new List<PermissionScope>();
var newScope = new PermissionScope
{
AdminConsentDescription = scopeDescription,
AdminConsentDisplayName = scopeDescription,
IsEnabled = true,
Type = "Admin",
Value = scopeName
};
var updated = new Application {
Api = new ApiApplication {
Oauth2PermissionScopes = currentList.Append(newScope).ToList()
}
};
await graphClient.Applications[appId].Request().UpdateAsync(updated);
However, when I do that, I get an exception:
Microsoft.Graph.ServiceException
Code: ValueRequired
Message: Property api.oauth2PermissionScopes.id value is required but is empty or missing.
Does this mean that I need to create the scope separately then add it to the application? Looking over the Graph API docs, it isn't obvious how to do that and I haven't found any articles that discuss it, either.
How do you use Graph API to create API scopes?
if you want to use the Microsoft Graph API to create an API Scope for an Azure AD B2C application, we need to define PermissionScope object. The object should provide id(it is GUID).
For example
Register Application
Grant API permissions
Under Manage, select API permissions.
Under Configured permissions, select Add a permission.
Select the Microsoft APIs tab, then select Microsoft Graph.
Select Application permissions.
Select the checkbox of the permission Application.ReadWrite.All to grant to your application.
Select Add permissions. As directed, wait a few minutes before proceeding to the next step.
Select Grant admin consent for (your tenant name).
Create a client secret
code
static async Task Main(string[] args)
{
string clientId = "0159ec7d-f99f-***";
string clientSecret = "G_fM3QKa***essTRX23t1_o";
string tenantDomain = "{your tenat name}.onmicrosoft.com";
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantDomain)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var id = "fa89ac50-d5fd-47cb-9f3f-833f413a2ed4";
var app =await graphClient.Applications[id].Request().GetAsync();
var updated = new Application();
if (app.IdentifierUris.ToList().Count == 0) {
updated.IdentifierUris = new string[] { $"https://{tenantDomain}/{app.AppId}" };
}
var appscope = app.Api.Oauth2PermissionScopes.ToList();
var newScope = new PermissionScope
{
Id = Guid.NewGuid(),
AdminConsentDescription = "Allow the application to have read-only access to all Employee data",
AdminConsentDisplayName = "Read-only access to Employee records",
IsEnabled = true,
Type = "Admin",
Value = "Employees.Read.All"
};
appscope.Add(newScope);
updated.Api = new ApiApplication { Oauth2PermissionScopes =appscope };
await graphClient.Applications[id].Request().UpdateAsync(updated);
}
For more details, please refer to here.

IdentityServer4 unsupported_grant_type Error

I have been trying to get the simplest examples of IdentityServer4 to work for requesting access in pure code behind. I can get an access token when using a client request but not when doing a user login..
var discos = new DiscoveryClient(authority);
var disco = await discos.GetAsync();
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return null;
}
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("username", "password", "api1");
This is the client making the request using user details.
I get a perpetual unsupported_grant_type..
The server has it setup as:
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
}
Can anyone please identify what Im mising. User can login using the front end quick start UI that the software offers and this is built in functionality.. Why wont it work if the company is valid.
Your ClientSecrets is configured for the Sha256 of "secret" not the literal string "secret".
Update your tokenClient to pass the Sha256 of "secret" instead of the literal string "secret"
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret".Sha256());
Now resolved.
I have managed to get this working using a newer version of the nuget package so may have been some conflict with what I was reading and old requirements.
For ref I have uploaded the working demo with Server, API and console client to github:
https://github.com/PheonixProject/IdentityServer4Demo

Categories

Resources