Many SharePoint Online sites belonging to Microsoft 365 Groups and Teams hold confidential information that you might not want to share with guest members. When Microsoft first supported guest users for Office 365 Groups (now Microsoft 365 Groups) through Azure B2B Collaboration, the focus was on allowing guests to collaborate with tenant users through email and shared documents. Over time, apps like Teams and Planner included support for Azure B2B Collaboration and increased the amount of data available to guests. The issue often encountered now is how to keep organizational secrets when using collaborative applications.
Controlling Guest Access
In the early days of Office 365 Groups, there wasn’t much that group members could do to protect confidential information from guests. The Groups membership model is very simple. All members enjoy equal access to group content. This led to the creation of many additional groups to segregate information which needed to stay internal with that which could be shared externally.
As time went by, Microsoft introduced functionality to help. A range of options now exist:
Groups and Teams blocked against guest access. By restricting membership to tenant users, you create conditions for unfettered internal discussions and sharing. The block is imposed by updating the properties of the group in Azure AD to prevent group owners adding guest members. An administrator can update the group properties manually or the group can inherit the block when a group owner or administrator assigns a sensitivity label with the appropriate restriction to the group.
Inside a group with guest members, sensitivity labels with encryption can stop specific members (guests and perhaps some internal users) accessing sensitive documents in the group’s document library. Access rights defined in the label control who can interact with documents, and if guests aren’t assigned rights in a label, they cannot open any document assigned that label. This method is an effective block, but it does go against the general philosophy that members share equal access to group resources. Remember that document metadata is not encrypted by sensitivity labels, so guests will be able to see document titles and authors.
Private channels avoid the need to create a new group by establishing barriers to sharing within teams. Private channels are restricted to a subset of team members, such as only tenant users. Anything shared in a private channel is only available to the members of the channel, including documents stored in the SharePoint Online team site for the channel.
Shared channelsdon’t use Azure B2B collaboration, so don’t use guest members to control external access. Instead, tenants agree to federate using Azure AD cross-tenant access settings to allow users to work together in shared channels, including access to the SharePoint Online team sites used by the channels (just like private channels, each shared channel has its own site). Sensitivity labels placed on confidential documents can limit access to tenant members of shared channels.
With these options in mind, the best approach might be to stop external users getting into sensitive groups in the first place. As noted above, this is possible by blocking the ability of owners to add guests to their groups and teams at a group level or (for shared channels) with cross-tenant access settings. Administrators can always add guest members to teams and groups if necessary.
Controlling Group Policy Settings
The Azure Active Directory policy for Groups holds settings for how Microsoft 365 Groups behave in a tenant. One of those settings is AllowToAddGuests, which is True if the tenant allows guests to be members of groups, and False if you want to block guests. This policy covers all groups and is managed through PowerShell. If the tenant policy allows guests users, the properties of individual groups can be amended to block access to those groups.
Use Sensitivity Labels
Today, sensitivity labels are the best method to controlling external access to confidential information. A sensitivity label can hold several container management settings, including guest access and the external sharing capability for SharePoint. Applying the label to a group forces the inheritance of the container settings, and if the settings dictate a block for guest access, the group’s AllowAddGuests property is set to #False. Sensitivity labels are available in the Office 365 E3 and E5 plans.
Using Classifications to Block Guest Access
If you choose not to use sensitivity labels, you can use group classifications to mark confidential groups and update the properties of those groups to block guest access. A classification is a text value defined in the ClassificationList setting of the Groups policy. Classifications are visual markers intended to convey to users what kind of information a group holds. They do not affect how a group or team works, nor does a classification protect content or place any restriction on how that content is used. Adding or updating a new classification or removing a classification from the list does not affect classifications placed on existing groups.
Let’s assume that you define a “Secret” classification to mark confidential groups (or teams). After classifying the secret groups (using PowerShell or client UIs), we can use PowerShell to scan for and block guest access for those groups.
The first step in the example code creates a set of groups classified as “Secret.” The code then loops through each group to discover whether group-specific policy settings are in place. If so, the code updates the settings to block guest access. Groups that don’t have a policy setting are controlled by the tenant policy, so the first step is to create policy settings for the group. We can then update the setting to block guest access.
$GroupTemplate = (Get-AzureADDirectorySettingTemplate | ? {$_.DisplayName -eq "Group.Unified.Guest"})
$Groups = (Get-UnifiedGroup -ResultSize Unlimited | Where {$_.Classification -eq "Secret"})
ForEach ($Group in $Groups) {
$GroupSettings = Get-AzureADObjectSetting -TargetType Groups -TargetObjectId $Group.ExternalDirectoryObjectId
if($GroupSettings) {
# Policy settings already exist for the group - so update them
$GroupSettings["AllowToAddGuests"] = $False
Set-AzureADObjectSetting -Id $GroupSettings.Id -DirectorySetting $GroupSettings -TargetObjectId $Group.ExternalDirectoryObjectId -TargetType Groups
Write-Host "External Guest accounts prohibited for" $Group.DisplayName
}
Else
{
# Settings do not exist for the group - so create a new settings object and update
$Settings = $GroupTemplate.CreateDirectorySetting()
$Settings["AllowToAddGuests"] = $False
New-AzureADObjectSetting -DirectorySetting $Settings -TargetObjectId $Group.ExternalDirectoryObjectId -TargetType Groups
Write-Host "External Guest accounts blocked for"$Group.DisplayName
}
}
To check that the block for guest access is in place, we can create a list of the groups blocked from having guest members. To do this, run the Get-UnifiedGroup cmdlet to check the AllowAddGuests property, which is $False if the group is blocked. For example, this command reports the display names and classification for all blocked groups. Remember that the block works for all clients that populate group membership, including Teams.
It’s critical to realize that applying a block on guests to a group does nothing to remove existing guests. If you want to eject existing guests, you need to do that separately.
Multiple Secret-Keeping Techniques
Multiple approaches are available to block guests from accessing content shared in Teams and Groups. The most fundamental is to block guest access completely, but if guests are already present, consider using Private channels in Teams or limit access to confidential documents with sensitivity labels and encryption.
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}