Skip to content
This repository has been archived by the owner on Jan 19, 2021. It is now read-only.

Commit

Permalink
Merge branch 'AllowScopesWithCredentials' of https://github.com/KoenZ…
Browse files Browse the repository at this point in the history
…omers/PnP-PowerShell into TeamsCmdlets
  • Loading branch information
erwinvanhunen committed Jun 29, 2020
2 parents 34e5ee7 + 56e199d commit b10af25
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 49 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## [3.23.2007.0] (not yet released)

### Added
- Added connection option to `Connect-PnPOnline` taking `-Scopes` and `-Credentials` to allow setting up a delegated permission token for use with Microsoft Graph and the Office 365 Management API. See [this wiki page](https://github.com/pnp/PnP-PowerShell/wiki/Connect-options#connect-using-scopes-and-credentials) for more details. [PR #2746](https://github.com/pnp/PnP-PowerShell/pull/2746)
- Added Get-PnPTeamsTeam, Get-PnPTeamsChannel, Add-PnPTeamsChannel, Remove-PnPTeamsChannel cmdlets

### Changed
Expand Down
38 changes: 22 additions & 16 deletions Commands/Base/ConnectOnline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,33 @@ namespace SharePointPnP.PowerShell.Commands.Base
Code = "PS:> Connect-PnPOnline -Scopes \"Mail.Read\",\"Files.Read\",\"ActivityFeed.Read\"",
Remarks = "Connects to Azure Active Directory interactively and gets an OAuth 2.0 Access Token to consume the resources of the declared permission scopes. It will utilize the Azure Active Directory enterprise application named PnP.PowerShell with application id bb0c5778-9d5c-41ea-a4a8-8cd417b3ab71 registered by the PnP PowerShell team. If you want to connect using your own Azure Active Directory application registration, use one of the Connect-PnPOnline cmdlets using a -ClientId attribute instead and pre-assign the required permissions/scopes/roles in your application registration in Azure Active Directory. The available permission scopes for Microsoft Graph are defined at the following URL: https://docs.microsoft.com/graph/permissions-reference . If the requested scope(s) have been used with this connect cmdlet before, they will not be asked for consent again. You can request scopes from different APIs in one Connect, i.e. from Microsoft Graph and the Microsoft Office Management API. It will ask you to authenticate for each of the APIs you have listed scopes for.",
SortOrder = 15)]
[CmdletExample(
Code = "PS:> Connect-PnPOnline -Scopes \"Mail.Read\",\"Files.Read\",\"ActivityFeed.Read\" -Credentials (New-Object System.Management.Automation.PSCredential (\"[email protected]\", (ConvertTo-SecureString \"password\" -AsPlainText -Force)))",
Remarks = "Connects to Azure Active Directory using delegated permissions and gets an OAuth 2.0 Access Token to consume the resources of the declared permission scopes. It will utilize the Azure Active Directory enterprise application named PnP.PowerShell with application id bb0c5778-9d5c-41ea-a4a8-8cd417b3ab71 registered by the PnP PowerShell team. If you want to connect using your own Azure Active Directory application registration, use one of the Connect-PnPOnline cmdlets using a -ClientId attribute instead and pre-assign the required permissions/scopes/roles in your application registration in Azure Active Directory. The available permission scopes for Microsoft Graph are defined at the following URL: https://docs.microsoft.com/graph/permissions-reference . If the requested scope(s) have been used with this connect cmdlet before, they will not be asked for consent again. You can request scopes from different APIs in one Connect, i.e. from Microsoft Graph and the Microsoft Office Management API. You must have logged on interactively with the same scopes at least once without using -Credentials to allow for the permission grant dialog to show and allow constent for the user account you would like to use.",
SortOrder = 16)]
#endif
#endif
#if !ONPREMISES
[CmdletExample(
Code = "PS:> Connect-PnPOnline -ClientId '<id>' -ClientSecret '<secret>' -AADDomain 'contoso.onmicrosoft.com'",
Remarks = "Connects to the Microsoft Graph API using application permissions via an app's declared permission scopes. See https://github.com/SharePoint/PnP-PowerShell/tree/master/Samples/Graph.ConnectUsingAppPermissions for a sample on how to get started.",
SortOrder = 16)]
SortOrder = 17)]
[CmdletExample(
Code = "PS:> Connect-PnPOnline -Url https://contoso.sharepoint.com -ClientId '<id>' -Tenant 'contoso.onmicrosoft.com' -CertificatePath c:\\absolute-path\\to\\pnp.pfx -CertificatePassword <if needed>",
Remarks = "Connects to SharePoint using app-only tokens via an app's declared permission scopes. See https://github.com/SharePoint/PnP-PowerShell/tree/master/Samples/SharePoint.ConnectUsingAppPermissions for a sample on how to get started.",
SortOrder = 17)]
SortOrder = 18)]
[CmdletExample(
Code = "PS:> Connect-PnPOnline -Url https://contoso.sharepoint.com -ClientId '<id>' -Tenant 'contoso.onmicrosoft.com' -Thumbprint 34CFAA860E5FB8C44335A38A097C1E41EEA206AA",
Remarks = "Connects to SharePoint using app-only tokens via an app's declared permission scopes. See https://github.com/SharePoint/PnP-PowerShell/tree/master/Samples/SharePoint.ConnectUsingAppPermissions for a sample on how to get started.",
SortOrder = 18)]
SortOrder = 19)]
[CmdletExample(
Code = "PS:> Connect-PnPOnline -Url https://contoso.sharepoint.com -ClientId '<id>' -Tenant 'contoso.onmicrosoft.com' -PEMCertificate <PEM string> -PEMPrivateKey <PEM string> -CertificatePassword <if needed>",
Remarks = "Connects to SharePoint using app-only tokens via an app's declared permission scopes. See https://github.com/SharePoint/PnP-PowerShell/tree/master/Samples/SharePoint.ConnectUsingAppPermissions for a sample on how to get started.",
SortOrder = 19)]
SortOrder = 20)]
[CmdletExample(
Code = "PS:> Connect-PnPOnline -Url https://contoso.sharepoint.com -ClientId '<id>' -Tenant 'contoso.onmicrosoft.com' -Certificate <X509Certificate2>",
Remarks = "Connects to SharePoint using app-only auth in combination with a certificate. See https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread#using-this-principal-in-your-powershell-script-using-the-pnp-sites-core-library for a sample on how to get started.",
SortOrder = 20)]
SortOrder = 21)]
#endif
#if ONPREMISES
[CmdletExample(
Expand Down Expand Up @@ -174,7 +178,7 @@ public class ConnectOnline : BasePSCmdlet
private const string ParameterSet_DEVICELOGIN = "PnP O365 Management Shell / DeviceLogin";
private const string ParameterSet_GRAPHDEVICELOGIN = "PnP Office 365 Management Shell to the Microsoft Graph";
#if !NETSTANDARD2_1
private const string ParameterSet_GRAPHWITHSCOPE = "Microsoft Graph using Scopes";
private const string ParameterSet_AADWITHSCOPE = "Azure Active Directory using Scopes";
#endif
private const string ParameterSet_GRAPHWITHAAD = "Microsoft Graph using Azure Active Directory";
private const string SPOManagementClientId = "9bc3ab49-b65d-410a-85ad-de819febfddc";
Expand Down Expand Up @@ -239,6 +243,7 @@ public class ConnectOnline : BasePSCmdlet

[Parameter(Mandatory = false, ParameterSetName = ParameterSet_MAIN, HelpMessage = "Credentials of the user to connect with. Either specify a PSCredential object or a string. In case of a string value a lookup will be done to the Generic Credentials section of the Windows Credentials in the Windows Credential Manager for the correct credentials.")]
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_ADFSCREDENTIALS, HelpMessage = "Credentials of the user to connect with. Either specify a PSCredential object or a string. In case of a string value a lookup will be done to the Generic Credentials section of the Windows Credentials in the Windows Credential Manager for the correct credentials.")]
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_AADWITHSCOPE, HelpMessage = "Credentials of the user to connect with. Either specify a PSCredential object or a string. In case of a string value a lookup will be done to the Generic Credentials section of the Windows Credentials in the Windows Credential Manager for the correct credentials.")]
public CredentialPipeBind Credentials;

