Showing posts with label spfx. Show all posts
Showing posts with label spfx. Show all posts

Friday, March 8, 2024

Allowing arbitrary custom scripting in SharePoint Online, or not? – that is the question! (aka Stealing your data since 2001!)

…and the answer is, as it always has been, NO!



Disclaimer: the opinions of this post are mine entirely, and nothing to do with my work at Microsoft. I have not changed opinion on this matter in the past many many years.

Sparked by the recent message center post MC714186 – Remove Custom Script setting in OneDrive and SharePoint web, I figured I’d write out my stance and my full support of the planned change.

Summary: The Custom Script setting in OneDrive and SharePoint web will be removed in March 2024. A new PowerShell command, "DelayDenyAddAndCustomizePagesEnforcement", has been introduced to delay the change to custom script set on the Tenant until mid-November 2024. The NoScriptSite setting will be configured to True for all existing SharePoint sites and OneDrive sites except for specific site templates. Existing scripts in OneDrive and SharePoint sites will remain unaffected. Administrators can permit the execution of custom scripts on specific SharePoint sites using the Set-SPOSite command.

In the above summary I want to point out that “existing scripts will remain unaffected” means classic page injections. Not SPFx solutions on with the setting requiresCustomScript=true.

The challenge

SharePoint by design is a JavaScript application and has always allowed for extensibility in the UX. In modern ways extensibility is achieved via the SharePoint Framework (SPFx), which you should use, and that is ok. Because by virtue of how SPFx is built any script or logic in a SPFx solution is governed and controlled by design.

To explain what I mean. By arbitrary code I mean someone can insert and freely modify JavaScript that runs in a SharePoint site or page without anyone noticing. One example being a bad actor put script on a page which when a person visit the page then transfers all the persons OneDrive files to evil.corp in the background without the person ever knowing. And this has been possible with SharePoint in classic experiences since always, and also with 3p modern webparts when allowing script to run, or by bypassing settings for a site.

When writing code in a SPFx solution, it is no longer arbitrary. Someone wrote it, built it, and then handed the package over to a person with SharePoint admin role rights to install it (or by an admin role proxy if a site has it’s own app catalog). How diligent the process is for code review and installation is up to each organization, but at least the setup allows for a governed process to help control what is installed into a tenants SharePoint Online experience.

Arbitrary script on the other hand would be JavaScript added to SharePoint sites or pages by any regular user with edit rights or a site administrator. Every Team or Group creator is a site administrator of the associated site, and this is not very controlled in my opinion. With classic SharePoint, script can be injected or allowed via the Script Editor web part, via search display templates, and via something called custom actions. When Modern sites were introduced many years ago, allowing these features were by default turned by setting the “Allow and Customize Pages” permission to false. The feature is more commonly renamed in e.g. PnP PowerShell to NoScriptSite. Documentation on turning this on or off can be found at https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script.

Back to the message center post and what changes

  • In March, the SharePoint admin UX setting to allow custom script on OneDrive sites or self-service sites is going away, and is being replaced by a PowerShell cmdlet function Set-SPOTenant DelayDenyAddAndCustomizePagesEnforcement which you can use until mid-November 2024.
  • All new and existing sites will be set to block custom scripts unless they were created with any of these web templates: BLANKINTERNETCONTAINER#0, CMSPUBLISHING#0, BLANKINTERNET#0. GROUP#0, APPCATALOG#0, CSPCONTAINER#0.
  • From mid-November 2024, custom script is disabled for your sites every 24 hours. You can manually re-enable it with for example Set-SPOSite <SiteURL> –DenyAddAndCustomizePages. This means you need to set up a scheduled job every day to re-enable it where needed for SPFx solutions relying on this feature, unless you migrate your ungoverned script solutions to governed ones using SPFx.

Should you be worried?

If you are still on classic pages, then disregard as you are a lost cause anyways. It’s 2024 people! Modern is no longer modern. It is the new classic.

Hopefully most customers have moved over to using SharePoint Framework for any custom JavaScript solution running in SharePoint Online by now. However, the elephant in the room is my infamous Modern Script Editor Web Part- https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-script-editor/README.md. If built without changes then someone has changed the site settings to allow arbitrary script to run for the web part to work. When this is then flipped off every 24 hours by the service, the web part will stop running (which is good!).

Instead of working the web part will render ugly white space instead.

image
Alternatively you rebuild the web part bypassing the custom script check saying it does not rely on custom script (boooooo on you, and bad governance practice).

