Register GraphAPI subscription in multi tenant case - microsoft-graph-api

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.

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?

Error in SharePoint oAuth Authentication using Sharepoint Online CSOM and PnP in .net core

I am trying to make sharepoint authentication using oAuth(Azure AD App) using Sharepoint Online CSOM and PnP, but it gives error "The given key was not present in the dictionary.". I have created Azure AD App and added API permission for Sharepoint AllSite.FullControl in that app.
I am using trial sharepoint tenant.
Here is my code snippets:
ClientContext _sharepointContaxt = null;
string Username = [Username];
string Password = [Password];
string AppId="67b1845e-88b1-4e6c-b7db-7f1d3abe3b06";
Uri site = new Uri([Sharepoint_site_url]);
using (var authenticationManager = new AuthenticationManager("67b1845e-88b1-4e6c-b7db-7f1e3aae3a06"))
using (_sharepointContaxt = authenticationManager.GetContext(site, Username, SecurePassword(Password)))
{
Web web = _sharepointContaxt.Web;
_sharepointContaxt.Load(web);
_sharepointContaxt.ExecuteQuery();
}
I faced the same "The given key was not present in the dictionary." issue whenever I occasionally sent Post request to Azure AD in a for loop. I'm not sure if this failure scenario is as the same as yours.
One of my debug way is to check the dictionary and see which "given key" was lost. In AuthenticationManager class, there is a private method called AcquireTokenAsync. This method is to request Azure AD to return SPO accessing token, and save it as a Json format in variable tokenResult, and then use GetProperty("access_token") to get token.
If Azure AD did not return SPO token for some reason, access_token might not be available in the tokenResult, result in the error code you saw.
In this case, error message in tokenResult help you to see the reason why Azure AD did not return the token.

Microsoft.Graph.Core create subscription "Access denied"

Following this walkthrough, I'm able to get a "subscription" on my Azure Function to a users mailbox.
However when I modify it to try to access a users onedrive, I'm able to access their files in the app, but when attempting to subscribe for a webhook I get the error below. I verified my token has Files.ReadWrite.All permission so I don't understand what I'm missing.
[2020-11-19T16:17:12.327Z] Executed 'SetDocSubscription' (Failed, Id=01410f60-0954-4e37-b9aa-2940cf9d0a17, Duration=2177ms)
[2020-11-19T16:17:12.330Z] System.Private.CoreLib: Exception while executing function: SetDocSubscription. Microsoft.Graph.Core: Code: ExtensionError
[2020-11-19T16:17:12.331Z] Message: Operation: Create; Exception: [Status Code: Forbidden; Reason: Access denied]
[2020-11-19T16:17:12.332Z] Inner error:
[2020-11-19T16:17:12.333Z] AdditionalData:
[2020-11-19T16:17:12.334Z] date: 2020-11-19T16:17:11
[2020-11-19T16:17:12.335Z] request-id: ccd648e7-b3fc-43f6-b1c5-481cbb5dcab6
[2020-11-19T16:17:12.336Z] client-request-id: ccd648e7-b3fc-43f6-b1c5-481cbb5dcab6
[2020-11-19T16:17:12.337Z] ClientRequestId: ccd648e7-b3fc-43f6-b1c5-481cbb5dcab6
...additional detail, calling function looks like this:
// Create a new subscription object
var subscription = new Subscription
{
ChangeType = "updated",
NotificationUrl = $"{notificationHost}/api/DocsNotify",
Resource = $"/users/{payload.UserId}/drive/root/",
ExpirationDateTime = DateTimeOffset.UtcNow.AddDays(2),
ClientState = Notify.ClientState
};
// POST /subscriptions
var createdSubscription = await graphClient.Subscriptions
.Request()
.AddAsync(subscription);
return new OkObjectResult(createdSubscription);
I am suspecting you're exceeding the limits here. When any limit (it can be Azure AD resource limitation as well) is
exceeded, attempts to create a subscription will result in an error
response - 403 Forbidden.
You can see the above error. In your
scenario, you will see the message property which will explain which
limit has been exceeded.
Here's the related doc.

Twilio Invalid Access Token Signature (iOS - Swift)

I am using Twilio's latest SDK they released on CocoaPods as of today. I am trying to implement VOIP feature to my app with Twilio Programmable Voice. My backend is .net which also uses the latest release of Twilio Helper Library for C#.
My client code looks like:
fetchAccessToken { (accessToken: String) in
TwilioVoice.register(withAccessToken: accessToken, deviceToken: deviceToken) { (error) in
if let error = error {
NSLog("An error occurred while registering: \(error.localizedDescription)")
}
else {
NSLog("Successfully registered for VoIP push notifications.")
}
}
}
What I get in the console is as following:
voipTestWithTwilio[2431:517236] [ERROR TwilioVoice] Inside register:deviceToken:completion:, failed to register for Twilio push notifications. Error:Invalid access token signature
voipTestWithTwilio[2431:517236] An error occurred while registering: Invalid access token signature
This is the C# code that actually creates the token:
var grant = new VoiceGrant
{
OutgoingApplicationSid = outgoingApplicationSid
};
var grants = new HashSet<IGrant> { { grant } };
var token = new Token(
accountSid: accountSid,
signingKeySid: apiKey,
secret: apiSecret,
identity: identity,
grants: grants
);
return token.ToJwt();
I have been looking for the issue on the internet, nothing helped so far. I have tried contacting them but have not got any response back. I also tried creating new api keys and even a new project for a couple times on Twilio. Can anybody say something about the issue?
UPDATE
I added push notification sid to VoiceGrant and now I’m getting 403 Forbidden.
On Twilio error codes page it is explained as: “The expiration time provided in the Access Token exceeds the maximum duration allowed.” which is definitely not my case. However, I tried passing expiration parameter in Token constructor with various values which didn’t change the result.
The problem is still persisting.
I solved the issue. It was because my server returned the token with quotation mark.
I remember print(token)'ing on client (iOS) to see whether there is encoding issue or something and all I see was a proper token between quotation marks. Since token is a string value, I didn't pay attention to quotation part of it. That's where I was wrong.

Unauthenticated identites not mapping to Developer Authenticated Identity

When a user launches the app they are an unauthenticated user and they receive a unauthenticated cognito identity supplied from the DeveloperAuthenticatedIdentityProvider class in the iOS app. I can see that unauthenticated cognito identity in the cognito console. However, when they login and I make a call to my nodejs backend with a logins map of:
{
DevAuthIdentityLogin:<username>
}
and using this backend code:
getCognitoIdentity: function(logins, cognitoId, error) {
var cognitoidentity = new AWS.CognitoIdentity(awsOptions);
var params = {
IdentityPoolId: identityPool,
Logins: logins,
TokenDuration: (60 * 5)
};
cognitoidentity.getOpenIdTokenForDeveloperIdentity(params, function(err, data) {
if (err) {
console.log(err, err.stack);
error(err)
} else {
console.log(data); // successful response
cognitoId(data);
}
});
}
It creates a new identity id with the developer authenticated identity and I can see that in the cognito console, but the old unauthenticated one is not being mapped to this new developer authenticated one.
Do I need to supply the unauthenticated identity id in the logins map when making a call to my backend to associate the two? OR am I not making this call correctly. I need some clarification on how to map/merge these identities please.
I already answered your question on our forums, but you need to include the unauth identitity id as a parameter to the GetOpenIdTokenForDeveloperIdentity call, otherwise Amazon Cognito will have no way of knowing that it should associate your user identifier to that identity.

Resources