PnP PowerShell: Complete Entra App Registration & Certificate Guide

Everything in one place — install PowerShell 7, install the PnP module, register your Entra app, generate a self-signed certificate, upload it, and connect with your method of choice.

PnP PowerShell is the most widely used open-source PowerShell module for managing SharePoint Online and Microsoft 365. To use it reliably in automated scripts, scheduled tasks, or Azure DevOps pipelines, you need an Entra app registration (formerly Azure AD app) and a certificate-based connection. This guide walks you through the complete setup from zero — including PowerShell 7 installation, module setup, roles, app registration in the Entra portal, self-signed certificate creation, and all three connection methods.

Which Connection Method Should You Use?

PnP PowerShell supports three authentication methods. Choose based on your use case:

Interactive

-Interactive

Opens a browser window for sign-in including MFA. Runs as the signed-in user.

✓ Development and testing

✓ Ad-hoc admin tasks

✗ Cannot be automated (requires human)

✗ Not for scheduled tasks

PFX Certificate

-CertificatePath

Authenticates non-interactively using a .pfx certificate file on disk. App identity, no user.

✓ Scheduled tasks, pipelines

✓ Works without cert store access

✗ PFX file (with private key) must be secured

✗ Password must be handled securely

Thumbprint

-Thumbprint

Authenticates non-interactively using a certificate already installed in the Windows certificate store.

✓ No PFX file on disk

✓ Ideal for on-premises servers

✗ Requires cert installed on each machine

✗ Windows-only

Interactive vs App-only permissions: The -Interactive method uses delegated permissions — the app can only do what the signed-in user can do. The -CertificatePath and -Thumbprint methods use application permissions — the app has its own identity and does not need a user account. For unattended automation, always use certificate-based authentication with application permissions.

Step 1: Install PowerShell 7

PnP.PowerShell is cross-platform and works on Windows PowerShell 5.1, but PowerShell 7 (built on .NET) is strongly recommended. It runs faster, supports more PnP cmdlets, and will be required in future module versions.

Check your current PowerShell version

PowerShell — check version
$PSVersionTable.PSVersion

# Look for Major: 7 (or higher) in the output
# If Major: 5, you are running Windows PowerShell — upgrade

Install PowerShell 7 via winget (recommended on Windows)

PowerShell or Command Prompt — install via winget
winget install --id Microsoft.PowerShell -e --source winget

# After installation, open a NEW terminal window and verify:
pwsh --version
# Expected output: PowerShell 7.x.x

Alternative: Install via MSI installer

Download the Windows 64-bit MSI from the PowerShell GitHub Releases page. The file is named PowerShell-7.x.x-win-x64.msi. Run the installer with default options.

After installation: PowerShell 7 installs alongside Windows PowerShell 5.1 — it does not replace it. Launch PS7 by running pwsh instead of powershell. In the Windows Start menu it appears as "PowerShell 7".

📄 Install PowerShell on Windows — learn.microsoft.com

Step 2: Install the PnP.PowerShell Module

The module is published to the PowerShell Gallery. Run these commands inside PowerShell 7 (pwsh).

Set the execution policy (if required)

PowerShell 7 — set execution policy
# If scripts are blocked, set the policy for the current user
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# Confirm when prompted (enter 'Y')
# RemoteSigned: local scripts run freely; downloaded scripts must be signed

Install PnP.PowerShell

PowerShell 7 — install module
# Install for the current user (no administrator rights needed)
Install-Module -Name PnP.PowerShell -Scope CurrentUser

# To install for all users on the machine (requires Run as Administrator)
# Install-Module -Name PnP.PowerShell -Scope AllUsers

# If prompted about an untrusted repository, enter 'Y' to accept

# Verify installation
Get-Module -Name PnP.PowerShell -ListAvailable

Update an existing installation

PowerShell 7 — update module
Update-Module -Name PnP.PowerShell

# Check the installed version
Import-Module PnP.PowerShell
Get-Module PnP.PowerShell | Select-Object Version

Module name matters: The current module is PnP.PowerShell (with a dot). An older module called SharePointPnPPowerShellOnline (no dot) exists on the Gallery but is deprecated and no longer maintained. Always use PnP.PowerShell.

