Wednesday, October 7, 2026

Teams Meeting Policy

Teams Meeting Policy: Auto-Recording, Transcription, Downloads and Never-Expiring Recordings


What You Will Configure

RequirementAdmin controlWhere
Allow meeting recording-AllowCloudRecording $trueTeams admin center or PowerShell
Allow transcription-AllowTranscription $trueTeams admin center or PowerShell
Record and transcribe automatically-AutoRecording EnabledPowerShell only
Recordings never expire-NewMeetingRecordingExpirationDays -1PowerShell only (or turn off "Recordings automatically expire" in the Teams admin center)
Participants can download recordings and transcriptsNo per-user admin policyMeeting options (organizer) + tenant download settings

Key Facts

TopicBehaviour
AutoRecording policyOnly shows the Record and transcribe automatically toggle in Meeting options
Default toggle stateOff for meetings, On for webinars and town halls
Force auto-record on every meetingNeeds a Teams Premium meeting template or a sensitivity label
Custom meeting templatesCreated in the Teams admin center only; no PowerShell cmdlet
Default recording expiry120 days
Expiry range1–99,999 days, or -1 (never) in PowerShell
Expiry change scopeApplies to new recordings only; existing recordings keep their expiry date
Recording storageOrganizer's OneDrive (non-channel meetings), channel SharePoint site (channel meetings)
Default download rightsOrganizers and co-organizers can download; other invitees can only view
"Who has access to the recording and transcript"Per-meeting option; needs Teams Premium or Copilot license
Tenant-wide download blockSet-SPOTenant -BlockDownloadFileTypePolicy with TeamsMeetingRecording overrides everything
Policy propagationCan take several hours after assignment
Legal retentionUse Microsoft Purview retention policies, not the expiry setting

Prerequisites

ItemDetail
RolesTeams Administrator; SharePoint Administrator (download check); Graph User.Read.All (license check)
ModulesMicrosoftTeams, Microsoft.Online.SharePoint.PowerShell, Microsoft.Graph.Users
Best practiceNever edit the Global policy; duplicate it and assign the copy to the target users

Implementation Steps

  1. Connect to Microsoft Teams PowerShell.
  2. Duplicate the Global meeting policy into a new custom policy.
  3. Enable recording, transcription and auto-recording, and set expiry to never.
  4. Assign the custom policy to the user.
  5. Verify the policy values and the assignment.
  6. Check the tenant does not block downloads of meeting recordings.
  7. Check for a Teams Premium license if auto-record must be enforced.
  8. Test with a short meeting after the policy has propagated.

Complete Script

<#
.SYNOPSIS
    Copies the Global Teams meeting policy into a custom policy, enables auto-recording,
    transcription and never-expiring recordings, assigns it to a user and runs checks.
.NOTES
    Replace the placeholder values before running.
#>

# ---------------- Variables ----------------
$sourcePolicy = "Global"
$newPolicy    = "MeetingPolicy-AutoRecord-NoExpiry"
$userUpn      = "user@contoso.com"
$spoAdminUrl  = "https://contoso-admin.sharepoint.com"

# ---------------- 1. Connect ----------------
Connect-MicrosoftTeams

# ---------------- 2. Copy Global into a new policy ----------------
$source = Get-CsTeamsMeetingPolicy -Identity $sourcePolicy -ErrorAction Stop

if (Get-CsTeamsMeetingPolicy -Identity $newPolicy -ErrorAction SilentlyContinue) {
    Write-Host "Policy '$newPolicy' already exists - syncing settings from '$sourcePolicy'." -ForegroundColor Yellow
} else {
    New-CsTeamsMeetingPolicy -Identity $newPolicy -Description "Copy of Global + auto-record + no recording expiry" -ErrorAction Stop | Out-Null
    Write-Host "Created policy '$newPolicy'." -ForegroundColor Green
}

$target = Get-CsTeamsMeetingPolicy -Identity $newPolicy
$skip   = @('Identity', 'Description', 'Tenant', 'Force', 'InMemory')
$common = [System.Management.Automation.PSCmdlet]::CommonParameters + [System.Management.Automation.PSCmdlet]::OptionalCommonParameters
$params = (Get-Command Set-CsTeamsMeetingPolicy).Parameters.Keys | Where-Object { $_ -notin $skip -and $_ -notin $common }

