Wednesday, April 29, 2020

Speaking at Microsoft 365 Saturday Madrid Virtual 2020



I'm looking forward to speaking at Microsoft 365 Saturday Madrid Virtual 2020 on April 30, 2020.

Microsoft 365 Saturday Madrid Virtual (M365MAD) was created by the Microsoft 365 community from Madrid as a digital alternative to the famous SharePoint Saturday Madrid which must be postponed to October 2020 because of the current pandemic we are facing worldwide.

M365MAD is an online and free event which will be broadcasted from YouTube. International and local speakers will share their knowledge and experience about different areas of Microsoft 365. For instance, I will contribute to M365MAD 2020 as a speaker with a session about Site Designs and Site Scripts.

I want to thank the organizers for setting up this event and for having me as a speaker.

Related links:
• Agenda: https://microsoft-365-virtual-summit-spain.sessionize.com/schedule
• YoutTube channel: https://www.youtube.com/channel/UCY1cqnq_HqNlV9SGV5VzDjQ

Monday, April 27, 2020

Understanding the TeamsLogon page

Whenever you create a Teams personal app or a Teams tab, a Teams app package will be required. In case of SharePoint Framework (SPFx), SharePoint generates this app package automatically when the app gets synchronized to Microsoft Teams for instance by using the Sync to Teams ribbon button in the SharePoint app catalog. By default, the Teams app package contains the required images that let your app looks shine in Teams, but also a manifest file which contains important configuration about the app.

The generated Teams app package is convenient, but it does have its limitations - for instance it doesn't include localization or other kind of customization you might want to have. The alternative is to generate the app package manually. Microsoft already provides a very good guidance which you can find here. Therefore, I won't cover that in this blog post. Rather, I want to deep dive on the TeamsLogon page (/_layouts/15/TeamsLogon.aspx) which is part of those app manifests. The findings described here are the output of tests I have done on my test environment and on customers feedback.

TeamsLogon's URL structure:

Along with the request URL
https://{teamSiteDomain}{teamSitePath}/_layouts/15/teamslogon.aspx
two query string parameters are required to request the TeamsLogon page successfully:
- spfx
- dest

TeamsLogon page in action:

Let's forget SPFx for a moment! Maybe you just want to display a SharePoint page as a Teams personal app. The mere fact that SharePoint and Teams run in Microsoft 365 doesn't result in bypassing authentication to access SharePoint resources from a Microsoft Teams app. By default, SharePoint pages won't load inside Microsoft Teams apps. It requires additional configuration! Lucky us, since this is why the TeamsLogon page is therefor.

In simple words, the TeamsLogon page is a bridge between Microsoft Teams and SharePoint that makes the access from Microsoft Teams apps to SharePoint possible. Behind the scenes, this page uses an access token generated by the microsoftTeams SDK to authenticate against SharePoint using the SP.OAuth.NativeClient/Authenticate API. A successful POST call to this API, sets the SPOIDCRL cookie which is used for authentication in SharePoint on behalf of the signed in user. After authentication is completed, TeamsLogon page redirects the user to the page specified in the dest (destination) query string parameter. Moreover, depending if the destination page is a classic or a modern one, the spfx query string parameter will apply some layout modifications to the rendered page.

I've created a simple graphic which describes the TeamsLogon page's process:


dest query string parameter in detail:

The query string parameter dest plays a very important role in this authentication process. It contains the destination URL which will be loaded after authentication is completed. In addition to that, the value provided here will be used to build the base URL, which will be used as part of the SP.OAuth.NativeClient/Authenticate request. This is how the logic to build the base URL based on the dest value looks:

var baseUrl = decodeURIComponent(
window.location.href.substring(window.location.href.indexOf(destQueryParam) + destQueryParam.length));

Important: you can add query string parameters to the destination URL. If you want to have more than one query string parameter in the destination URL, it is important to encode the connecting & character. Otherwise, additional query string parameters will be recognized as being part of the TeamsLogon's URL and not as part of the destination page. This is how the encoded & character looks:

