You run a PnP PowerShell script that worked fine for years, and you get this:
Connect-PnPOnline: Specified method is not supported.
Or, depending on which version of the module you are on, this one:
AADSTS700016: Application with identifier '31359c7f-bd7e-475c-86db-fdb8c937548e'
was not found in the directory.
Both mean the same thing. Nothing is wrong with your script. The app registration it was quietly relying on does not exist any more.
What happened
Until September 2024, PnP PowerShell shipped with a multi-tenant Entra ID app called PnP Management Shell, and every tenant could use it without registering anything. That is the app ID in the error above. The PnP team announced on 21 August 2024 that it was going away, and deleted it on 9 September 2024.
So Connect-PnPOnline -Url ... -Interactive with no -ClientId has nothing to authenticate against. You now need your own app registration in your own tenant.
This is a good change, even though it broke everyone’s scripts on the same day. That shared app had far more permissions than any one script needed.
The fix – register your own app
PnP gives you a cmdlet for this, so you do not have to click through the Entra portal. Run this once per tenant:
Register-PnPEntraIDAppForInteractiveLogin `
-ApplicationName "PnP.PowerShell" `
-Tenant contoso.onmicrosoft.com `
-Interactive
The one to watch here is -Interactive. On PnP.PowerShell 2.x you must include it, or you get this instead:
Register-PnPEntraIDAppForInteractiveLogin: Parameter set cannot be resolved
using the specified named parameters.
Which is not a helpful message when you are already fixing a different error. Check what you are on with Get-Module PnP.PowerShell -ListAvailable, and if you are ever unsure of the parameters for your version, Get-Command Register-PnPEntraIDAppForInteractiveLogin -Syntax tells you rather than the documentation, which describes whichever version is current.
You will then see a warning that no permissions were specified so defaults are being used, a line confirming the app was created with its ID, and a 30 second pause while Entra ID catches up before the consent window opens. Sign in and accept.
When it finishes it prints a Client ID – copy that, you need it every time you connect from now on.
The important thing to note is you need to be a Global Administrator or Application Administrator to run this, because it is creating an app registration and granting consent. If you are not, this is the point where you go and talk to whoever is.
Then connect like this:
Connect-PnPOnline `
-Url "https://contoso.sharepoint.com/sites/Demo" `
-ClientId "11111111-2222-3333-4444-555555555555" `
-Interactive
That is it. Every script you have needs that one extra parameter.
If your script runs unattended
Interactive login is no good for anything scheduled. For that you want app-only with a certificate:
Register-PnPEntraIDApp `
-ApplicationName "PnP.PowerShell.Unattended" `
-Tenant contoso.onmicrosoft.com `
-OutPath C:\certs `
-DeviceLogin
That writes a certificate to C:\certs. Then:
Connect-PnPOnline `
-Url "https://contoso.sharepoint.com/sites/Demo" `
-ClientId "11111111-2222-3333-4444-555555555555" `
-Tenant contoso.onmicrosoft.com `
-CertificatePath "C:\certs\PnP.PowerShell.Unattended.pfx" `
-CertificatePassword (ConvertTo-SecureString -String "yourpassword" -AsPlainText -Force)
Keep that certificate somewhere sensible. Anyone who has the file and the password has whatever permissions you granted the app.
Two things that catch people out
You still get an error after registering. Nine times out of ten the app is missing a permission, or the permission is there but nobody clicked Grant admin consent. Open the app in Entra admin center > App registrations > API permissions and check for the warning triangle.
Both cmdlets only add a small default set of permissions. If your script does something beyond reading sites, add what you need explicitly:
Register-PnPEntraIDAppForInteractiveLogin `
-ApplicationName "PnP.PowerShell" `
-Tenant contoso.onmicrosoft.com `
-SharePointDelegatePermissions "AllSites.FullControl" `
-GraphDelegatePermissions "User.Read.All"
Register once, put the Client ID somewhere your scripts can read it, and you are back to writing PowerShell instead of fixing it 🙂
If you are updating old scripts, my earlier post on copying SharePoint Online web part settings with PnP PowerShell is one of the ones I had to go back and fix – the connection line is the only part that changed.