📄 PnP PowerShell documentation — pnp.github.io

Step 3: Roles Required for App Registration

Creating an Entra app registration and granting it high-privilege permissions requires specific Azure AD roles. Confirm these with your tenant administrator before starting.

TaskRequired roleNotes
Create an app registrationApplication Administrator or Cloud Application AdministratorThese roles allow creating and managing app registrations without being a Global Admin
Grant admin consent for Graph permissionsPrivileged Role Administrator or Global AdministratorRequired for high-privilege Application permissions such as Sites.FullControl.All
Run SharePoint tenant-level cmdletsSharePoint Administrator or Global AdministratorNeeded for cmdlets like Get-PnPTenantSite — the Entra app alone is not sufficient
Upload certificate to appApplication Administrator (on that app)The app owner can upload certs to their own app without Global Admin

Least privilege note: If your scripts only access specific site collections and not the entire tenant, request Sites.Selected (application permission) and use Graph API to grant access to individual sites. This is the most secure option and avoids giving the app full tenant-wide SharePoint access.

Step 4: Register the App in Microsoft Entra ID

Sign in to the Microsoft Entra admin center (or Azure portal > Microsoft Entra ID). You need Application Administrator role or higher.

🏠 Microsoft Entra ID App registrations + New registration
entra.microsoft.com › Applications › App registrations › New registration
  • Name — Enter a descriptive name, e.g. PnP SharePoint Automation. This name appears in audit logs.
  • Supported account types — Select: Accounts in this organizational directory only (Single tenant). Only your organisation's users can use this app.
  • Redirect URI — Leave blank if you are only using certificate-based (non-interactive) authentication. If you also want -Interactive support, select Public client/native (mobile & desktop) and enter: https://login.microsoftonline.com/common/oauth2/nativeclient
Click: Register

Note your Application IDs

After registration, you land on the app's Overview page. Note down these two values — you will need them for every Connect-PnPOnline call:

📄 Your app Overview
entra.microsoft.com › App registrations › PnP SharePoint Automation › Overview
  • Application (client) ID — A GUID like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. This is your -ClientId parameter.
  • Directory (tenant) ID — A GUID that identifies your Entra tenant. This is your -Tenant parameter (you can also use yourcompany.onmicrosoft.com).

Copy both values to a temporary notepad — you will use them in Step 8.

Step 5: Configure API Permissions

For certificate-based (app-only) connections, you need Application permissions — not Delegated permissions. Application permissions give the app its own identity, independent of any user account. The required permissions depend on what your scripts will do.

🔒 Your app API permissions + Add a permission

Recommended permissions for SharePoint management

APIPermission nameTypeWhen you need it
Microsoft GraphSites.FullControl.AllApplicationFull read/write access to all SharePoint sites via Graph. Required for most PnP cmdlets in app-only mode.
Microsoft GraphSites.ReadWrite.AllApplicationRead and write sites — use instead of FullControl if you don't need to manage permissions.
Microsoft GraphUser.ReadBasic.AllApplicationResolve users by email/UPN. Required if scripts look up user profiles.
Microsoft GraphGroup.ReadWrite.AllApplicationManage Microsoft 365 groups (which back Teams and SharePoint team sites).
SharePointSites.FullControl.AllApplicationFull control via SharePoint CSOM/REST — required for tenant-level PnP cmdlets like Get-PnPTenantSite.
entra.microsoft.com › API permissions › Add a permission
  • Click + Add a permission
  • Select Microsoft GraphApplication permissions → search Sites.FullControl.All → tick the checkbox → click Add permissions
  • Repeat for any additional Graph permissions your scripts need
  • Click + Add a permission again → select SharePointApplication permissions → search Sites.FullControl.All → tick → Add permissions
Click: Grant admin consent for [Your Tenant]

⚠  Admin consent is required for Application permissions. Without it, connections will fail with an authorization error. Only a Privileged Role Administrator or Global Administrator can grant consent.

Principle of least privilege — use Sites.Selected: Instead of Sites.FullControl.All (which grants access to every site in your tenant), you can add Sites.Selected (Application, Microsoft Graph) and then explicitly grant the app permission to only specific sites using Graph API or PnP PowerShell's Grant-PnPAzureADAppSitePermission. This is best practice for production apps.