https://{teamSiteDomain}{teamSitePath}/_layouts/15/teamslogon.aspx?spfx=true&dest={teamSitePath}?forceLocale={locale}%26theme={theme}

spfx query string parameter in detail:

This parameter renders SharePoint modern pages inside Teams without navigation, footer and header. Basically, it renders only the page's content. Additionally, spfx requires a boolean value which must be always true. Setting it to false, results in the very famous Sorry, something went wrong error which happens when loading the page:


Also, those changes done by the spfx query string parameter won't apply to classic pages. Basically, navigation, header, footer etc. won't be hidden. If only the page's content should be displayed, additional CSS hack is required. I would personally advise against that and suggest you to use only modern pages inside Teams apps. This is what a classic page looks like when loaded inside Teams:


Final words:

Thank you for your reading this blog post. I hope it clarifies the meaning of the TeamsLogon page!

Thursday, April 16, 2020

List of errors you might face in the SharePoint API Management page

The SharePoint API Management page allows administrators to manage (approve, reject and remove) permissions requested/granted at tenant-level. However, the experience of error in this SharePoint admin area is simply terrible. From my point of view, a good error message should be an educational experience. Unfortunately, this is exactly the opposite in the SharePoint API Management page 😔

This blog post is a continuation of my previous post about a specific error message from the API management page which was causing confusion out there. Since Microsoft hasn't enhanced the error message's content and I have faced other encrypted errors when using the API management page, I decided to list all errors from the API management page in a dedicated blog post which I can maintain over the time.

The list below describes the possible error messages that you might get depending on the operation you want to execute. I also added possible solutions in order to help you getting rid of those inconvenient errors:

Case: 
Approve a requested permission as a SharePoint administrator
Error message:
[HTTP]:500 - [CorrelationId]:53ee2d9f-a0f9-2000-078d-b1ec5183945b [Version]:16.0.0.20001
Solution:
The logged in user must be a global administrator in order to approve requested permissions

Case: 
Reject a requested permission as a SharePoint administrator
Error message:
[HTTP]:403 - [CorrelationId]:5cee2d9f-801d-2000-6cd2-3db457dd64f0 [Version]:16.0.0.20001
Solution:
The logged in user must be a global administrator in order to reject requested permissions

Case: 
Remove a granted permission as a SharePoint administrator
Error message:
Insufficient privileges to complete the operation
Solution:
The logged in user must be a global administrator in order to remove granted permissions

Case: 
Approve a requested permission
Error message:
[HTTP]:400 - [CorrelationId]:a340499f-6054-2000-7120-91cbdfcc05f3 [Version]:16.0.0.20001
Solution:
Ensure the permission/scope wasn't misspelled. E.g.: A permission such as User.ReadWrit.All isn't valid! In this case, the requested permission would be User.ReadWrite.All. Consider correcting the permission and retrying the operation. Also, have a look at the Microsoft Graph permissions reference page for information about supported permissions: https://docs.microsoft.com/en-us/graph/permissions-reference

Case: 
Approve a requested permission
Error message:
[HTTP]:400 - [CorrelationId]:223e499f-00e1-2000-03d0-e19a7de3a6c5 [Version]:16.0.0.20001
Solution:
Ensure the API name/resource wasn't misspelled. E.g.: An API name such as Microsft Graph isn't valid! In this case, the specific resource secured with Azure AD would be Microsoft Graph. However, it is more common to face this error when dealing with  Azure AD enterprise applications. Consider correcting the API name and retrying the operation.

Case: 
Approve a requested permission
Error message:
[HTTP]:400 - [CorrelationId]:a53f499f-3046-2000-6cd2-30c17ac0aab4 [Version]:16.0.0.20001
Solution:
Ensure the API name isn't the application ID or the object ID of the resource secured with Azure AD. Only the display name of the application is supported! Consider correcting the API name and retrying the operation.


Helpful link:

This Microsoft documentation explains very well how to connect to Azure AD-secured APIs. It explains this process based on SharePoint Framework solutions. Check it out for more information!