Getting presence data from the Microsoft Graph API - microsoft-graph-api

I have been following the instructions to setup the Microsoft Graph Webhooks Sample for Node.js app here: https://github.com/microsoftgraph/nodejs-webhooks-rest-sample
However, when it tries to create the subscription I receive the following error:
Error: Operation: Create; Exception: [Status Code: BadRequest; Reason: Unsupported workload.]
at new GraphError (C:\Dev\nodejs-webhooks-rest-sample\node_modules\#microsoft\microsoft-graph-client\src\GraphError.ts:59:3)
at Function.GraphErrorHandler.constructErrorFromResponse (C:\Dev\nodejs-webhooks-rest-sample\node_modules\#microsoft\microsoft-graph-client\src\GraphErrorHandler.ts:62:18)
at Function.<anonymous> (C:\Dev\nodejs-webhooks-rest-sample\node_modules\#microsoft\microsoft-graph-client\src\GraphErrorHandler.ts:89:31)
at step (C:\Dev\nodejs-webhooks-rest-sample\node_modules\tslib\tslib.js:141:27)
at Object.next (C:\Dev\nodejs-webhooks-rest-sample\node_modules\tslib\tslib.js:122:57)
at C:\Dev\nodejs-webhooks-rest-sample\node_modules\tslib\tslib.js:115:75
at new Promise (<anonymous>)
at Object.__awaiter (C:\Dev\nodejs-webhooks-rest-sample\node_modules\tslib\tslib.js:111:16)
at Function.GraphErrorHandler.getError (C:\Dev\nodejs-webhooks-rest-sample\node_modules\#microsoft\microsoft-graph-client\lib\src\GraphErrorHandler.js:88:24)
at GraphRequest.<anonymous> (C:\Dev\nodejs-webhooks-rest-sample\node_modules\#microsoft\microsoft-graph-client\src\GraphRequest.ts:386:55)
My subscription configuration is as follows:
exports.subscriptionConfiguration = {
changeType: 'updated',
notificationUrl: 'https://123456789.ngrok.io/listen',
resource: '/me/presence',
clientState: 'SecretClientState',
includeResourceData: false
};
and I have the following permissions associated with my Azure app:
Azure app permissions
Can anyone suggest what I am doing wrong?

I tried the following which worked for me. Sharing the related info:
This API (me/presence) uses the Presence.Read.All delegated permission - i see that you already specified it.
A signed-in user is required.
Follow these steps to set up a webhook and retrieve these notifications:
Subscribe to a single user’s presence through the /communications/presences/{id} path.
Subscribe to a maximum number of 650 users by using /communications/presences?$filter=id in ({id},{id}...).
The {id} represents a user ID GUID.
Subscriptions expire every hour and must be renewed.

Related

Invalid Request 409 when trying to subscribe to Microsoft Graph for Presence

Executing a subscription to presence request for users with the SDK targeting the MS Graph API is resulting in an error:
409Graph service exception Error code: InvalidRequest
Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: InvalidRequest
Error message: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
POST https://graph.microsoft.com/v1.0/subscriptions
SdkVersion : graph-java/v5.16.0
SdkVersion : graph-java/v5.16.0
[...]
400 : Bad Request
[...]
My code is:
final Subscription subscriptionRequest = new Subscription();
subscriptionRequest.changeType = ChangeType.UPDATED.toString();
subscriptionRequest.notificationUrl = notificationsHost;
subscriptionRequest.resource = "/communications/presences?$filter=id in ("+userIdsSb.toString()+")";
subscriptionRequest.clientState = subscribeToPresenceRequest.getClientState();
}el
subscriptionRequest.clientState = UUID.randomUUID().toString();
subscriptionRequest.expirationDateTime = OffsetDateTime.now().plusHours(1);
Subscription subscription = null;
try {
subscription = graphClient.subscriptions().buildRequest().post(subscriptionRequest);
response.setSubscribed(false);
failedIds.addAll(this.getFailedIds(e));
log.error("Error while trying to execute subscribeToPresence. ", e);
if(failedIds!=null && !failedIds.isEmpty()) {
log.error("The ids {} failed during the subscription request ",failedIds);
response.setFailedIds(failedIds);
}
}catch(Exception e) {
log.error("General Error while trying to execute subscribeToPresence. ", e);
retur
}
My subscription request includes the following values:
applicationId: null
changeType: UPDATED
clientState: 7fc6bf6b-6cc2-438d-a293-aa47539ad02a
creatorId: null
id: null
latestSupportedTlsVersion: null
lifecycleNotificationUrl: null
notificationQueryOptions: null
notificationUrl: https://myhost:port/graph/listen
notificationUrlAppId: null
oDataType: null
resource: /communications/presences?$filter=id in ('932b90ca-e5a4-42c7-a985-f4ddfc6d6715','6be2455d-63ac-4423-aa3e-7188fdbd5e73','41b3d168-5c28-4596-ba3b-d5c70a3c3967','8830a8bc-f882-4c13-b33a-7031423b5a24','ab548af7-d5a9-4388-9800-7668a20bb2b9')
expirationDateTime: 2023-02-02T16:41:11.737+02:00
includeResourceData: false
I saw this article regarding the beta version of the sdk https://learn.microsoft.com/en-us/graph/api/resources/subscription?view=graph-rest-1.0.
It indicates "Subscriptions to resources marked with an asterisk (*) are available on the /beta endpoint only." and presence is one of those resources. Is this related to my error?
I tried to use this version instead, but I still have the same Invalid request error.
I am using delegated permission to call the /subscription/presence endpoint of the Microsoft Graph API.
I was able to fetch previous subscriptions by calling /subscription endpoint and was also able to find users through /users/filter endpoint with application permission.
Is there something wrong in the format of my subscription request? This all worked fine a few months ago and I haven't changed anything.
Is this related to SSL/TLS secure communication? But then again, why would my other requests get responses?

Security rules of realtime database doesn't work

I have a firebase realtime database as below:
The key for each user is the uid of the authenticated user.
Following the security rules tutorial, I created a simple security rule for authenticated users who have the correct User UID to access the users information.
Part of the Javascript code to access the realtime database is:
fireusers = firebase.database().ref('/users');
this.fireusers.orderByChild('identifier').equalTo(this.email).once("value").then((snapshot) => {
var temp = snapshot.val();
for (var tempkey in temp) {
this.globalvar.userName = temp[tempkey].name
this.globalvar.userCompany = temp[tempkey].company
}
})
But the access is denied, and the error log is:
ERROR Error: Uncaught (in promise): Error: permission_denied at /users: Client doesn't have permission to access the desired data.
Error: permission_denied at /users: Client doesn't have permission to access the desired data.
Can you please help for solving this problem?
Your code (that you didn't share) is trying to read the /users node. Your rules don't grant anyone access to that node, so the read gets rejected.
It is important to realize that Firebase security rules don't filter data, but instead merely check whether the code is trying to access any more data than it is allowed. And in your case it does, so it gets rejected.
To read the data, try to only read the path for the current user's UID: /users/$uid.
Also see: Restricting child/field access with security rules

Register GraphAPI subscription in multi tenant case

Having an Azure "App registration" which is single tenant it is possible to register a subscription for the graphAPI for calendar events with the following resource:
/users/<user-id>/events
However after switching the app registration to multi-tenancy when attempting to register by calling /users/<user-id>/events if fails with the error:
Error: Operation: Create; Exception: [Status Code: NotFound; Reason: The requested user '<user-id>#72f988bf-86f1-41af-91ab-2d7cd011db47' is invalid.]
The GUID 72f988bf-86f1-41af-91ab-2d7cd011db47 apparently seems to be the TenantId of Microsoft according to this reference.
So what probably should be different is that I have to "tell" which tenant the user belongs to when registering the subscription in the case of a multi-tenant app registration. What I tried so far without success is the following: /users/<user-id>#<tenant-id>/events. The error message then is:
Status Code: NotFound; Reason: The requested user '<user-id>#<tenant-id>' is invalid.]
So the question is: How must I pass the tenant-id in the request so the correct user can be resolved?
Update
The error observed happens using the msal-client (#azure/msal-node) like this to obtain the graphAPI access token:
// Get a token using client credentials
const response =
await msalClient.acquireTokenByClientCredential({
scopes: ['https://graph.microsoft.com/.default']
});
// First param to callback is the error,
// Set to null in success case
done(null, response.accessToken)
Where the msalClient is instantiated like this:
const clientConfig: any = {
auth: {
clientId: clientId,
authority: authority,
clientSecret: configuration.getSyncServerClientSecret()
}
};
msalClient = new msal.ConfidentialClientApplication(
clientConfig
);
But requesting a token manually with Postman and then calling https://graph.microsoft.com/v1.0/subscriptions just works....
So the error must be with the usage of msalClient.

Microsoft Graph returning Resource Not Found

I've registered an app in Azure AD and given it API permissions(both Application and delegated) to read all AD groups (Group.Read.All, also Directory.Read.All etc). Using this app I am using Graph Service Client to make a call to get user's AD groups.
public async Task<IEnumerable<GroupInfo>> GetAllGroupsOfUser(string mail)
{
IList<GroupInfo> result = new List<GroupInfo>();
IUserMemberOfCollectionWithReferencesPage memberOfGroups = await _graphServiceClient.Users[mail].MemberOf.Request().GetAsync();
.......... More code ........
}
It works fine for most of the users email but for few emails, which are present in the active directory, I'm getting the following exception
Code: Request_ResourceNotFound Message: Resource 'someuser#somedomain.co' does not exist or one of its queried reference-property objects are not present.
Your error is not that you lack certain permissions, and it has nothing to do with which api testing tool you are using. Your error is very simple. As your error message says, it is that you entered the wrong user email.
Your error message has clearly stated that there is no'someuser#somedomain.co' email, because this is not a correct email, it should be .com instead of .co.
So you must make sure that you enter the correct email without special characters or spaces.
This is my test result:
1.
2.

Microsoft graph API return ExtensionError when creating subscription

I have an application that uses MS Graph API to subscribe to calendar events. For most of the users this works fine, however, for certain users https://graph.microsoft.com/v1.0/subscriptions always fail with ExtensionError.
For the same user manually triggered sync works fine.
Other thread here say the issue got fixed for them over time but I am facing this issue for a long time now.
Example error:
Error message: Operation: Create; Exception: [Status Code: NotFound; Reason: The requested user '<user#email.com>' is invalid.]
POST https://graph.microsoft.com/v1.0/subscriptions
Prefer : IdType=ImmutableId
SdkVersion : graph-java/v2.3.2
SdkVersion : graph-java/v2.3.2
Authorization : [PII_REDACTED]
{"changeType":"created,updated,deleted","clientSta[...]
404 : Not Found
[...]

Resources