From b8f4fae96070ad51187b878d59d90046d4b7419b Mon Sep 17 00:00:00 2001 From: Koen Zomers Date: Thu, 13 Jun 2024 15:56:48 +0200 Subject: [PATCH] Fixing update done through #3958 (#4013) * Adding additional information, removing alias as it works inversed from the original cmdlet name, only kept the Graph name and ditched the Exchange Online name * Added code to distinguish the type of token being used (Delegate vs AppOnly) and using it to show a warning if properties are being set with the wrong token type * Renaming method as this makes more sense --------- Co-authored-by: Gautam Sheth --- documentation/Set-PnPMicrosoft365Group.md | 34 +++++++++++-------- src/Commands/Base/TokenHandling.cs | 30 ++++++++++++++++ src/Commands/Enums/IdType.cs | 23 +++++++++++++ .../SetMicrosoft365Group.cs | 19 ++++++++--- 4 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 src/Commands/Enums/IdType.cs diff --git a/documentation/Set-PnPMicrosoft365Group.md b/documentation/Set-PnPMicrosoft365Group.md index ac215e160..db0556187 100644 --- a/documentation/Set-PnPMicrosoft365Group.md +++ b/documentation/Set-PnPMicrosoft365Group.md @@ -73,6 +73,23 @@ Sets the sensitivity label of the group ## PARAMETERS +### -AllowExternalSenders +Allows configuring if the Microsoft 365 Group should accept e-mail from senders outside of the organisation (true) or if both internal as well as external senders can send e-mail to the e-mail address of the Microsoft 365 group (false). + +In the Exchange Online PowerShell cmdlet this would be the RequireSenderAuthenticationEnabled property, but then inversed, so when that would be set to $true it would not accept e-mail from outside the organisation and when set to $false it would. + +This property can only be set using a Delegated logon, not with an Application logon. + +```yaml +Type: Boolean +Parameter Sets: (All) +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -AutoSubscribeNewMembers The AutoSubscribeNewMembers switch specifies whether to automatically subscribe new members that are added to the Microsoft 365 Group to conversations and calendar events. Only users that are added to the group after you enable this setting are automatically subscribed to the group. @@ -81,6 +98,8 @@ If you don't want to subscribe new members to conversations and calendar events, Note: This property is evaluated only when you add internal members from your organization. Guest user accounts are always subscribed when added as a member. +This property can only be set using a Delegated logon, not with an Application logon. + ```yaml Type: SwitchParameter Parameter Sets: (All) @@ -246,21 +265,6 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -RequireSenderAuthenticationEnabled -Allows configuring if the Microsoft 365 Group should accept e-mail from senders outside of the organisation (false) or if both internal as well as external senders can send e-mail to the e-mail address of the Microsoft 365 group (true). - -Alias: AllowExternalSenders - -```yaml -Type: Boolean -Parameter Sets: (All) -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - ### -SensitivityLabels The Sensitivity label to be set to the Microsoft 365 Group. To retrieve the sensitivity label Ids you can use [Get-PnPAvailableSensitivityLabel](Get-PnPAvailableSensitivityLabel.md). diff --git a/src/Commands/Base/TokenHandling.cs b/src/Commands/Base/TokenHandling.cs index 70c4f0cbc..46fabbd8b 100644 --- a/src/Commands/Base/TokenHandling.cs +++ b/src/Commands/Base/TokenHandling.cs @@ -13,6 +13,36 @@ namespace PnP.PowerShell.Commands.Base { internal static class TokenHandler { + /// + /// Returns the type of oAuth JWT token being passed in (Delegate/AppOnly) + /// + /// The oAuth JWT token + /// Enum indicating the type of oAuth JWT token + internal static Enums.IdType RetrieveTokenType(string token) + { + var decodedToken = new JwtSecurityToken(token); + + // The idType is stored in the token as a claim + var idType = decodedToken.Claims.FirstOrDefault(c => c.Type == "idtyp"); + + // Check if the token contains an idType + if (idType == null) return Enums.IdType.Unknown; + + // Parse the idType to the corresponding enum value + return idType.Value.ToLowerInvariant() switch + { + "user" => Enums.IdType.Delegate, + "app" => Enums.IdType.Application, + _ => Enums.IdType.Unknown + }; + } + + /// + /// Extracts the oAuth JWT token to compare the permissions in it (roles) with the required permissions for the cmdlet provided through an attribute + /// + /// The cmdlet that will be executed. Used to check for the permissions attribute. + /// The oAuth JWT token that needs to be validated for its roles + /// Thrown if the permissions set through the permissions attribute do not match the roles in the JWT token internal static void ValidateTokenForPermissions(Type cmdletType, string token) { string[] requiredScopes = null; diff --git a/src/Commands/Enums/IdType.cs b/src/Commands/Enums/IdType.cs new file mode 100644 index 000000000..29a948e59 --- /dev/null +++ b/src/Commands/Enums/IdType.cs @@ -0,0 +1,23 @@ +namespace PnP.PowerShell.Commands.Enums +{ + /// + /// Possible IdType values inside an oAuth JWT token + /// + public enum IdType : short + { + /// + /// Unable to identify the token type + /// + Unknown, + + /// + /// IdType user, indicates a delegate token + /// + Delegate, + + /// + /// IdType app, indicates an application token + /// + Application + } +} diff --git a/src/Commands/Microsoft365Groups/SetMicrosoft365Group.cs b/src/Commands/Microsoft365Groups/SetMicrosoft365Group.cs index 977433ac9..d65a39278 100644 --- a/src/Commands/Microsoft365Groups/SetMicrosoft365Group.cs +++ b/src/Commands/Microsoft365Groups/SetMicrosoft365Group.cs @@ -54,9 +54,8 @@ public class SetMicrosoft365Group : PnPGraphCmdlet [Parameter(Mandatory = false)] public string MailNickname; - [Parameter(Mandatory = false)] - [Alias("AllowExternalSenders")] // This is the name used in Microsoft Graph while the name below is the one used within Exchange Online. They both are about the same feature. - public bool? RequireSenderAuthenticationEnabled; + [Parameter(Mandatory = false)] // This is the name used in Microsoft Graph while the name RequireSenderAuthenticationEnabled is the one used within Exchange Online, but there its inversed, so we cannot easily add it as an alias here. They both are about the same feature. + public bool? AllowExternalSenders; [Parameter(Mandatory = false)] public bool? AutoSubscribeNewMembers; @@ -103,14 +102,24 @@ protected override void ExecuteCmdlet() group = Microsoft365GroupsUtility.UpdateAsync(Connection, AccessToken, group).GetAwaiter().GetResult(); } - if (ParameterSpecified(nameof(RequireSenderAuthenticationEnabled)) && RequireSenderAuthenticationEnabled.HasValue) + if (ParameterSpecified(nameof(AllowExternalSenders)) && AllowExternalSenders.HasValue) { - group.AllowExternalSenders = RequireSenderAuthenticationEnabled.Value; + if(TokenHandler.RetrieveTokenType(AccessToken) != Enums.IdType.Delegate) + { + WriteWarning($"{nameof(AllowExternalSenders)} can only be used with a delegate token. You're currently connected through an application token."); + } + + group.AllowExternalSenders = AllowExternalSenders.Value; exchangeOnlinePropertiesChanged = true; } if (ParameterSpecified(nameof(AutoSubscribeNewMembers)) && AutoSubscribeNewMembers.HasValue) { + if (TokenHandler.RetrieveTokenType(AccessToken) != Enums.IdType.Delegate) + { + WriteWarning($"{nameof(AllowExternalSenders)} can only be used with a delegate token. You're currently connected through an application token."); + } + group.AutoSubscribeNewMembers = AutoSubscribeNewMembers.Value; exchangeOnlinePropertiesChanged = true; }