SharePoint / sp-dev-docs

SharePoint & Viva Connections Developer Documentation
https://docs.microsoft.com/en-us/sharepoint/dev/
Creative Commons Attribution 4.0 International
1.25k stars 1.01k forks source link

SPFx Teams tab Graph API- teamwork: sendActivityNotificationToRecipients #8786

Open SantanuPati opened 1 year ago

SantanuPati commented 1 year ago

We ### What type of issue is this?

Question

What SharePoint development model, framework, SDK or API is this about?

πŸ’₯ SharePoint Framework

Target SharePoint environment

SharePoint Online

What browser(s) / client(s) have you tested

Additional environment details

Issue description

I am using Graph teamwork-sendactivitynotificationtorecipients API to send activity notification to bulk users using a custom topic https://learn.microsoft.com/en-us/graph/api/teamwork-sendactivitynotificationtorecipients?view=graph-rest-1.0#example-2-notify-multiple-users-about-an-event-using-a-custom-topic. (Using this API as I need to send the multiple specific users and can't send it via teams or channel members API)

Although I have noticed that this API has some limitation on Token refresh as documented by Microsoft (Note: The token provided must be at least 45 minutes away from expiry. The API call will return a 412 Precondition Failed response if the token expires within 45 minutes.) --This is causing error multiple times whenever the current token crosses the first 15 minutes.

Do we have any workaround for this limitation - such as forcing the token to refresh(in SPFx) every time before calling this API?

ghost commented 1 year ago

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

SantanuPati commented 1 year ago

@AJIXuMuK - do you have any suggestions here?

AJIXuMuK commented 1 year ago

@SantanuPati - thank you for bringing this up. We're discussing it internally.

smolattack commented 1 year ago

Can you not request a new token before making the call? https://learn.microsoft.com/en-us/javascript/api/sp-http/aadtokenprovider?view=sp-typescript-latest#@microsoft-sp-http-aadtokenprovider-gettoken-member(1)

`useCachedToken`    boolean

Allows the developer to specify if cached tokens should be returned.
SantanuPati commented 1 year ago

@smolattack Thanks for the input. But this doesn't refresh the token. It always returns the old token, irrespective of "useCachedToken" value.

smolattack commented 1 year ago

I'm assuming that the AAD client uses MSAL internally. https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/caching.md

I think the useCachedToken only controls the client side caching (i.e., whether or not a call is made to AAD identity provider). I think the problem is that the identity provider caches the token on the server side and doesn't generate a new one every time your request it. I don't think there is a public API to bust that cache (other than to delete and recreate the app registration/permissions).

If you're notifications aren't time-sensitive, I can only suggest the obvious, just retry when you get a 412 or decode the token and get the expiration date.

SantanuPati commented 1 year ago

Thanks for your input, indeed I completely agree with your points.

Unfortunately In my case it's time-sensitive, moreover we can't hold users in a screen for that long while retrying. In some scenarios it can be as long as 45 min before getting a refreshed token.

AJIXuMuK commented 1 year ago

@SantanuPati - we have created an backlog item to come up with an approach of force refresh access token if MSAL allows it.

SantanuPati commented 1 year ago

@AJIXuMuK is there any update on this topic?

MarksPoint commented 1 month ago

Are there any updates on this matter?

We're trying to leverage the same API to send Teams notifications and we run into the same 412 error when the token is within 45 minutes of expiring.

Fetching a 'fresh' token using the getToken method of the AAD token provider that was initiated using the aadTokenProviderFactory doesn't do the trick, even with the useCachedToken argument set to false. With the flag set to false, we do get new tokens, but the expiry claim in the JWT token is always the same.

A dirty fix we found that works in SharePoint is to delete the local storage entry with key 12d0e7df-***-***-9c51-****6c6808cc.da4d975a-***-***-88b1-****be7e26d3-login.windows.net-accesstoken-08e18876-***-***-b8b5-****0c1e598c-da4d975a-***-***-88b1-****be7e26d3-f5feb208-***-***-b33c-****46763459/user_impersonation f5feb208-***-***-b33c-****46763459/.default-- right before we do the getToken call. This somehow triggers logic to fetch a new OBO token with a fresh expiration date that is then used to get the access token.

_(The key is composed of various Guids, being [user.aadObjectId].[tenantId]-login.windows.net-accesstoken-[spWebClientId]-[tenantId]-[spAppId]/userimpersonation [spAppId]/.default--)

Unfortunatetly, this fix only works in SharePoint, but doesn't work when we run our SPFx app as a Teams personal app because this key isn't used in this context. We haven't found a workaround for this scenario...

@SantanuPati did you find a solution to this? @AJIXuMuK Is the item still on your backlog or have you introduced a way to fix this?