Friday, March 11, 2022

Tip: Reuse authentication of MFA secured account over multiple Connect-PnPOnline calls

A best security practice to connect into SharePoint Online is configure MultiFactor Authentication (MFA). When connecting from PowerShell to SharePoint Online this can give some challenges, as the default 'Credentials' based logon is not MFA aware. Resolution for this is to use either '-Interactive' or '-PnPO365ManagementShell' flag: both result that you are enabled to interactive address the MFA challenge.
Need to address the MFA challenge is acceptable to do one-time. But in an administration context, it might be that you need to execute settings over a set of sitecollections. Then it is not a pleasant experience to everytime need to (re)logon including MFA challenge. Common way to address this is by piping the authenticated SPO connection into the subsequent PnP calls. But Connect-PnPOnline does not support the '-Connection' flag (other PnP cmdlets do support it; PnP is not consistent across all its cmdlets). But I found an alternative that works:
  • $connection = Connect-PnPOnline -Url $spoAdminUrl -PnPO365ManagementShell -ReturnCollection
  • Connect-PnPOnline -Url <Url to other site collection> -Interactive -ClientId $connection.ClientId

Saturday, January 8, 2022

Validate UDP communication in datacenter

When application setup is using UDP connection, and it is experiencing an issue on the UDP communication, as a first check you want to verify whether the UDP traffic is allowed over the network including the firewall(s). For TCP traffic you can use telnet as simple OS command tool, but telnet is not appropriate for UDP.
On a client station one would then typically use a network sniffer as Wireshark to monitor that the UDP traffic can be delivered and received. On a server in the data center this is typical not allowed. And the Windows Server does not include itself a command to verify UDP communication. But you can easily create a validation setup yourself via Windows PowerShell.
A good example/inspiration is post Test UDP connection with PowerShell.
PowerShell cmdlet running on both VMs / nodes in the datacenter
Result of the UDP communication test: both VMs can communicate to each other over UDP <port>

Wednesday, December 29, 2021

Beware: on site renaming, initial Url preserved as ReadOnly site collection

Last year Microsoft delivered the long-requested capability to change the address of a SharePoint Online site collection. One of the features is that any request to the original / initial site address, is seamless mapped to the renamed site address. An unexpected side-effect is that on SharePoint tenant level a placeholder site collection is created to deliver this site mapping / redirection.
Visualization of the effect: before + after
Before RenamingAfter Renaming

Friday, December 24, 2021

Things to be aware of when embedding video play in Teams Meeting

the presenter clarifies the multiple hop issue that may result for the audience in non-optimal experience when embedding a video play in the Teams meetings.

Awareness 1: Recording misses the video if embedded via PowerPoint live

In this video he also introduces the Microsoft recommendation how to resolve this; namely by uploading the video via PowerPoint already in the Microsoft cloud. With this approach the first 2 hops are avoided. This works like a charm for the people live in the meeting. But a caveat I noticed is that when you need a recording of the meeting for afterwards (re)watch, then the video play is missing.
Include the video play via PowerPoint Live in the Teams Meeting presentation
Video is playing in the Teams Meeting, audience can live watch it
Video play is missing in the recording of the Teams Meeting

Awareness 2: Embed the video as shared content - video play stops on ANY mouseclick

If you need to meetings to be recorded; then you must share the video ‘as content’. The first of the 3 hops can be avoided by storing the video first local on your workstation, and play it from there on a 2nd monitor. Select this 2nd monitor on which playing for sharing in the Teams, and don’t forget to turn on ‘Include computer sound’ ! The video playing is then both visible for the audience 'live' in the meeting, and also included in the Teams meeting recording. Caveat with this setup is that during video play, you must take care not to click your mouse at all. If you do so, it doesn't matter whether in other screen or application; the video play immediate stops, resulting in disrupted experience. If you want to rule out this risk, then the trick is to play the video on another system then the one used for sharing in Teams Meeting (or Live Event). This setup is described in detail by Chris Stegh in his excellent article Sharing Video in Microsoft Teams Meetings.
Include the video play via shared content in the Teams Meeting presentation
Video play is included in the recording of the Teams Meeting

Awareness 3: Reporter layout not propagated into recording

A nice recent addition to Teams Meeting is multiple layout-options for the presenter, contributing to more professional appearance to the audience. However, only the 'live' audience can enjoy it; in the recording the presenter mode is ignored and it always in side-by-side layout. This holds for both approaches: whether including the video via PowerPoint (but this is current a no-go if video AND need recording) and on including as shared content.
Reporter layout for the presenter in the 'live' meeting
Side-by-Side layout for the presenter in the recording of meeting

Wednesday, October 13, 2021

