Saturday, 10 August 2019

Move SharePoint Online Sites using Powershell

You can now swap your SharePoint Online site with another site using the Invoke-SPOSiteSwap Powershell cmdlet. When the swap is initiated, the target site is moved to the archive location and the source site is moved to the target location.

To use this new cmdlet, you need to use SharePoint Online Powershell version 16.0.8812.1200 or later (Download Link: https://www.microsoft.com/en-us/download/details.aspx?id=35588). You can install the latest SPO Powershell by running below command.
Install-Module -Name Microsoft.Online.SharePoint.PowerShell -MinimumVersion "16.0.8812.1200"

Current Limitations :

  • The target site can only be the root site (https://tenant-name.sharepoint.com) or the search center (https://tenant-name.sharepoint.com/search.).
  • The source or target sites can't be associated with an Office 365 Group (team) or a hub site. If the site is a associated to a hub site, you can remove the association, perform the swap and then re enable the association.
  • If the target is the root site at https://tenant-name.sharepoint.com then the source site must be either a Team Site (STS#0), a Modern Team Site (STS#3), or a Communication Site (SITEPAGEPUBLISHING#0).
  • If the target is the search center site at https://tenant-name.sharepoint.com/search then the source site must be either a Search Center Site (SRCHCEN#0) or a Basic Search Center Site (SRCHCENTERLITE#0).
The below commands archives the existing root site and moves the CommunicationSite to root site.
Connect-SPOService -Url "https://<tenant-name>-admin.sharepoint.com"
$SourceSite = "https://<tenant-name>.sharepoint.com/sites/CommunicationSite"
$TargetSite = "https://<tenant-name>.sharepoint.com"
$AcrhiveSite = "https://<tenant-name>.sharepoint.com/sites/Archive"
Invoke-SPOSiteSwap -SourceUrl $SourceSite -TargetUrl $TargetSite -ArchiveUrl $AcrhiveSite
Note: Before proceed replace the parameter "<tenant-name>" with your tenant name in commands.

You can refer this post for more details.
Read More...

Monday, 5 August 2019

Get Microsoft Graph API Access Token using ClientID and ClientSecret

In some cases, apps or users might want to acquire Microsoft Graph access token by using the ClientID (Azure AD Application ID) and ClientSecret instead of providing their own credentials. In many cases, these are background services or automation jobs which require to authenticate a script without user interaction (Unattended Authentication). I would also recommend you to read the post Get access without a user.

Note: Assume that you have already registered an App in Azure AD through App Registration and you have the Client ID, Client Secret, and your Tenant Domain Name (or Tenant ID).

Required Parameters :

  • ClientID - AppId of your Azure AD Application.
  • ClientSecret - A secret code that you get from the registered app.
  • Tenant - Provide your tenant id or tenant domain name (ex: xxxxx.onmicrosoft.com). Refer this post to find your tenant id.

Get Access Token :

In the OAuth 2.0 client credentials grant flow, you can acquire an access token by sending a POST request to the /token identity platform endpoint with required parameters :
Http Method : POST
Endpoint URL : https://login.microsoftonline.com/Tenant/oauth2/v2.0/token
Content-Type : application/x-www-form-urlencoded
Body : scope=https://graph.microsoft.com/.default&grant_type=client_credentials&client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&client_secret=qWgdYAmab0YSkuL1qKv5bPX

Get Graph Access Token Using Powershell :

In Powershell, you can use the Invoke-RestMethod cmdlet to send the post request to the /token identity endpoint. Use the below commands after replacing your own values for ClientID, ClientSecret and TenantId.
#This is the ClientID (Application ID) of registered AzureAD App
$ClientID = "535fb089-9ff3-47b6-9bfb-4f1264799865"
#This is the key of the registered AzureAD app
$ClientSecret = "qWgdYAmab0YSkuL1qKv5bPX"
#This is your Office 365 Tenant Domain Name or Tenant Id
$TenantId = "m365xxxxx.onmicrosoft.com"
#$TenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$Body = @{client_id=$ClientID;client_secret=$ClientSecret;grant_type="client_credentials";scope="https://graph.microsoft.com/.default";}
$OAuthReq = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token -Body $Body
$TokenType = $OAuthReq.token_type
$AccessToken = $OAuthReq.access_token

Call Graph API Using Powershell :

The below command retrieves all the Azure AD user details by passing the acquired access token.
$apiUrl = "https://graph.microsoft.com/v1.0/users"
$users = Invoke-RestMethod -Headers @{Authorization = "Bearer $AccessToken"} -Uri $apiUrl -Method Get
Note : Before using the above end-point (https://graph.microsoft.com/v1.0/users), you should have added the Application permission User.Read.All (or User.ReadWrite.All) in your Azure AD app and you should have already provided Admin consent for your app.
Read More...

Fix - AADSTS90002: Tenant 'xxxxxx' not found. This may happen if there are no active subscriptions for the tenant.

Problem :

Recieived the below error when I try to get Microsoft Graph access token with my Azure AD Application using OAuth 2.0 client credentials grant flow.
Token identity endpoint URL : https://login.microsoftonline.com/xxxxxx/oauth2/v2.0/token

"error":"invalid_request","error_description":"AADSTS90002: Tenant 'xxxxxx' not found. This
may happen if there are no active subscriptions for the tenant. Check with your subscription administrator

Fix/Solution :

We need to provide either TenantID (Guid) or Tenant DomainName (ex: xxxxx.onmicrosoft.com) in token identity endpoint URL to get access token. But in my case, I have just provided tenant name alone instead of tenant domain name/tenantId, the problem solved after providing complete tenant domain name.
#Token endpoint URL with tenant domain name
https://login.microsoftonline.com/xxxxxx.onmicrosoft.com/oauth2/v2.0/token

#Token endpoint URL with tenant id (guid)
Token identity endpoint URL : https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/v2.0/token
To find your tenant id, you can refer this post : How to find your Office 365 Tenant ID
Read More...

How to find your Office 365 Tenant ID

Office 365 Tenant ID is a globally unique identifier (GUID) value for your Azure AD Tenant. You can find your Tenant ID in the following methods.

1. From Azure AD Portal

You can find your tenant ID in the Azure AD portal if you have Azure AD administrator privilege.
  • Log in to Azure AD Portal (https://portal.azure.com).
  • In the Azure portal, click Azure Active Directory in the left-side navigation box.
  • Under Manage, click Properties. You can retrieve the tenant id from the Directory ID box.
How to retrieve your Office 365 Tenant ID


2. Use Azure AD PowerShell

If you have already installed Azure AD Powershell V2 module, then you can get TenantId while running the Connect-AzureAD cmdlet.
PS C:\> Connect-AzureAD | FL

Account      : UserName@DomainName.onmicrosoft.com
Environment  : AzureCloud
Tenant       : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TenantId     : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TenantDomain : DomainName.onmicrosoft.com

3. Use Azure CLI

If you have Azure CLI setup, you can run the command "azure account show" to get your tenant id.
$ azure account show

data:    Name                        : Subscription Name
data:    ID                          : yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
data:    State                       : Enabled
data:    Tenant ID                   : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
data:    Is Default                  : true
data:    Environment                 : AzureCloud
data:    Has Certificate             : No
data:    Has Access Token            : Yes
data:    User name                   : kevin@xxxxxxx.onmicrosoft.com
You can fine tune the result by running below commands.
azure account show --json | jq -r '.[0].tenantId'

or 

az account show --subscription a... | jq -r '.tenantId'
az account list | jq -r '.[].tenantId'

Related Posts :

Read More...

Wednesday, 31 July 2019

Get all Public Folders and Permissions using Powershell

You can get a list of all public folders with the Exchange powershell cmdlet Get-PublicFolder and you can easily extract the permissions applied to the public folder by using the Get-PublicFolderClientPermission cmdlet.

Before proceed run the below commands to connect Exchange Online (EXO) powershell.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the below command to list all the public folders in your organization.
Get-PublicFolder -Recurse -ResultSize Unlimited
The below command returns the specific folder "Support" and all the sub-folders located under this folder.
Get-PublicFolder -Identity "\Support" -Recurse -ResultSize Unlimited
The below command list only first level sub-folders alone.
Get-PublicFolder -Identity "\Support" -GetChildren -ResultSize Unlimited
Run the below command to list the applied permissions in a public folder.
Get-PublicFolderClientPermission -Identity "\Support" | Select User, AccessRights
The below command returns all the folders and the permissions applied to each folder.
Get-PublicFolder -Recurse | Get-PublicFolderClientPermission | Select Identity, User, AccessRights

Export all Public Folder Permissions

The below commands fetch all folders and permissions applied to the folders and export the result to CSV file.
$Result=@()
$allFolders = Get-PublicFolder -Recurse -ResultSize Unlimited
$totalfolders = $allFolders.Count
$i = 1 
$allFolders | ForEach-Object {
$folder = $_
Write-Progress -activity "Processing $folder" -status "$i out of $totalfolders completed"
$folderPerms = Get-PublicFolderClientPermission -Identity $folder.Identity
$folderPerms | ForEach-Object {
$Result += New-Object PSObject -property @{ 
Folder = $folder.Identity
User = $_.User
Permissions = $_.AccessRights
}}
$i++
}
$Result | Select Folder, User, Permissions |
Export-CSV "C:\\PublicFolderPermissions.CSV" -NoTypeInformation -Encoding UTF8
Read More...

Thursday, 25 July 2019

Create a new public folder in Office 365 using Powershell

Public folders are used to share information and collaborate with other people in your organization. Once the admin enables public folders they are automatically shown in all users' Outlook client. The content is organized in a hierarchy which makes browsing very easier for users.

Things To Know Before Proceed :

  • Public folder content can include email messages, posts, documents, and eForms.
  • Public folder architecture uses specially designed mailboxes (Public folder mailbox) to store both the public folder hierarchy (folder structure) and the content.
  • Before creating a public folder, you must first create a public folder mailbox.
  • There are two types of public folder mailboxes: the primary hierarchy mailbox and secondary hierarchy mailboxes. Both types of mailboxes can contain content.
  • Primary hierarchy mailbox: The first public folder mailbox you create will be the primary hierarchy mailbox in your organization. This is the only mailbox containing a writable (read/write) copy of the public folder structure. The public folder hierarchy is copied to all other public folder mailboxes, but these will be read-only copies.
  • Secondary hierarchy mailboxes: Any additional public folder mailboxes you create will be secondary mailboxes. The secondary hierarchy mailboxes contain public folder content and a read-only copy of the public folder hierarchy.

Create a new public folder mailbox using Powershell

We can use the New-Mailbox cmdlet to create a public folder mailbox. Before proceed run the below commands to connect Exchange Online (EXO) powershell.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session
The first mailbox you create will be the primary hierarchy mailbox in your organization.
New-Mailbox -PublicFolder -Name "Master-PFM"
Once you created a public folder mailbox (primary), any additional public folder mailboxes you create will be secondary mailboxes.
New-Mailbox -PublicFolder -Name "PFM2"
You can get your primary public folder mailbox by running the following command.
Get-OrganizationConfig | Format-List RootPublicFolderMailbox

Create a new public folder using Powershell

Once you created required public folder mailbox, you can use the New-PublicFolder cmdlet to create a public folder. The below command creates the public folder Support in the root of the public folder.
New-PublicFolder -Name "Support"
The below command creates the public folder Product1 under the existing folder \Support.
New-PublicFolder -Name "Product1" -Path "\Support"
The below command creates the public folder FAQs under the existing folder \Support\Product1.
New-PublicFolder -Name "FAQs" -Path "\Support\Product1"
The below command creates the public folder Marketing in the specific mailbox PFM2.
New-PublicFolder -Name "Marketing" -Mailbox "PFM2"
Read More...

Tuesday, 23 July 2019

Fix : The query cannot be completed because the number of lookup columns exceeds the threshold limit

Problem

You might have received the below error when you use SharePoint Rest API to retrieve list items.
Code: Microsoft.SharePoint.SPQueryThrottledException
Message: "The query cannot be completed because the number of lookup columns it contains exceeds the lookup column threshold enforced by the administrator."
In my case I have received the same error for the following queries :
https://Tenant.sharepoint.com/sites/MySite/_api/web/lists/getByTitle('MyList')/items?$select=*

https://Tenant.sharepoint.com/sites/MySite/_api/web/lists/getByTitle('MyList')/items

Cause

As error message clearly indicates, this problem occurs since the problematic list contains lookup columns more than the List View Lookup Threshold limit. In SharePoint On-premises, the List View Lookup Threshold default limit is 8 and it can be changed on the Resource Throttling page in Central Administration. In SharePoint Online, this limit is 12 lookup columns and increasing the List View Threshold is not supported in SharePoint Online.

What columns are classified as Lookup columns

The following column types are classified as lookup columns: (Source: List view Lookup threshold uncovered)
  • Standard lookup columns
  • Managed metadata (single and multi-value)
  • People and group (single and multi-value)
  • Workflow status Created by (people and group)
  • Modified by (people and group)
Additionally following columns shows on list view also work as lookup columns : Name ( linked to Document) , Link (Edit to edit item) , Name ( linked to Document with edit menu), type ( icon linked to document).

Workaround

In Rest API, you can fix this problem by limiting the number columns to be returned using Select option. If you do not use the select option (or if you use select=*), then the rest query try to retrieve all fields, so you can limit the columns by providing only required columns in select option.
https://Tenant.sharepoint.com/sites/MySite/_api/web/lists/getByTitle('MyList')/items?$select=Title,Id
Note : Your select query should not include more than 12 (List View Lookup Threshold) lookup columns.

You can apply the same workaround if you face the issue in Microsoft Flow and PowerApps. For SharePoint views, you can just modify your view to list only required columns so that there will be no more than 12 lookup columns inside your view.
Read More...

Monday, 22 July 2019

Fix : Connect-SPOService : Could not authenticate to SharePoint Online using OAuth 2.0

Problem :

You might have received the below error when you try to connect SPO site using Connect-SPOService cmdlet.
Connect-SPOService : Could not authenticate to SharePoint Online https://TenantName.sharepoint.com/sites/SiteName
using OAuth 2.0
At line:1 char:1
+ Connect-SPOService -Url https://TenantName.sharepoint.com/sites/SiteName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Connect-SPOService], AuthenticationException
    + FullyQualifiedErrorId : Microsoft.Online.SharePoint.PowerShell.AuthenticationException,Microsoft.Online.SharePoi
   nt.PowerShell.ConnectSPOService

Fix/Soution:

In my case, I have provided my site URL as opposed to my SharePoint Admin Site URL. The URL parameter of Connect-SPOService cmdlet accepts only the URL of SharePoint Online Administration Center site. My problem solved after providing Admin site URL.
Connect-SPOService -url https://TenantName-admin.sharepoint.com
If you face the problem even with Admin site URL, then pass the -Credential parameter to bypass ADAL/Modern authentication and use legacy authentication.
$PSCred = Get-Credential
Connect-SPOService -url https://TenantName-admin.sharepoint.com -Credential $PSCred
Note: The legacy authentication will not work MFA enabled user account.

If you still face the issue, try to re-install the SPO Powershell module, reboot machine and check the case again.
Read More...