$copied = 0
$failed = @()
foreach ($p in $params) {
    if ($source.PSObject.Properties.Name -notcontains $p) { continue }
    if ("$($source.$p)" -eq "$($target.$p)") { continue }
    try {
        $splat = @{ Identity = $newPolicy; $p = $source.$p; ErrorAction = 'Stop' }
        Set-CsTeamsMeetingPolicy @splat
        $copied++
    } catch {
        $failed += [pscustomobject]@{ Setting = $p; Value = "$($source.$p)"; Error = $_.Exception.Message }
    }
}
Write-Host "Copied $copied setting(s) from '$sourcePolicy'." -ForegroundColor Green
if ($failed) {
    Write-Host "Settings not copied (usually retired parameters):" -ForegroundColor Yellow
    $failed | Format-Table -AutoSize
} else {
    Write-Host "No copy failures." -ForegroundColor Green
}

# ---------------- 3. Apply required settings ----------------
Set-CsTeamsMeetingPolicy -Identity $newPolicy `
    -AllowCloudRecording $true `
    -AllowTranscription $true `
    -AutoRecording Enabled `
    -NewMeetingRecordingExpirationDays -1

# ---------------- 4. Assign to the user ----------------
Grant-CsTeamsMeetingPolicy -Identity $userUpn -PolicyName $newPolicy

# ---------------- 5. Verify ----------------
Get-CsTeamsMeetingPolicy -Identity $newPolicy |
    Select-Object Identity, AllowCloudRecording, AllowTranscription, AutoRecording, NewMeetingRecordingExpirationDays
Get-CsUserPolicyAssignment -Identity $userUpn -PolicyType TeamsMeetingPolicy

# ---------------- 6. Check tenant-wide recording download block ----------------
Connect-SPOService -Url $spoAdminUrl
$spo = Get-SPOTenant | Select-Object BlockDownloadFileTypePolicy, BlockDownloadFileTypeIds
if ($spo.BlockDownloadFileTypePolicy -and ($spo.BlockDownloadFileTypeIds -contains "TeamsMeetingRecording")) {
    Write-Host "Recording downloads are BLOCKED tenant-wide - participants cannot download." -ForegroundColor Red
} else {
    Write-Host "No tenant-wide block on meeting recording downloads." -ForegroundColor Green
}

# ---------------- 7. Check Teams Premium (needed to enforce auto-record) ----------------
Connect-MgGraph -Scopes "User.Read.All" -NoWelcome
$premium = Get-MgUserLicenseDetail -UserId $userUpn |
    ForEach-Object { $_.ServicePlans } |
    Where-Object { $_.ServicePlanName -like "TEAMSPRO*" -and $_.ProvisioningStatus -eq "Success" }
if ($premium) {
    Write-Host "Teams Premium found - a locked meeting template can enforce auto-record." -ForegroundColor Green
} else {
    Write-Host "No Teams Premium - organizer must switch the toggle on per meeting." -ForegroundColor Yellow
}

# ---------------- Rollback (run only if needed) ----------------
# Grant-CsTeamsMeetingPolicy -Identity $userUpn -PolicyName $null   # revert user to Global
# Remove-CsTeamsMeetingPolicy -Identity $newPolicy                   # delete custom policy

Organizer Actions After Policy Applies

GoalAction
Auto-record a meetingMeeting options → Record and transcribe automatically → On (per meeting or per recurring series)
Let attendees downloadAdd them as co-organizers, or use Who has access to the recording and transcript (Premium/Copilot)
Share with othersShare the .mp4 / transcript from OneDrive with the required permission
Change expiry on an old recordingOpen the file details in OneDrive and edit the expiration date

Validation Checklist

  • AllowCloudRecording = True
  • AllowTranscription = True
  • AutoRecording = Enabled
  • NewMeetingRecordingExpirationDays = -1
  • User assigned the custom policy
  • Toggle visible in Meeting options of a new meeting
  • Test meeting records and transcribes automatically
  • Recording shows no expiration date
  • Participant can download recording and transcript

Troubleshooting