Beware: Issues in Hybrid Search Crawling might not be flagged

We have a mixed SharePoint setup with parts still on-prem, while for others we moved to Microsoft cloud. We try as much as possible to abstract our end-users from this complexity in the SharePoint landscape. Therefore we utilize SharePoint Hybrid Search to allow the end-users finding from one single search entrance all SharePoint stored content, whether stored on-prem or online.
From time to time we encounter issues in this setup, most significant cause being that the required trust on the on-prem search crawlers to online index is lost due change of certificate on Microsoft Online side. We are automated flagged if such issue occurs, as we have an automated health monitoring + notification on the state of the crawl logs. Too bad, due a recent Microsoft change we can no longer trustworthy rely on the automated signalling. For (design) reasons so far only known to Microsoft development team, they decided to no longer flag in the crawl log in case an error occurs on propagating crawled content to the online index. We noticed as we started missing recent content in the search results; while on inspection of the crawl log it was reported to be successful crawled: full green. Yet by doing a query on 'k=isExternalContent:1' the most recent on-prem crawled items were not included in the search result, a clear deviation from the healthy report of the on-prem to online crawling.
Note: the actual rootcause of the missed crawled items in the online index was that in the user policy of the on-prem webapplication some accounts were configured, that in online world no longer had a match. This resulted in failing to index in SharePoint Online with error "Hybrid ACL Mapping: Deny ACE with unknown/unmappable hybrid claim", but it turns out that such error is no longer notified back to the on-prem crawler context. As Office 365 customer you do not have visibility on the Online index; we only came to know of this rootcause after we involved Microsoft Support. Once cause known, the problem was easily fixed: we removed the stale accounts also from the on-prem user policy.

Sunday, May 30, 2021

Prevent that Azure AD B2B guests are blocked due expired MFA

Azure AD B2B can also be used to authorized identified externals to digital events that your organization hosts, via Teams Live Event or via any streaming platform that is access-control protected via Azure AD. To increase security, enterprise organizations typical employ Multi-Factor Authentication via MS Authenticator App. A problem can be that re-visiting guests have their MFA status expired, but are unaware of that. And then face issue at the moment they want to join the digital event.
To prevent this, better to explicit reset the MFA status before the event. But you should not do this blind for all invited guests, as there are likely also guests that still have and use an active MFA status; e.g. for regular external collaboration with your organization. The trick here is to inspect the latest logon of the guest, and in case this was longer ago then you can safely assume the person is not an heavy guest-user, and for safety sake reset the MFA.
Azure AD does not direct reveal 'last logon' information, but you can utilize that access is granted via OAuth2.0 tokens: Azure AD stores per account 'RefreshTokensValidFromDateTime'; and this value can be interpreted as the datetime of 'last logon' (source: How to find Stale(ish) Azure B2B Guest Accounts)

Saturday, May 22, 2021

Tip: How-To get non-persistent cookie (e.g ASP.NET_SessionId) within PowerShell

Context of my need: a COTS application deployed as Azure WebApp that is also used as REST Api by this webapplication, and the need to automate some of the provision capabilities in this application. The user-based authentication and access control on the Azure WebApp as Api is implemented by leveraging the SharePoint Add-In model, with the remote Azure App launched via AppRedirect.aspx. And next the Api endpoints check the 'SPAppToken' cookie included in Api request, plus the "ASP.NET_SessionId".
The first is rather simple to get hands on in PowerShell code, by 'Invoke_WebRequest' to AppRedirect.aspx with the proper launch parameters; and from the WebResponse object parse the SPAppToken value that is returned in body of the response.
However, the 2nd is more tricky: it is returned as non-persistent cookie in the response, and default not available within PowerShell automation context to read from the WebResponse object. I tried the approach described in Cannot get authentication cookie from web server with Invoke-WebRequest. Without success, but it did inspire me to an alternative approach; and that does work:

  function GetAzureAppASPNetSessionId() {
     $appLaunchCookies = "SPAppToken=$global:AzureSPAppToken&SPSiteUrl=$([System.Web.HttpUtility]::UrlEncode($global:targetSite))"
     $url = "$azureAppLaunchUrl/?SPHostUrl=$([System.Web.HttpUtility]::UrlEncode($global:targetSite))";

     $WebSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession;
     $wr1 = Invoke-WebRequest -Uri $url -Method Post -Body $akuminaCookie -WebSession $WebSession;

     $cookieCont = $WebSession.Cookies.GetCookies($appLaunchCookies);
     $aspNetSessionIdCookie =  $cookieCont | Where {$_.Name -eq "ASP.NET_SessionId" };
     if ($aspNetSessionIdCookie) {
        return $aspNetSessionIdCookie.Value;
    }
}