It is no secret what my take is on usage of this web part. The sample modern script web part should NEVER be used, and I will argue to my death that there are no good scenarios for it. Sure, it’s quicker to use compared to always creating new SPFx extensions or web parts, but is this ease of use more important than security? My answer is still a big NO! Sure, you may reduce the attack vector by using site scoped app catalogs, and maybe you have the utter most control for who can edit pages in those sites. But is this a long term risk you are willing to take?

Why not just build your scenario solutions in a governed way thus blocking someone from changing the code? If you have access to someone building the Modern Script Editor web part, then you also have access to someone who can do it the right way.

What now?

My hope is that people do not run a script every 24h to allow custom script, or that they cheat on building SPFx web parts to bypass scripting. Instead everyone should embrace this opportunity to get their solutions cleaned up – if they haven’t already.

Happy coding governed solution, and preventing your files from being stolen!

Wednesday, March 20, 2019

Puzzlepart introduces Hook me up! – an anchor part for modern pagers

In January of 2018 I wrote a post showing how you could use the modern script editor web part to add a jump anchor to a modern page. Of course, you should shy this web part due to possible security risks (unless you really really know what you are doing).

Last night Theresa Eller was looking for a proper solution to this on twitter, so I whipped up a small web part which adds an invisible span tag to the page, which you can anchor to. If you set scrolltome as the id, you can reference it when creating a hyper link in the text web part.

image

This time around I made the code compatible with both SharePoint 2016 and 2019 as well.

Go download the sppkg file from https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Part.HookMeUp and install it where needed.

Monday, March 18, 2019

Fetch a Bearer token in SharePoint context to be used with a back-end service


(The post image has nothing to do with bearer tokens, but the Lego 1967 Mustang GT I finished building is just freakishly cool!)

I’m working on a solution which has a small UI created using the SharePoint Framework. This UI will make an authenticated call to a back-end service, which again has to read some data from a SharePoint list for validation.

The easy approach would be to read the validation data in the UI, but this would lead to a potential security hole, disclosing the verification mechanism. I could also have read the SharePoint data using app-only permissions in the back-end service, but this adds one more moving piece.

Thus, I ended up with fetching a valid Bearer token for the logged in user, and passing that along to the back-end service, which in turn can use it for SharePoint authorization.

The code itself is fairly simple from within the SPFx web part.

const provider = await this.context.aadTokenProviderFactory.getTokenProvider();
const token = await provider.getToken('https://<tenant>.sharepoint.com');

Took me a few tries, but pass in the root URL for your tenant and you get a token you can use for future calls against any SharePoint resource (as long as it’s valid).

Tuesday, August 28, 2018

Gotcha when adding Office UI Fabric React to SPFx



(Update for SPFx v1.7 - 2018-11-09)
This post is still valid for SPFx v1.7

When installing a reference to Office UI Fabric React make sure to run

npm i office-ui-fabric-react@lts --save

and not

npm i office-ui-fabric-react@latest --save

Lts is the latest stable version, which currently is v5.122.1 and in this case compatible with React 15 which is what SPFx uses. The latest version is 6.57.0 which require React 16, and won’t build with SPFx.

Stable photo by Ryan Yeaman at Unsplash

Wednesday, August 22, 2018

An even better bundle optimization method for SPFx using webpack dynamic imports


Photo by Rose Elena at Unsplash

In my last post I ventured into how you dynamically can load script resources in your SPFx web part or extension. Typically you might have parts only needed in edit mode, or parts only used in certain view scenarios. By not including everything in the SPFx bundle you will reduce loading time and page bootstrapping of your solution.

For example, if you use a lot of Office UI Fabric components or an external library like moment, then your overall bundle size, or downloaded .js file increase a lot. If those components are not always needed, loading them dynamically at will is a better solution.

And, it’s so easy! SPFx uses web pack to create the bundle, and webpack allows for something called dynamic imports. And this is such a golden nugget – sitting there without anyone knowing :)

Tuesday, August 21, 2018

An adventure into optimizing SharePoint Framework runtime bundle sizes

image