SymptomCauseFix
Toggle not visiblePolicy not propagated or not assignedWait a few hours; sign out and in; check Get-CsUserPolicyAssignment
Toggle visible but meeting not recordedToggle is Off by defaultOrganizer switches it On per meeting
Auto-record cannot be enforcedNo Teams PremiumUse a sensitivity label or license Teams Premium
Recording still shows an expiry dateRecording created before the changeEdit expiry on the file manually
Participants cannot downloadDefault view-only rights or tenant download blockMake co-organizers / share file / review BlockDownloadFileTypePolicy
A setting failed to copyRetired or read-only parameterReview and ignore if not relevant

References

Wednesday, September 30, 2026

Pin a SharePoint Site to the Microsoft Teams Left Rail (No Code)

This is a no-code, step-by-step guide. You package a SharePoint page as a Teams app, upload it, and pin it for everyone in your organisation.

Why do this?

Most organisations already have an intranet on SharePoint, yet people spend their day in Microsoft Teams. Putting the intranet one click away on the Teams app bar (the icons down the left side) raises traffic to the intranet and saves people switching windows.

In this guide you build a small Teams app with one personal tab that loads a SharePoint page. You then upload the app in the Teams admin center and pin it with an app setup policy, so every user sees the icon without installing anything.

What you end up with: an "Intranet" icon in the Teams left rail. Clicking it opens the SharePoint site home page inside Teams, already signed in.

Prerequisites

RequirementDetails
Admin roleTeams Administrator (or Global Administrator) to upload custom apps and edit setup policies
SharePoint siteA modern SharePoint site the target users can already read
Custom apps allowedOrg-wide app settings must allow custom apps to be uploaded
ToolsAny text editor and a zip tool. No Visual Studio, SPFx, or Azure resources are needed

How it works

PieceRole
Teams app manifestDescribes the app: its name, its icons and one static (personal) tab
teamslogon.aspxA SharePoint page that signs the user in through Teams, then redirects to the page given in the dest parameter
webApplicationInfoPoints at the SharePoint Online resource (00000003-0000-0ff1-ce00-000000000000) so single sign-on works in the Teams desktop client
App setup policyPins the app to the app bar for everyone the policy applies to

Step 1 – Find the SharePoint site and its home page

  1. Open the SharePoint admin center and go to Sites > Active sites.
  2. Search for the site and note its URL (in this example, /sites/work).
Step 1a – Locate the site in SharePoint admin center > Active sites

Step 1a – Locate the site in SharePoint admin center > Active sites

  1. Open the site and confirm which page is the home page. For most modern sites it is SitePages/Home.aspx.
Step 1b – The SharePoint site home page that will appear in Teams

Step 1b – The SharePoint site home page that will appear in Teams

Tip: to confirm the home page, open the browser developer console on the site and run fetch('/sites/work/_api/web/WelcomePage',{headers:{accept:'application/json'}}).then(r=>r.json()).

Step 2 – Create the Teams app package

A Teams app package is a .zip file that holds three files, all at the root of the zip with no folders:

FileSpecification
manifest.jsonApp definition (shown below)
color.png192 × 192 px full-colour icon
outline.png32 × 32 px icon, white on a transparent background

Here is the manifest. Replace contoso with your tenant name, /sites/work with your site path, and <new-guid> with a new GUID (in PowerShell, run [guid]::NewGuid()).

{
  "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
  "manifestVersion": "1.17",
  "version": "1.0.0",
  "id": "<new-guid>",
  "developer": {
    "name": "IT",
    "websiteUrl": "https://contoso.sharepoint.com/sites/work",
    "privacyUrl": "https://contoso.sharepoint.com/sites/work",
    "termsOfUseUrl": "https://contoso.sharepoint.com/sites/work"
  },
  "name": { "short": "Intranet", "full": "Intranet (SharePoint)" },
  "description": {
    "short": "Company intranet SharePoint site in Teams",
    "full": "Opens the intranet SharePoint site home page inside Microsoft Teams."
  },
  "icons": { "color": "color.png", "outline": "outline.png" },
  "accentColor": "#0078D4",
  "staticTabs": [{
    "entityId": "intranethome",
    "name": "Intranet",
    "contentUrl": "https://contoso.sharepoint.com/_layouts/15/teamslogon.aspx?spfx=true&dest=https://contoso.sharepoint.com/sites/work/SitePages/Home.aspx",
    "websiteUrl": "https://contoso.sharepoint.com/sites/work/SitePages/Home.aspx",
    "scopes": ["personal"]
  }],
  "permissions": ["identity"],
  "validDomains": [
    "contoso.sharepoint.com",
    "*.login.microsoftonline.com",
    "*.sharepoint.com",
    "spoprod-a.akamaihd.net",
    "resourceseng.blob.core.windows.net"
  ],
  "webApplicationInfo": {
    "id": "00000003-0000-0ff1-ce00-000000000000",
    "resource": "https://contoso.sharepoint.com"
  }
}

