ErrorInsufficientPermissionsInAccessToken trying to update guest user profile photo Microsoft Graph - microsoft-graph-api

I've been using Microsoft Graph to try to update the profile photo of a guest user. I've tried using postman and our own front-end and always end up with the following exception:
Code: ErrorInsufficientPermissionsInAccessToken
Message: Exception of type 'Microsoft.Fast.Profile.Core.Exception.ProfileAccessDeniedException' was thrown.
Inner error:
AdditionalData:
I am, however, able to successfully retrieve the guest user's photo with a GET on both: users/{userid}/photo/$value and me/photo/$value, but unable to update it using a PUT or PATCH request on either of the URLs on both /beta/ and /v1.0/.
The request has the following scopes defined:
"scp": "AllSites.Read Calendars.Read Calendars.ReadWrite Calendars.ReadWrite.Shared Contacts.Read Directory.AccessAsUser.All EWS.AccessAsUser.All Files.Read.All Group.Read.All Group.ReadWrite.All Mail.Read Mail.Send MailboxSettings.Read MyFiles.Read Notes.Read Notifications.ReadWrite.CreatedByApp openid People.Read People.Read.All Place.Read.All Presence.Read.All profile Sites.Read.All Sites.Search.All Tasks.ReadWrite TermStore.Read.All User.Read User.Read.All User.ReadWrite UserActivity.ReadWrite.CreatedByApp UserNotification.ReadWrite.CreatedByApp"
Note the: User.ReadWrite as specified in the docs: profilephoto-update
I am specifically using the Id as opposed to the UserPrincipleName, so specifically: /users/{id}/photo/$value,
but I get the error on both of them regardless. I am making the PUT request as follows:
var photoBytes = Convert.FromBase64String(photoData);
var stream = new MemoryStream(photoBytes);
var graphServiceClient = new GraphProvider(graphToken).GraphServiceClient;
return graphServiceClient.Users[userId].Photo.Content
.Request()
.PutAsync(stream);
I am able to change the profile photo of a non-guest user, but I'm unable to do so with a guest user. Is it possible that there is an issue with Microsoft.Graph itself or am I missing something.

Thanks for reaching out to us , could you please try to add User.ReadWrite.All permission and retry again .
Thanks

Related

Insufficient privileges to complete the operation when adding a member to a Microsoft 365 group

While adding a member to a Microsoft 365 Group with permission type: Delegated - I am using the following error:
Microsoft.Graph.ServiceException
HResult=0x80131500
Message=Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
As per Microsoft's documentation - all the required permissions are added in the AD App: GroupMember.ReadWrite.All, Group.ReadWrite.All, Directory.ReadWrite.All, Directory.AccessAsUser.All
https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0&tabs=csharp
I am using the same code request provided by Microsoft:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var directoryObject = new DirectoryObject
{
Id = "{id}"
};
await graphClient.Groups["{group-id}"].Members.References
.Request()
.AddAsync(directoryObject);
What permissions are still missing ?
The missing role was User Administrator Role - once my "user" account got added I was able to add/remove the users.

Skip offline access permission in Microsoft OIDC authorization

I'm using this code
var app = ConfidentialClientApplicationBuilder.Create(AzureAdApplicationId)
.WithTenantId("organizations")
.WithRedirectUri(AzureAdRedirectUrl)
.WithClientSecret(AzureAdSecretKey)
.Build();
azureAdScopes = new List<string>() { "email" };
var signInRequest = app.GetAuthorizationRequestUrl(azureAdScopes);
var uri = await signInRequest.ExecuteAsync();
which produces the url
https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?scope=email+openid+profile+offline_access&...
All I need is the user's username and I don't need offline access to the user's account. How can I remove them from the scope?
You could request the url without offline_access, but Azure AD v2.0 OAuth2 Account Consent Page automatically lists "Access your data anytime" even though offline_access is not specified in scope. This is an issue related.
The Note shows in the document:
At this time, the offline_access ("Maintain access to data you have
given it access to") and user.read ("Sign you in and read your
profile") permissions are automatically included in the initial
consent to an application.

Error when querying Microsoft Graph API Shifts: "MS-APP-ACTS-AS header needs to be set for application context requests"

We are trying to query shifts in the Microsoft Graph API using a C# app, now that StaffHub got deprecated , in the past we were getting an Unknown Error which looked like a permissions issue.
In the docs I noticed permissions for Schedule.ReadAll and Schedule.ReadWriteAll so I added them to the application permissions in our App Registration in Azure.
Now when we send the request to https://graph.microsoft.com/beta/teams/{teamid}/schedule we get this error:
Microsoft.Graph.ServiceException: 'Code: Forbidden Message: {"error":{"code":"Forbidden","message":"MS-APP-ACTS-AS header needs to be set for application context requests.","details":[],"innererror":{"code":"MissingUserIdHeaderInAppContext"}}}
The documentation says the Schedule permissions are in private preview, are these required for querying a schedule & shifts, and if so, is it possible to request access to the private preview?
I'm in the same situation. It's possible to request private preview access (we have), but I'm guessing that it's primarily granted to Microsoft partners or at least have a connection at Microsoft.
The workaround for me has been getting access on behalf of a user. It does however require the user to enter username and password in order to get an access token, so it might not be a perfect solution for you. But it works. You need to add (and, I believe, grant admin consent for) delegated permissions for this to work, either Group.Read.All or Group.ReadWrite.All.
Edit:
I've got it working now. We have private preview access, so I'm not sure this will help you unless you do too, but as I understand it will be available eventually. Given your question, I presume you already have an access token.
Add MS-APP-ACT-AS as a header with the user ID of the user you want the Graph client to act as.
If you're using the Graph SDK for .NET Core you can just add a header to the authentication provider:
public IAuthenticationProvider GetAuthenticationProviderForActingAsUser(string userId, string accessToken)
{
return new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
// Get event times in the current time zone.
requestMessage.Headers.Add("Prefer", "outlook.timezone=\"" + TimeZoneInfo.Local.Id + "\"");
requestMessage.Headers.Add("MS-APP-ACTS-AS", userId);
return Task.CompletedTask;
});
}
Then you call the graph service client:
var authenticationProvider = GetAuthenticationProviderForActingAsUser(userId, accessToken);
var graphClient = new GraphServiceClient(authenticationProvider);
You should then be able to fetch the shifts:
var shifts = await graphClient.Teams[teamId].Schedule.Shifts
.Request()
.AddAsync(shift);

