30-second answer
Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "PnP Scripts" `
-Tenant contoso.onmicrosoft.com
# The command above prints the app id it registered. Use it from here on:
$appId = 'the id printed by the registration'
Connect-PnPOnline -Url https://contoso.sharepoint.com -Interactive -ClientId $appIdSince PnP.PowerShell 2.99 there is no shipped multi-tenant application:
-ClientId is mandatory on every connection, and the id must be an app
registration in your tenant.
What this proves
That your scripts authenticate as an application your organisation registered, with scopes your organisation consented to, instead of a shared identity every PnP user on earth once used.
What it does not prove
- That the connection has the rights your script needs. The client id gets you authenticated; what you can read is decided by the delegated scopes on the registration and the rights of the signed-in user.
- That a wrong id fails clearly everywhere. It fails at connect time
with
AADSTS700016: Application with identifier '...' was not found in the directory, which at least names the problem.
PowerShell
# Browser available: interactive
Connect-PnPOnline -Url https://contoso.sharepoint.com -Interactive -ClientId $appId
# No browser on this host: device code
Connect-PnPOnline -Url https://contoso.sharepoint.com -DeviceLogin -ClientId $appIdExample output
WARNING: AADSTS700016: Application with identifier '31359c7f-...' was not
found in the directory 'e5373...'. This can happen if the application has
not been installed by the administrator of the tenant or consented to by
any user in the tenant.Explanation
The example output is the failure you will actually meet: the id of the
old shared PnP application, or of an app from another tenant, produces
AADSTS700016 before anything reaches SharePoint. The fix is never to
find "a working id" on a forum; it is to register an application in your
own tenant and consent to the scopes your work needs. One registration
serves all your scripts.
There is a second reason to require the id, and it is a governance
reason, not an authentication one. The shared PnP application was
removed in PnP.PowerShell 2.12.0 (there is no version 2.99, whatever
older posts claim; the governance engine corrected its own changelog on
that point, in place, with a note admitting the error). But the engine's
collector marks -ClientId as required even though the module itself
can sometimes proceed without it: evidence has to say which identity
observed it. A reading made under an application nobody can name is a
reading nobody can reproduce, and reproducibility is the entire value
of collected evidence.
Production considerations
- Choose the login flow before you connect. After a device-code login, PnP
refuses to switch to the tenant administration context, so a script that
needs
Get-PnPTenantSitemust authenticate againsthttps://<tenant>-admin.sharepoint.comfrom the start. - Device login exists for hosts without a browser; it is not a way around consent.
- Certificate-based application login (unattended, no user) is a separate registration with application permissions and admin consent.
Related governance rules
None. Authentication is how evidence gets collected, not a claim about a tenant; the collector records which identity kind produced each document.
References
- Register an Entra ID application for PnP PowerShell (PnP)
- Connect-PnPOnline (PnP PowerShell)
Found something wrong? Suggest a correction. The article source is not public; the engine it cites is.
What this answer underwrites
The engine reads these Microsoft operations to collect evidence, so what is established here is what those collectors rest on.