The key line is contentUrl. It points at /_layouts/15/teamslogon.aspx?spfx=true&dest=<page URL>. Microsoft documents this pattern for SharePoint content hosted in Teams. It signs the user in to SharePoint through Teams single sign-on, so they don't get a blank frame or a second sign-in prompt.

Zip the three files (select the files themselves, not the folder that contains them). Name the zip something like IntranetTeamsApp.zip.

Step 3 – Upload the app in the Teams admin center

  1. Go to Teams admin center > Teams apps > Manage apps.
Step 3a – Teams admin center > Teams apps > Manage apps

Step 3a – Teams admin center > Teams apps > Manage apps

  1. Open the Actions menu and choose Upload new app.
Step 3b – Actions > Upload new app

Step 3b – Actions > Upload new app

  1. Select Upload and choose your .zip file.
Step 3c – The Upload a custom app dialog

Step 3c – The Upload a custom app dialog

  1. When New app added appears, select this link to open the app.
Step 3d – The app was uploaded

Step 3d – The app was uploaded

  1. Check the app details. Available to should read Everyone (org-wide default). If the app shows as Blocked, select Allow.
Step 3e – The app's details page, showing it available to everyone

Step 3e – The app's details page, showing it available to everyone

Step 4 – Pin the app with an app setup policy

  1. Go to Teams apps > Setup policies and open Global (Org-wide default). To reach only a pilot group, create a custom policy instead and assign it to that group.
Step 4a – The App setup policies page

Step 4a – The App setup policies page

  1. Scroll to Pinned apps.
Step 4b – Settings for the Global (Org-wide default) policy

Step 4b – Settings for the Global (Org-wide default) policy

  1. Select + Add apps.
Step 4c – Pinned apps > Add apps

Step 4c – Pinned apps > Add apps

  1. Search for the app name, hover over it, and choose Select.
Step 4d – Search for the custom app in the Add pinned apps pane

Step 4d – Search for the custom app in the Add pinned apps pane

  1. Check that it appears under Apps to add, then select Add.
Step 4e – The app is queued under Apps to add

Step 4e – The app is queued under Apps to add

  1. The app now appears in the App bar list. Use Move up or Move down, or drag the handle, to change its position.
Step 4f – The Intranet app in the pinned App bar list

Step 4f – The Intranet app in the pinned App bar list

  1. Select Save, then Confirm in the warning that changes to the Global policy affect the whole organisation.
Step 4g – Confirm the change to the Global policy

Step 4g – Confirm the change to the Global policy

Step 5 – Test it in Teams

Open Teams on the web or on the desktop. The new icon appears in the left app bar. Click it and the SharePoint home page loads inside Teams, signed in and fully usable. Users can read news and open links, and page authors can even use Edit.

Step 5 – The SharePoint site running inside Teams from the pinned icon

Step 5 – The SharePoint site running inside Teams from the pinned icon

Rollout timing: Microsoft states that setup policy changes can take a few hours to take effect. Teams on the web usually picks them up first. On desktop, signing out and back in speeds things up.

Troubleshooting

SymptomCause / fix
"This app cannot be found" right after uploadingThe app catalog hasn't finished propagating. Wait a few minutes and reload Teams
Blank white frame in the tabcontentUrl doesn't use teamslogon.aspx, or the domain is missing from validDomains
Repeated sign-in prompts on desktopwebApplicationInfo is missing or has the wrong resource. It must be your own tenant's https://<tenant>.sharepoint.com
App is missing from the Add pinned apps searchThe app is blocked or not yet available. Allow it under Manage apps, and check that the tab scope is personal
Icon doesn't appear on mobileMobile clients need at least two pinned apps in the policy
You need to change the target pageEdit contentUrl and websiteUrl, raise version (for example to 1.0.1), re-zip, then use Manage apps > app > Upload file