(See https://www.techmikael.com/2018/08/an-even-better-bundle-optimization.html for an even better solution)

When I wrote the Modern Script Editor web part I went with using Office UI Fabric React (ouifr) for the editor UI. The web part bundle yields a zipped script file of 84KB when used on a page. Not that much really, and it will be cached in the browser. But most of the bundle size is due to the use of ouifr in the edit experience of the web part – not needed in view mode for a page.

Thus I’ve had a nagging feeling working on my mind for a while, and it occurred to me; why can’t I have the editor experience separate from the run-time experience?

And you can!! which I will explain how further in this post.

The result is that the updated web part now will download 4KB zipped on run-time instead of 84KB. A whopping 95% decrease. The editor experience will be another 141KB, which is more in total than before, but this only happens when you edit the page and web part – certainly a good trade off.

Tuesday, May 22, 2018

Two SPFx manifest settings you might not be aware of

image

If you take a look at the manifest schema for a SPFx web part there are a couple of settings you might want to take a look at.

hiddenFromToolbox

If hiddenFromToolbox is set to "true", the web part will not be visible in the modern SharePoint toolbox. Very useful for web parts you provision automatically on pages, but don’t want users to add themselves.

supportsFullBleed

If supportsFullBleed is set to "true", the web part can be added to a full page width zone on a modern page in a communication site, spanning from the left margin to the right margin without any white space.

Wednesday, April 11, 2018

Free status bar extensions for modern SharePoint sites

Did you think we were being lazy over at Puzzlepart? Think again. This time we give you a status bar top extensions.

statusbar

Get the code at https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Ext.StatusBar

The above image shows two notifications, one which checks if the Office 365 Group support external member or if the site allows sharing with external users. The other highlights a classification setting if it’s a specific value, in this case sites with classification Confidential or above will show a status message.

Technically it consists of three extensions, one base extension doing the rendering, and then you can add any number of other extensions which render a message based on the logic you decide. If there are nothing to render, then the status bar will not render.

I’m not saying the communication between the parts is the most graceful one, but it’s a pattern we are trying out – and it works, and you can use the base renderer with your own logic. Take a look at the two samples provided and you should figure out how to create your own. The clue is the messageId parameter which has to be the same for all extensions, to make them aware of each other.

Get the code at https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Ext.StatusBar

Thursday, March 29, 2018

Quick tip: easily test SharePoint Framework web parts on modern pages (addendum to Waldek’s post)

image

Did you know that you can easily test your SharePoint Framework web parts on modern pages?

If there’s one guy who know, it’s my friend Waldek Mastykarz. Today he had a post outlining how you can debug/test SPFx web parts on a real modern page, not the SharePoint workbench.

Monday, February 26, 2018

Alternative way to solve the issue where a SPFx v1.4.0 web part don’t show when upgrading.

In SPFx v1.4.1 there was an important bug fix which was introduced in SPFx v1.4.0. If you created a web part which was manually installed on a site collection, upgrading the web part would result in the web part not showing. The issue noted on the release notes for v1.4.1 says in order to fix this do the following:

  1. Remove all instances of existing SharePoint Framework solutions from site level
  2. Remove SharePoint Framework solution from app catalog
  3. Upload new SharePoint Framework solution built with 1.4.1 version to your app catalog
  4. Install SharePoint Framework solutions back to sites.

You don’t have to uninstall the solution, but can follow these steps instead:

  1. Upgrade your web part to SPFx v1.4.1 and bump the version number of the part in package-solution.json and package it.
  2. Navigate to https://<tenant>.sharepoint.com/sites/<AppCatalogSite>/Lists/ComponentManifests and remove the entry for the web part in question.
  3. Upload the updated web part to your app catalog, overwriting the old one, and ensure the app is checked in, if it becomes checked out.
  4. Upgrade the web part package on the site collection(s) where used (site contents, classic view, about on the part, then “Get it” to get the latest version.
    image
    image

Unfortunately there is no easy way to see all sites which have installed a particular SPFx v1.4.0 web part, so you have to loop over all sites in order to ensure they are all working as expected.

Tuesday, February 20, 2018

Automatically set an Office 365 Group Logo - Another free SharePoint Framework extension from Puzzlepart

image

Photo by Mikael Svenson

If you haven’t caught on already, at Puzzlepart we love sharing our small quirky workarounds. This time around it’s a run-once extension which will set the logo for an Office 365 Group when a group owner visits the site for the first time.

Get the extension code!

Friday, February 2, 2018

Two free SharePoint Framework Extensions for Office 365 Groups

Hands outstretched with a Christmas gift wrapped in holiday wrapping paper
Photo by Ben White at Unsplash

At Puzzlepart we believe that sharing is caring, and it’s pretty core in how we think about code and solutions. We contribute monthly to SharePoint PnP, but the two extensions released here are not really samples on how to use SPFx, but they solve concrete business problems.

We’ll start off with two extensions, and add more extensions and web parts in the time coming forward.

You can find the code at https://github.com/Puzzlepart/spfx-solutions

Enable Teams on an Office 365 Group

If you are working in an environment where the out of the box self-service of Office 365 Groups have been turned off, but you still want to create Teams for O365 Groups via some other provisioning solution – or give users an alternative to create the Team via the Teams client, this is the extensions for you.

Move Everyone to Visitors

By default in a public Office 365 Group every employee in your organization will have write access to the groups site. I believe you should be an explicit member of a group in order to produce content in it, so it makes more sense for a public group for everyone to have read-only access instead.

This extension sits silently on the group site, and when a group owner visits the site it checks that non-members have read-only and not contribute access. If the Everyone group somehow has been given contribute access, it’s moved back.

Thursday, January 11, 2018

Creating anchor link scrolling on a modern page using the Modern Script Editor Web Part

There are times when you might have some topical links at the top of a page, and once clicked you want the page to scroll down to the right section. This is a perfect use-case for the Modern Script Editor web part. The Modern Script Editor web part is part of the PnP sample web parts project at Github. (A pull request with an updated version to SPFx v1.4 is in the progress of being processed.)

First add a text section, highlight the link part and in the address field type a hash sign and a unique name. In my case I use #scrolltome.

image

Below the hero web part I add an instance of the Modern Script Editor web part. And this is the easy part. Paste in either of the following HTML snippets and your page will scroll down to this place once the above link is clicked. In the old days anchor tags was used for this, but in these modern times any tag with a unique id works.

  • <a name="something"></a>
  • <span id="something"></span>

image

The updated script web part has an added property to remove the top/bottom padding of the container, thus making the web part take up zero real estate on the page, perfect for this case.

image

Once you save your page and test the link this is what it looks like:

scroll

If you want a more smooth scroll that’s also possible with your favorite smoothing scrolling script/css.

Tuesday, October 10, 2017

Deploy a SharePoint Framework application customizer tenant wide

Creating application customizers which are available to all site collections is a very useful feature. Especially when it comes to site provisioning solutions. In my current project I’m creating a top banner which shows if the Office 365 Group is allowed to have external members, or if the team site can be shared with external users. This extension is installed on all new sites during creation.

Want to know more about a custom self-service solution for Office 365 Groups? Join me at ESPC November 16th 2017 where this post will be part of the solution demoed.

image

Wednesday, August 30, 2017

How to update a SharePoint Framework project to Drop 1.2 (Extensions RC0)

[Update September 2nd, 2017]

I’ve updated the steps to remove the node_modules forlder, as that seems to fix some of the build libraries.

--

With the release of SharePoint Framework Extensions RC, SPFx has moved to Drop 1.2. If you want to update an existing project these are the steps you need to take.

Update the generator to Drop 1.2

npm install -g @microsoft/generator-sharepoint 

Enter your SPFx project folder and open package.json, where you need to update the version numbers for the following packages:

dependencies

"@microsoft/sp-core-library": "~1.2.0",
"@microsoft/sp-webpart-base": "~1.2.0",
"@types/react": "15.0.38",


devDependencies

"@microsoft/sp-build-web": "~1.2.0",
"@microsoft/sp-module-interfaces": "~1.2.0",
"@microsoft/sp-webpart-workbench": "~1.2.0"

If you have other @microsoft packages, set them to 1.2 as well, or if it’s @microsoft/sp-client-base, you can remove it.

Next up, remove your node_modules folder with your favorite command before running:

npm install
gulp --upgrade

And you should be all set!

NOTE! You may run into other breaking API changes you have to deal with.

NOTE 2! If you are using Office UI Fabric with react, Drop 1.2 takes a dependency on v4.32.0, and not on v2.34.2. If you have an explicit link to v2.x, then you have to upgrade in order for the build to work. See this issue for information about Office UI Fabric React which I raised with Drop 1.2 https://github.com/SharePoint/sp-dev-docs/issues/827

Tuesday, August 8, 2017

SPFx bundle size when using Office UI Fabric React components

I was making some updates to a SharePoint Framework web part which utilized the React Office UI Fabric components today. Previously when I built the web part, the bundle .js size was about 10kb. When I built it today the size was suddenly close to 600kb.

image

The reason turns out to be how the build process works in SPFx. It now bundles Office UI Fabric components instead of re-using whatever SPO has installed. It actually makes sense to de-couple the dependency and ensuring your web parts won’t break if Microsoft decides to upgrade Office UI Fabric on their side.

Ideally I would like to externalize Office UI Fabric to a version which I control. Reading up on How to use the Office UI Fabric React in a Safe Way in Your Solution we’re told to put an explicit dependency in your project to Office UI Fabric, so you have control over the version. The biggest issue right now might be that can you really expect an average developer to hit that doc page? Hopefully the version will be added in packages.json in a future version of the SPFx generator. (See the end of this post for how to add the reference.)

Monday, July 10, 2017

Querying managed metadata using REST (unsupported)

I’m working with a set of SharePoint framework web parts and finally got fed up of using JSOM to work with managed metadata. Referencing JSOM feels wrong for so many reasons in this modern day and age, so I’d rather not do it.

I mean, when the out-of-the-box modern controls in SharePoint can work with terms using REST, why shouldn’t I? I like to believe I’m pretty modern.

image

After Fiddling the modern UI I found out that all taxonomy requests are working against a service at /_vti_bin/TaxonomyInternalService.json. This is a good old service, also listed on MSDN at https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.taxonomy.webservices.taxonomyinternalservice_methods.aspx. It is indeed marked for internal use, and until we get a new public REST point, everything points to that it should indeed work. If not, why would Microsoft use it themselves?

I have put together a sample SPFx web part based on the MSDN documentation, trial and error, showcasing different methods I found useful when retrieving terms. It’s by no means complete, but should help you get started.

You can find the sample at https://github.com/wobba/spfx4fun/tree/master/react-taxonomy-rest (link to all methods)

Samples include:

  • List term stores
  • List term groups in a term store
  • List term sets in a term group
  • Search for term by label
  • Search for term sets by name of term set or term in set
  • Get level one terms of a term set
  • Get child terms for a term

Using these calls you should have enough information to build a metadata driven megamenu, or build a taxonomy picker.

I have included interfaces for all the REST calls with some comments, but not for the returned results. You might have to examine the result JSON and pick out what you need.

And as a nugget I output the JSON with indentation, a tip I picked up from Sahil Malik :)

Sample interface

interface IGetSuggestionsRequest {
  start: string; // query
  lcid: number;
  sspList: string; // guid of term store
  termSetList: string; // guid of term set
  anchorId: string;
  isSpanTermStores: boolean; // search in all termstores
  isSpanTermSets: boolean;
  isIncludeUnavailable: boolean;
  isIncludeDeprecated: boolean;
  isAddTerms: boolean;
  isIncludePathData: boolean;
  excludeKeyword: boolean;
  excludedTermset: string;
}

Wednesday, June 7, 2017

Accessing Microsoft Graph resources from the SharePoint Framework

You can find the complete sample web part at: https://github.com/wobba/spfx4fun/tree/master/GraphCallTest

With the recent release of the Developer Preview of the SharePoint Framework it’s now possible to start running queries against the Microsoft Graph without the use of ADAL.

The savior in this case is the introduction of the GraphHttpClient class (which at the time of writing this does not have a documentation page).  If you decode the Bearer token used by GraphHttpClient you can see the following permissions being available:

The Groups permission lets you read information about Office 365 Groups, but not everything as stated in the documentation. You can read the basic information about the group as well as Exchange data like calendar events, but I got access denied when trying to list members of a Group.

Friday, March 10, 2017

Perhaps the only SharePoint Framework web part you will ever need

Ok, that’s not entirely true, but it might come in handy for sure…

[Update 2017-03-13]
This post sparked some action over the weekend on twitter and Facebook, and as a response Pat Miller at Microsoft put out one guidance article and one post with thoughts around the web part. The first one, How to block webparts from noscript sites, goes into detail how you today can mark a SPFx in a way so that you cannot add it to non-script sites (Group sites, Delve blog, sites where script is turned off etc.) Once this capability moves from the developer to the IT admin it's way better than any CAS policy we ever had back on-premises. The other is an issue titled General thoughts on a modern script editor webpart, which explains why Microsoft did not deliver this out of the box themselves.

Both of them are must-reads in my opinion to better understand how Microsoft think about governance in SPFx.

[Original post]
Unless you are all new to SharePoint pages, the chance that you have used at least one script editor web part or a content editor web part is pretty high. With the advent of the SharePoint Framework, Microsoft has given developers a way to create JavaScript solutions for modern pages. If you however have some small snippets or existing code, going the whole SPFx route might be a bit overkill.

Which is why I created a script editor web part for modern pages. Simply paste in any script or html, and it is rendered on the page.

modern-script-editor-wp

Code can be found at the sample SPFx web part github repo from Microsoft. Also a big thank you to Waldek for always being helpful and helping me with how to load a script async in SPFx.

The code works by loading each <script src> in sequence, and then executing any other script block. So if you have script dependencies, simply list them in the right order and it should just work.