[Parameter(Mandatory = false, ParameterSetName = ParameterSet_MAIN, HelpMessage = "If you want to connect with the current user credentials")]
Expand Down Expand Up @@ -518,8 +523,8 @@ public class ConnectOnline : BasePSCmdlet
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYCLIENTIDCLIENTSECRETURL, HelpMessage = "The Azure environment to use for authentication, the defaults to 'Production' which is the main Azure environment.")]
public AzureEnvironment AzureEnvironment = AzureEnvironment.Production;

#if !NETSTANDARD2_1
[Parameter(Mandatory = true, ParameterSetName = ParameterSet_GRAPHWITHSCOPE, HelpMessage = "The array of permission scopes for the Microsoft Graph API.")]
#if !NETSTANDARD2_1
[Parameter(Mandatory = true, ParameterSetName = ParameterSet_AADWITHSCOPE, HelpMessage = "The array of permission scopes to request from Azure Active Directory")]
public string[] Scopes;
#endif

Expand Down Expand Up @@ -585,7 +590,7 @@ public class ConnectOnline : BasePSCmdlet
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADCER, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting to a SharePoint farm using self signed certificates or using a certificate authority not trusted by this machine.")]
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_GRAPHWITHAAD, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting through a proxy to the Microsoft Graph API which has SSL interception enabled.")]
#if !NETSTANDARD2_1
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_GRAPHWITHSCOPE, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting through a proxy to the Microsoft Graph API which has SSL interception enabled.")]
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_AADWITHSCOPE, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting through a proxy to the Microsoft Graph API which has SSL interception enabled.")]
#endif
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_GRAPHDEVICELOGIN, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting through a proxy to the Microsoft Graph API which has SSL interception enabled.")]
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_SPOMANAGEMENT, HelpMessage = "Ignores any SSL errors. To be used i.e. when connecting to a SharePoint farm using self signed certificates or using a certificate authority not trusted by this machine.")]
Expand Down Expand Up @@ -697,8 +702,8 @@ protected void Connect()
break;