Alternatives worth knowing

  • Viva Connections: Microsoft's supported way to bring the SharePoint home site into Teams, with a dashboard, feed and resources. Choose it when the page is your organisation's home site.
  • Website tab in a channel: quick for one team, but it appears only inside that channel and can't be pinned to the app bar.
  • SPFx personal app: choose this when you need custom code rather than an existing SharePoint page.

Summary

A three-file Teams app package, one upload and one setup-policy edit put any SharePoint site in the Teams left rail for the whole organisation. You don't write code or host anything, and single sign-on works on web and desktop. Repeat the steps with a new GUID and name to add more sites.

References

Sunday, September 27, 2026

Connect to SharePoint Online with Connect-PnPOnline

Goal: Starting from a fresh Windows PC, finish by running one PowerShell command that reads the title of a SharePoint site.
Who it's for: Anyone. You don't need PowerShell experience, just copy, paste and follow the screenshots.


At a glance

ItemDetails
⏱️ Time needed15–20 minutes (first time)
💻 ComputerWindows 10 / 11
👤 AccountA Microsoft 365 work account with access to the SharePoint site
🔑 One-time admin helpSomeone with Global Administrator (or an admin role that can grant consent) for Step 3
🎯 End result(Get-PnPWeb).Title prints your site title

The workflow

Workflow: install PowerShell 7, install PnP.PowerShell, register the Entra ID app, connect, read the site title
Workflow: install PowerShell 7, install PnP.PowerShell, register the Entra ID app, connect, read the site title

Key terms (30-second glossary)

TermWhat it means in plain English
PowerShell 7The modern command window from Microsoft. Not the same as the built-in "Windows PowerShell 5.1".
PnP.PowerShellA free add-on (module) with 700+ SharePoint and Microsoft 365 commands.
Connect-PnPOnlineThe command that signs you in to a SharePoint site. Every other PnP command needs it first.
Entra ID app registrationAn "ID card" for PnP PowerShell in your tenant. Since September 2024, every tenant needs its own.
Client IDThe ID number of that app registration. You pass it to Connect-PnPOnline.
Admin consentA one-time approval by an admin that allows the app to access SharePoint.

Step 1: Install PowerShell 7

Why not the built-in PowerShell?

Windows PowerShell 5.1PowerShell 7
Comes with Windows✅ Yes❌ Install once
Runs PnP.PowerShell 3.x❌ No✅ Yes (needs 7.4.0 or later)
Window title"Windows PowerShell""PowerShell" / "PowerShell 7"
Start commandpowershellpwsh

If you run PnP commands in the old one, you get this error:

Windows PowerShell 5.1 does not recognise Connect-PnPOnline
Windows PowerShell 5.1 does not recognise Connect-PnPOnline

Install it

#Action
1Open Start → type PowerShell → open Windows PowerShell (any window works for this step)
2Check the latest version: winget search --id Microsoft.PowerShell --exact
3Install: winget install --id Microsoft.PowerShell --source winget
4Close the window. Open Start → type PowerShell 7 → open it
5Confirm the version: $PSVersionTable.PSVersion → Major must be 7
winget search --id Microsoft.PowerShell --exact
winget install --id Microsoft.PowerShell --source winget
winget search and install PowerShell 7
winget search and install PowerShell 7
pwsh
$PSVersionTable.PSVersion
Switch to PowerShell 7 and confirm the version
Switch to PowerShell 7 and confirm the version

💡 Tip: Already inside Windows PowerShell? Just type pwsh and press Enter to switch to PowerShell 7 in the same window.


Step 2: Install the PnP.PowerShell module

Run this inside PowerShell 7:

Install-Module PnP.PowerShell -Scope CurrentUser -Force
Get-Module PnP.PowerShell -ListAvailable | Select-Object Name, Version
PartMeaning
-Scope CurrentUserInstalls for you only, so no admin rights are needed
-ForceSkips the "untrusted repository" prompt
Get-Module ... -ListAvailableProves it installed and shows the version
PnP.PowerShell installed
PnP.PowerShell installed