Step 6: Generate a Self-Signed Certificate

Certificate-based authentication requires a key pair: a public key (uploaded to Entra) and a private key (kept secure on your machine or server). You can generate both with a single PowerShell command. Run these commands in PowerShell 7 on the machine where you will run the scripts.

PowerShell 7 — create self-signed certificate
# ── Step 1: Create the certificate in the Windows cert store ──
$certName = "PnPSharePointApp"
$notAfter  = (Get-Date).AddYears(2)   # 2-year validity

$cert = New-SelfSignedCertificate `
    -Subject           "CN=$certName" `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -KeyExportPolicy   Exportable `
    -KeySpec           Signature `
    -KeyLength         2048 `
    -KeyAlgorithm      RSA `
    -HashAlgorithm     SHA256 `
    -NotAfter          $notAfter

# Output the thumbprint — save this value, you will need it later
Write-Host "Thumbprint: $($cert.Thumbprint)" -ForegroundColor Cyan

# ── Step 2: Export public key (.cer) — upload this to Entra ──
$cerPath = "C:\Certs\PnPSharePointApp.cer"
New-Item -ItemType Directory -Force -Path "C:\Certs" | Out-Null
Export-Certificate -Cert $cert -FilePath $cerPath
Write-Host "Public key exported to: $cerPath"

# ── Step 3: Export PFX (private + public) — use with -CertificatePath ──
$pfxPath     = "C:\Certs\PnPSharePointApp.pfx"
$pfxPassword = ConvertTo-SecureString -String "YourSecureP@ssword!" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath $pfxPath -Password $pfxPassword
Write-Host "PFX exported to: $pfxPath"

Secure your PFX file: The .pfx file contains the private key and is equivalent to a password. Store it in a dedicated folder accessible only to the service account that runs the scripts. Never commit it to source control, place it on a shared drive, or email it. Consider using Azure Key Vault for production environments.

Alternative: Use PnP's built-in certificate generator

After installing PnP.PowerShell, you can use New-PnPAzureCertificate which generates both the .cer and .pfx in a single command without creating a cert store entry:

PowerShell 7 — PnP certificate generator (alternative)
# This does NOT require an active PnP connection — run it before connecting
$pfxPassword = ConvertTo-SecureString -String "YourSecureP@ssword!" -AsPlainText -Force

New-PnPAzureCertificate `
    -CommonName         "PnPSharePointApp" `
    -OutPfx             "C:\Certs\PnPSharePointApp.pfx" `
    -OutCert            "C:\Certs\PnPSharePointApp.cer" `
    -CertificatePassword $pfxPassword `
    -ValidYears         2

# The cmdlet also outputs the Thumbprint and an Entra manifest JSON snippet
# you can paste directly into the app registration's Manifest tab

Step 7: Upload the Certificate to Your Entra App

Upload only the .cer file (public key) to Entra. Never upload the .pfx — Entra only needs the public key to verify signatures made by the private key.

🔒 Your app Certificates & secrets Certificates tab Upload certificate
entra.microsoft.com › App registrations › PnP SharePoint Automation › Certificates & secrets
  • Click the Certificates tab (not "Client secrets")
  • Click Upload certificate
  • Click the folder icon and browse to C:\Certs\PnPSharePointApp.cer
  • Optionally add a description, e.g. Script server — expires May 2028 (helps at renewal time)
Click: Add

After upload, the Certificates tab shows the certificate thumbprint, start date, and expiry date. The thumbprint shown here must match the one output by New-SelfSignedCertificate in Step 6.

Certificate flow — what goes where

New-SelfSignedCertificate
Creates key pair in Windows cert store
Cert:\CurrentUser\My
Export-Certificate (.cer)
Public key only
Safe to share
⇧ Upload to Entra
Entra stores fingerprint to verify your app's signature
Export-PfxCertificate (.pfx)
Private + public key
Password-protected
💾 Use with -CertificatePath
PnP reads the PFX and signs auth requests with the private key
🔑 Or use -Thumbprint
PnP looks up the cert in the Windows cert store by its thumbprint