Microsoft Graph API - Insufficient privileges to complete the operation

I am trying to use Microsoft Graph API to update another user in Active Directory.
I have the following permissions set for both user and application at https://apps.dev.microsoft.com/
I've requested the following scopes:
Directory.ReadWrite.All
User.ReadWrite.All
Group.ReadWrite.All
I am able to get a listing of all users in the directory, but when trying to update (in this case, the city) it fails:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
var usersResponse = graphClient.Users.Request ().GetAsync ();
var users = usersResponse.Result;
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
var user = users.FirstOrDefault (m => m.Id == userId);
if (user != null) {
user.City = "New York";
await graphClient.Me.Request ().UpdateAsync (user);
}
I get:
{
Code : Authorization_RequestDenied
Message : Insufficient privileges to complete the operation.
Inner error
}
The user I am logged in as is a Global Administrator of the directory.
I took the JWT token, headed over to https://jwt.io and these are the roles I am seeing:
Directory.Read.All
Directory.ReadWrite.All
Files.ReadWrite
Group.ReadWrite.All
Mail.Send
User.Read
User.Read.All
User.ReadWrite.All
Do I need other permissions to make this happen?
At the end of the day, I'd like to create a console app (not web app) that I can update other user information in the directory. But I figured using this sample app provided by Microsoft is a good start.
The reason you're seeing this is because you're passing the complete user object rather than only the city property. In other words, you're attempting to update every property in that user record, including several that are read-only.
This is one of those cases where having an SDK that wraps a REST API can be result in some confusing errors. As REST API, it is stateless so passing in the entire user property set is telling the API you want to PATCH all of those values.
You're also passing in a different user object into the me object (i.e. you're replacing all of your property values with this other user's property values):
await graphClient.Me.Request().UpdateAsync(user);
Instead, try this:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
await graphClient.Users[userId].Request ().UpdateAsync(new User
{
City = "New York"
});

Google Fusion Tables 400 invalid_grant

I am trying to use google fusion tables API from Java. I am getting 400 Bad Request and
"error" : "invalid_grant".
I am using Service account API and OAuth2.0 to authorize my requests.
1) I have downloaded my secret key and use the below snippet for Credential.
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("[[293873940759-je0f8o4j90nmqvlbl6ofbtm0492paikd#developer.gserviceaccount.com]]")
.setServiceAccountPrivateKeyFromP12File(KeyResources.INSTANCE.getFileFromPath("b9b48154142d235bbd711c3eb8f86bb2ec155faf-privatekey.p12"))
.setServiceAccountScopes("oauth2:https://www.googleapis.com/auth/fusiontables")
.build();
2) I am using the below code to connect to code snippet.
Credential credential = ServiceAccount.INSTANCE.getCredentials();
Fusiontables fusiontables = new Fusiontables.Builder(ServiceAccount.HTTP_TRANSPORT, ServiceAccount.JSON_FACTORY, credential)
.setApplicationName("sfdgdfgdfgdfgdfgdfgf345q23")
.setHttpRequestInitializer(credential)
.build();
Fusiontables.Table.List listTables = fusiontables.table().list();
This is the error i am getting.
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:340)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:508)
Any help would be great.
Thanks,
Ganesh V
I think you have to remove the "[]" around your service account Id.
Apart from that, if you get 403 unauthorized error after you change the service account id, it might because that you have not grant the edit access for your table to you service account. To change the access, simply share you fusion table to you service account email and grant the "can edit" access.
Hope it help you.
I think you need to set a user email, as the service account need to delegate a user account:
GoogleCredential credential = new GoogleCredential.Builder()
...
.setServiceAccountUser(UserEmail)
and make sure the service Fusion Tables API is on, and in the user's owner domain console grant the correct scope to your service account:
https://www.googleapis.com/auth/fusiontables

Resources