⚠️ Common mistake: Installing the module from Windows PowerShell 5.1 puts it in a different folder. PowerShell 7 then says Connect-PnPOnline is not recognized. Always install from PowerShell 7.


Step 3: Create the Entra ID app registration (one time per tenant)

Pick one option.

Option A: Azure portalOption B: One command
Best forVisual learners, full controlSpeed
Clicks~151 command + sign-in
NeedsAdmin who can grant consentSame

Option A: Azure portal (click-by-click)

A1. Open App registrations

#Action
1Go to https://portal.azure.com and sign in
2In the top search bar type App registrations → open it
3Click + New registration
App registrations → New registration
App registrations → New registration

A2. Fill in the registration form

FieldValue
NamePnP.PowerShell (any name works)
Supported account typesSingle tenant only (default)
Redirect URI → platformPublic client/native (mobile & desktop)
Redirect URI → valuehttp://localhost

Click Register.

Register an application form
Register an application form

A3. Copy the Client ID

On the Overview page, copy Application (client) ID and save it in Notepad. You'll need it in Step 4. The Directory (tenant) ID is here too.

Overview page: Application (client) ID
Overview page: Application (client) ID

A4. Add the SharePoint permission

#Action
1Left menu → API permissions → + Add a permission
2Choose SharePoint
3Choose Delegated permissions (you sign in as yourself)
4Search AllSites → tick the permission you need (see table below)
5Click Add permissions
SharePoint → Delegated → AllSites permissions
SharePoint → Delegated → AllSites permissions
PermissionWhat you can doAdmin consent?
AllSites.ReadRead sites, lists, items (enough for this guide)No
AllSites.WriteRead + write list itemsNo
AllSites.ManageRead + write items and listsNo
AllSites.FullControlEverything, including site settingsYes

🔒 Least privilege: Start with AllSites.Read. Add more only when you need it.

A5. Grant admin consent

Click ✓ Grant admin consent for <your org> → Yes. The Status column turns green: Granted for …

API permissions with admin consent granted
API permissions with admin consent granted

A6. Check the Authentication settings

WhereWhat to check
Authentication → Redirect URI configurationMobile and desktop applications → http://localhost
Authentication → SettingsAllow public client flows = Enabled (needed for -DeviceLogin)
Redirect URI http://localhost
Redirect URI http://localhost
Allow public client flows enabled
Allow public client flows enabled

Option B: One command (PnP does it for you)

Run in PowerShell 7 and sign in with an admin account when the browser opens:

Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "PnP.PowerShell" -Tenant "contoso.onmicrosoft.com"
What it does automatically
Creates the app registration✅
Adds redirect URI + default permissions✅
Prompts you to grant consent✅
Prints the Client ID at the end✅ Copy it

💡 Add -SharePointDelegatePermissions "AllSites.Read" to choose the exact permission.
Add -DeviceLogin if no browser pops up (sign in with a code instead).


Step 4: Connect to the SharePoint site

Replace the two values, then run:

Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/pub" -ClientId "<your-client-id>" -Interactive
ParameterValue to use
-UrlFull site address from your browser, e.g. https://contoso.sharepoint.com/sites/pub
-ClientIdThe Application (client) ID from Step 3
-InteractiveOpens a Microsoft sign-in window → sign in with your work account

No output = success. PowerShell just returns to the prompt.

No browser pop-up? Use a device code instead

Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/pub" -ClientId "<your-client-id>" -Tenant "contoso.onmicrosoft.com" -DeviceLogin
#Action
1PowerShell shows a code, e.g. ABCD1234
2Open https://microsoft.com/devicelogin in any browser
3Enter the code → sign in → return to PowerShell

Step 5: Read the site title 🎯

(Get-PnPWeb).Title
Connect-PnPOnline and site title output
Connect-PnPOnline and site title output

✅ You did it. You're connected, and PowerShell printed the site title.

Bonus: a few more read-only commands to try

CommandShows
Get-PnPWeb -Includes Created | Select Title, Url, CreatedTitle, address, creation date
Get-PnPList | Select Title, ItemCountAll lists and libraries with item counts
Get-PnPSiteCollectionAdminSite collection admins
Disconnect-PnPOnlineSigns out of the session