Certificate expiry: Self-signed certificates expire. The -NotAfter (Get-Date).AddYears(2) gives you 2 years. Set a calendar reminder 60 days before expiry to generate a new certificate, upload the new .cer to Entra (you can have multiple active certificates at the same time), and update your scripts before removing the old one.

Step 8: Connect with Your Chosen Method

Replace the placeholder values with your actual Application (client) ID and Tenant ID from Step 4.

Method 1 — Interactive (browser sign-in)

Interactive authentication opens a browser window, signs in as a real user, and runs commands under that user's identity. It uses delegated permissions — the app can only access what the signed-in user is already allowed to access in SharePoint. Two variants exist depending on whether you supply -ClientId.

Variant-ClientId needed?App registration needed?Best for
A — PnP Management ShellNo — omit itNo (uses Microsoft's pre-built app)Ad-hoc scripts, testing, first-time use
B — Your own appYesYes — must have delegated permissions + Redirect URIControlled scope, audit trail, custom consent

Variant A — No ClientId (uses PnP Management Shell)

The PnP open-source team maintains a pre-registered Entra application called PnP Management Shell. You do not need to create your own app registration. The browser popup handles sign-in and MFA automatically. The first time this app is used in your tenant, a Global Administrator must grant tenant-wide consent once.

PowerShell 7 — Interactive (no ClientId, PnP Management Shell)
# No -ClientId required — PnP uses its own pre-registered app
Connect-PnPOnline `
    -Url "https://contoso.sharepoint.com" `
    -Interactive

# Verify
$web = Get-PnPWeb
Write-Host "Connected to: $($web.Title)"

First-run tenant consent: On the very first use of the PnP Management Shell app in your tenant, Entra presents a consent screen. A Global Administrator must approve it. This is a one-time step — all subsequent users can connect interactively without seeing the consent screen (assuming they have the required SharePoint permissions on the target site).

Variant B — Your own ClientId (delegated permissions)

If you need full control over which permissions the app requests, register your own Entra app and add delegated permissions to it. This is fundamentally different from the certificate-based methods (Methods 2 and 3): delegated permissions act on behalf of the signed-in user, meaning the user's own SharePoint access is the effective ceiling — the app cannot do more than the user can.

Before this variant will work your app registration needs two things in Entra:

  • A Redirect URI: In your app → Authentication → + Add a platformMobile and desktop applications → tick https://login.microsoftonline.com/common/oauth2/nativeclient → Configure. Then scroll to Advanced settings and set Allow public client flows to Yes.
  • Delegated permissions (not Application permissions — those are for cert-based auth only):
APIDelegated permissionWhen you need it
Microsoft GraphSites.ReadWrite.AllRead and write SharePoint sites as the signed-in user
Microsoft GraphSites.FullControl.AllManage permissions — user must already be a site owner or higher
Microsoft GraphUser.ReadBasic.AllResolve users by name or email in scripts
SharePointAllSites.FullControlSharePoint REST / CSOM tenant admin operations as the signed-in user
🔒 Your app API permissions + Add a permission Delegated permissions
PowerShell 7 — Interactive with your own app (delegated permissions)
# -ClientId is your own app registration that has:
#   - Redirect URI configured (Public client / native platform)
#   - Delegated permissions (Sites.ReadWrite.All, etc.) — NOT Application permissions
#   - "Allow public client flows" set to Yes in Authentication settings
Connect-PnPOnline `
    -Url      "https://contoso.sharepoint.com" `
    -ClientId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
    -Interactive

# Verify
$web = Get-PnPWeb
Write-Host "Connected to: $($web.Title)"

Delegated vs Application permissions — common mistake: The app registration created in Steps 4–7 of this guide was configured with Application permissions for certificate-based (non-interactive) use. If you pass that same ClientId to -Interactive, the sign-in will fail or return a token without the correct SharePoint scopes. Interactive auth requires Delegated permissions. You can add both permission types to the same app, or keep a separate app registration for interactive vs automated use.

Method 2 — Client ID + Certificate Path (PFX file)

Fully non-interactive. Authenticates as the application, not a user. Suitable for scheduled tasks, Azure Automation runbooks, and CI/CD pipelines.

PowerShell 7 — Connect-PnPOnline with PFX certificate
# Store the password securely — never hardcode in scripts
# In production, retrieve from Azure Key Vault or an environment variable
$pfxPassword = ConvertTo-SecureString `
    -String    "YourSecureP@ssword!" `
    -AsPlainText -Force

Connect-PnPOnline `
    -Url                 "https://contoso.sharepoint.com" `
    -ClientId            "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
    -CertificatePath     "C:\Certs\PnPSharePointApp.pfx" `
    -CertificatePassword $pfxPassword `
    -Tenant              "contoso.onmicrosoft.com"

# Verify
$web = Get-PnPWeb
Write-Host "Connected as app to: $($web.Title)"

Method 3 — Client ID + Thumbprint (Windows cert store)

Also non-interactive. The certificate must already be installed in the current user's or local machine's certificate store. No PFX file is needed at runtime — the private key stays in the protected cert store.

PowerShell 7 — Connect-PnPOnline with Thumbprint
# The thumbprint was displayed in Step 6 when you created the certificate
# You can also retrieve it from the Entra portal (Certificates & secrets tab)
# or from PowerShell:
$thumbprint = (Get-ChildItem Cert:\CurrentUser\My |
    Where-Object { $_.Subject -like "*PnPSharePointApp*" }).Thumbprint

Connect-PnPOnline `
    -Url        "https://contoso.sharepoint.com" `
    -ClientId   "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
    -Thumbprint $thumbprint `
    -Tenant     "contoso.onmicrosoft.com"

# Verify
$web = Get-PnPWeb
Write-Host "Connected as app to: $($web.Title)"

Thumbprint on server deployments: When deploying to a new server, import the PFX into the Windows certificate store first, then use the thumbprint. Import command: Import-PfxCertificate -FilePath "C:\Certs\PnPSharePointApp.pfx" -CertStoreLocation "Cert:\LocalMachine\My" -Password $pfxPassword. After import, the PFX file is no longer needed and can be deleted.

Step 9: Verify the Connection

Run a few PnP cmdlets to confirm everything is working correctly.

PowerShell 7 — verify PnP connection
# Basic connectivity check
$web = Get-PnPWeb
Write-Host "Site title  : $($web.Title)"
Write-Host "Site URL    : $($web.Url)"
Write-Host "Site template: $($web.WebTemplate)"

# Check connection details (shows which ClientId and auth method is active)
Get-PnPConnection

# List all site collections (requires SharePoint Admin role for the app)
# Use -Limit All to retrieve more than the default 200 results
Get-PnPTenantSite -Limit All | Select-Object Title, Url, Template | Format-Table -AutoSize

# List libraries on the current site
Get-PnPList | Where-Object { $_.BaseType -eq "DocumentLibrary" } | Select-Object Title, DefaultViewUrl

Access denied after connecting? A successful Connect-PnPOnline does not guarantee that the app has permission to the specific site. If you see "Access denied" after connecting, check that: (1) admin consent was granted for the API permissions in Step 5, and (2) if using Sites.Selected, the app has been explicitly granted access to that site using Grant-PnPAzureADAppSitePermission.

Connecting to the SharePoint Admin Center

Some cmdlets (like Get-PnPTenantSite, Set-PnPTenant, New-PnPSite) require connecting to the admin URL, not a regular site URL:

PowerShell 7 — connect to SharePoint admin center
# Admin center URL format: https://[tenant]-admin.sharepoint.com
$pfxPassword = ConvertTo-SecureString -String "YourSecureP@ssword!" -AsPlainText -Force

Connect-PnPOnline `
    -Url                 "https://contoso-admin.sharepoint.com" `
    -ClientId            "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
    -CertificatePath     "C:\Certs\PnPSharePointApp.pfx" `
    -CertificatePassword $pfxPassword `
    -Tenant              "contoso.onmicrosoft.com"

# Now tenant-level cmdlets are available
Get-PnPTenantSite -Limit All
New-PnPSite -Type TeamSite -Title "Project Alpha" -Alias "project-alpha"

Security Best Practices

  • 1
    Use a dedicated service account for interactive connections

    Never use a named user's account (e.g. vipin@contoso.com) for automation. Create a dedicated service account (e.g. svc-pnp@contoso.com), assign it the minimum SharePoint Admin role it needs, and assign the PnP app to that account. This decouples the automation from any individual's employment status.

  • 2
    Never store PFX files or passwords in source control

    Add *.pfx to your .gitignore and treat the PFX like a password. In production, load the password from Azure Key Vault, an environment variable, or a secrets management system — never hardcode it in a script file.

  • 3
    Set calendar reminders for certificate renewal

    Create a 2-year certificate and set a reminder 60 days before expiry. Generate a new certificate, upload the new .cer to Entra (you can have multiple active certs simultaneously), update your scripts or vault with the new thumbprint/PFX, confirm the new cert works, then delete the old one from Entra. Never let the certificate expire — it causes silent auth failures in scheduled scripts.

  • 4
    Prefer Sites.Selected over Sites.FullControl.All in production

    Granting Sites.FullControl.All means the app can access every site in your tenant. For production apps that only need to access specific sites, use Sites.Selected and grant granular access per site. This limits the blast radius if the app's credentials are compromised.

  • 5
    Enable conditional access for your app

    In the Entra admin center, apply conditional access policies to restrict which IP addresses or named locations can authenticate as your PnP app. This prevents use of the certificate from outside your corporate network even if the PFX is stolen.

Troubleshooting Common Errors

  • AADSTS70011: The provided request must include a 'response_type' input parameter Cause: Wrong redirect URI or the app is not configured for the requested auth flow. Fix: For interactive auth, ensure the Redirect URI is set to https://login.microsoftonline.com/common/oauth2/nativeclient under Public client platform in Entra › Authentication.
  • AADSTS700027: Client assertion contains an invalid signature Cause: The certificate in the app registration does not match the PFX or thumbprint being used. Fix: Verify that the thumbprint shown in Entra (Certificates & secrets tab) exactly matches $cert.Thumbprint from PowerShell. If you recreated the cert, re-upload the new .cer to Entra.
  • Invoke-WebRequest: The remote name could not be resolved: 'login.microsoftonline.com' Cause: No internet connectivity or DNS resolution failure on the server. Fix: Confirm the server can reach login.microsoftonline.com and graph.microsoft.com. Check proxy settings — PnP respects the $env:HTTPS_PROXY environment variable.
  • Access denied. You do not have permission to perform this action or access this resource. Cause: Connection succeeded but the app lacks permission on that site. Fix: (1) Confirm admin consent was granted in Entra for the required permissions. (2) If using Sites.Selected, run Grant-PnPAzureADAppSitePermission to explicitly add the app to the site. (3) Check if the site has unique permissions that exclude the app's identity.
  • The term 'Connect-PnPOnline' is not recognized as the name of a cmdlet Cause: PnP.PowerShell is not installed in the current PowerShell session or version. Fix: Run Get-Module PnP.PowerShell -ListAvailable to check. If not found, run Install-Module PnP.PowerShell -Scope CurrentUser. Ensure you are running PowerShell 7 (pwsh), not Windows PowerShell 5.1 (powershell).
  • Cannot find certificate with thumbprint 'ABC123...' in certificate store Cause: The -Thumbprint method cannot find the cert in the store. Fix: Run Get-ChildItem Cert:\CurrentUser\My to list available certs. If the cert is missing, import the PFX: Import-PfxCertificate -FilePath "path.pfx" -CertStoreLocation "Cert:\CurrentUser\My" -Password $pfxPassword. On a server, use Cert:\LocalMachine\My instead.
📄 Register an application in Microsoft Entra — learn.microsoft.com
📄 PnP PowerShell authentication guide — pnp.github.io

Need help setting up PnP PowerShell automation for your tenant?

OceanCloud builds and maintains SharePoint automation scripts for organisations of all sizes — from simple scheduled reports to complex multi-tenant governance pipelines. We handle the Entra app setup, certificate management, and Power Automate integration so your team doesn't have to.

Talk to a SharePoint Automation Expert