#if !NETSTANDARD2_1
case ParameterSet_GRAPHWITHSCOPE:
connection = ConnectGraphWithScope();
case ParameterSet_AADWITHSCOPE:
connection = ConnectAadWithScope(credentials);
break;
#endif
case ParameterSet_ACCESSTOKEN:
Expand Down Expand Up @@ -1082,10 +1087,11 @@ private PnPConnection ConnectAppOnlyAadCer()
}

/// <summary>
/// Connect using the parameter set GRAPHWITHSCOPE
/// Connect using the parameter set AADWITHSCOPE
/// </summary>
/// <param name="credentials">Credentials to authenticate with for delegated access or NULL for application permissions</param>
/// <returns>PnPConnection based on the parameters provided in the parameter set</returns>
private PnPConnection ConnectGraphWithScope()
private PnPConnection ConnectAadWithScope(PSCredential credentials)
{
#if !ONPREMISES
#if !NETSTANDARD2_1
Expand All @@ -1100,16 +1106,16 @@ private PnPConnection ConnectGraphWithScope()
// If we have Office 365 scopes, get a token for those first
if (officeManagementApiScopes.Length > 0)
{
var officeManagementApiToken = OfficeManagementApiToken.AcquireTokenInteractive(MSALPnPPowerShellClientId, officeManagementApiScopes);
var officeManagementApiToken = credentials == null ? OfficeManagementApiToken.AcquireApplicationTokenInteractive(MSALPnPPowerShellClientId, officeManagementApiScopes) : OfficeManagementApiToken.AcquireDelegatedTokenWithCredentials(MSALPnPPowerShellClientId, graphScopes, credentials.UserName, credentials.Password);
connection = PnPConnection.GetConnectionWithToken(officeManagementApiToken, TokenAudience.OfficeManagementApi, Host, InitializationType.InteractiveLogin, disableTelemetry: NoTelemetry.ToBool());
}

// If we have Graph scopes, get a token for it
if (graphScopes.Length > 0)
{
var graphToken = GraphToken.AcquireTokenInteractive(MSALPnPPowerShellClientId, graphScopes);
var graphToken = credentials == null ? GraphToken.AcquireApplicationTokenInteractive(MSALPnPPowerShellClientId, graphScopes) : GraphToken.AcquireDelegatedTokenWithCredentials(MSALPnPPowerShellClientId, graphScopes, credentials.UserName, credentials.Password);

// If there's a connection already, add the Graph token to it, otherwise set up a new connection with it
// If there's a connection already, add the AAD token to it, otherwise set up a new connection with it
if (connection != null)
{
connection.AddToken(TokenAudience.MicrosoftGraph, graphToken);
Expand Down
8 changes: 4 additions & 4 deletions Commands/Base/PnPConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,11 @@ internal GenericToken TryGetToken(TokenAudience tokenAudience, string[] orRoles
{
if (Certificate != null)
{
token = GraphToken.AcquireToken(Tenant, ClientId, Certificate);
token = GraphToken.AcquireApplicationToken(Tenant, ClientId, Certificate);
}
else if (ClientSecret != null)
{
token = GraphToken.AcquireToken(Tenant, ClientId, ClientSecret);
token = GraphToken.AcquireApplicationToken(Tenant, ClientId, ClientSecret);
}
}
break;
Expand All @@ -213,11 +213,11 @@ internal GenericToken TryGetToken(TokenAudience tokenAudience, string[] orRoles
{
if (Certificate != null)
{
token = OfficeManagementApiToken.AcquireToken(Tenant, ClientId, Certificate);
token = OfficeManagementApiToken.AcquireApplicationToken(Tenant, ClientId, Certificate);
}
else if (ClientSecret != null)
{
token = OfficeManagementApiToken.AcquireToken(Tenant, ClientId, ClientSecret);
token = OfficeManagementApiToken.AcquireApplicationToken(Tenant, ClientId, ClientSecret);
}
}
break;
Expand Down
36 changes: 22 additions & 14 deletions Commands/Graph/SetUnifiedGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ namespace SharePointPnP.PowerShell.Commands.Graph
SortOrder = 2)]
[CmdletExample(
Code = @"PS:> Set-PnPUnifiedGroup -Identity $group -GroupLogoPath "".\MyLogo.png""",
Remarks = "Sets a specific Microsoft 365 Group logo.",
Remarks = "Sets a specific Microsoft 365 Group logo",
SortOrder = 3)]
[CmdletExample(
Code = @"PS:> Set-PnPUnifiedGroup -Identity $group -IsPrivate:$false",
Remarks = "Sets a group to be Public if previously Private.",
Remarks = "Sets a group to be Public if previously Private",
SortOrder = 4)]
[CmdletExample(
Code = @"PS:> Set-PnPUnifiedGroup -Identity $group -Owners [email protected]",
Remarks = "Sets [email protected] as owner of the group.",
Remarks = "Sets [email protected] as owner of the group",
SortOrder = 5)]
[CmdletMicrosoftGraphApiPermission(MicrosoftGraphApiPermission.Group_ReadWrite_All)]
public class SetUnifiedGroup : PnPGraphCmdlet
Expand All @@ -56,7 +56,7 @@ public class SetUnifiedGroup : PnPGraphCmdlet
[Parameter(Mandatory = false, HelpMessage = "Makes the group private when selected")]
public SwitchParameter IsPrivate;

[Parameter(Mandatory = false, HelpMessage = "The path to the logo file of to set")]
[Parameter(Mandatory = false, HelpMessage = "The path to the logo file of to set. Logo must be at least 48 pixels wide and may be at most 4 MB in size. Requires Site.ReadWrite.All permissions.")]
public string GroupLogoPath;

[Parameter(Mandatory = false, HelpMessage = "Creates a Microsoft Teams team associated with created group")]
Expand Down Expand Up @@ -88,16 +88,24 @@ protected override void ExecuteCmdlet()
{
isPrivateGroup = IsPrivate.ToBool();
}
UnifiedGroupsUtility.UpdateUnifiedGroup(
groupId: group.GroupId,
accessToken: AccessToken,
displayName: DisplayName,
description: Description,
owners: Owners,
members: Members,
groupLogo: groupLogoStream,
isPrivate: isPrivateGroup,
createTeam: CreateTeam);
try
{
UnifiedGroupsUtility.UpdateUnifiedGroup(
groupId: group.GroupId,
accessToken: AccessToken,
displayName: DisplayName,
description: Description,
owners: Owners,
members: Members,
groupLogo: groupLogoStream,
isPrivate: isPrivateGroup,
createTeam: CreateTeam);
}
catch(Exception e)
{
while (e.InnerException != null) e = e.InnerException;
WriteError(new ErrorRecord(e, "GROUPUPDATEFAILED", ErrorCategory.InvalidOperation, this));
}
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion Commands/ManagementApi/GetManagementApiAccessToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class GetManagementApiAccessToken : BasePSCmdlet

protected override void ExecuteCmdlet()
{
var officeManagementApiToken = OfficeManagementApiToken.AcquireToken(TenantId, ClientId, ClientSecret);
var officeManagementApiToken = OfficeManagementApiToken.AcquireApplicationToken(TenantId, ClientId, ClientSecret);
WriteObject(officeManagementApiToken.AccessToken);
}
}
Expand Down
Loading

0 comments on commit b10af25

Please sign in to comment.