Save it as a reusable script

Save as Get-SiteTitle.ps1, then run .\Get-SiteTitle.ps1 from PowerShell 7:

param(
    [string]$SiteUrl  = "https://contoso.sharepoint.com/sites/pub",
    [string]$ClientId = "<your-client-id>",
    [string]$Tenant   = "contoso.onmicrosoft.com",
    [switch]$DeviceLogin
)

if (-not (Get-Module -ListAvailable PnP.PowerShell)) {
    Install-Module PnP.PowerShell -Scope CurrentUser -Force
}
Import-Module PnP.PowerShell

if ($DeviceLogin) {
    Connect-PnPOnline -Url $SiteUrl -ClientId $ClientId -Tenant $Tenant -DeviceLogin
} else {
    Connect-PnPOnline -Url $SiteUrl -ClientId $ClientId -Interactive
}

$web = Get-PnPWeb -Includes Title, Url, Created
Write-Host "Title   : $($web.Title)"
Write-Host "Url     : $($web.Url)"
Write-Host "Created : $($web.Created)"

Disconnect-PnPOnline

💡 Skip typing -ClientId every time. Save it once as an environment variable, then open a new PowerShell 7 window:

[Environment]::SetEnvironmentVariable("ENTRAID_APP_ID", "<your-client-id>", "User")

Troubleshooting

SymptomCauseFix
Connect-PnPOnline is not recognizedYou're in Windows PowerShell 5.1, or the module was installed thereType pwsh, then re-run Install-Module PnP.PowerShell -Scope CurrentUser -Force
pwsh is not recognized right after installPATH not refreshedClose and reopen the window, or open PowerShell 7 from Start
AADSTS700016: Application ... not foundWrong Client ID or wrong tenantCopy the Client ID again from Overview
AADSTS65001: ... has not consentedAdmin consent missingAPI permissions → Grant admin consent
AADSTS7000218: ... client_assertion or client_secretPublic client flows disabled (device login)Authentication → Settings → Allow public client flows = Enabled
403 Forbidden / Access deniedYour account has no access to that siteAsk the site owner to add you as a member/visitor
running scripts is disabled on this systemExecution policySet-ExecutionPolicy -Scope CurrentUser RemoteSigned
Sign-in window never appearsPop-up blocked / remote sessionUse -DeviceLogin

Cheat sheet

TaskCommand
Install PowerShell 7winget install --id Microsoft.PowerShell --source winget
Switch to PowerShell 7pwsh
Check version$PSVersionTable.PSVersion
Install PnPInstall-Module PnP.PowerShell -Scope CurrentUser -Force
Update PnPUpdate-Module PnP.PowerShell
Create the app (one command)Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "PnP.PowerShell" -Tenant "contoso.onmicrosoft.com"
Connect (browser)Connect-PnPOnline -Url "<site-url>" -ClientId "<client-id>" -Interactive
Connect (device code)Connect-PnPOnline -Url "<site-url>" -ClientId "<client-id>" -Tenant "<tenant>.onmicrosoft.com" -DeviceLogin
Site title(Get-PnPWeb).Title
Sign outDisconnect-PnPOnline

References

SourceLink
Install PowerShell 7 on Windows (Microsoft Learn)https://learn.microsoft.com/powershell/scripting/install/install-powershell-on-windows
PnP PowerShell: Installationhttps://pnp.github.io/powershell/articles/installation.html
PnP PowerShell: Register an Entra ID applicationhttps://pnp.github.io/powershell/articles/registerapplication.html
Connect-PnPOnline referencehttps://pnp.github.io/powershell/cmdlets/Connect-PnPOnline.html
Grant tenant-wide admin consent (Microsoft Learn)https://learn.microsoft.com/entra/identity/enterprise-apps/grant-admin-consent

Tags: #SharePointOnline #PnPPowerShell #PowerShell7 #EntraID #Microsoft365 #M365Admin

Featured Post

Teams Meeting Policy

Teams Meeting Policy: Auto-Recording, Transcription, Downloads and Never-Expiring Recordings What You Will Configure Requirement Admin contr...

Popular posts