Azure AD – Create Dynamic Groups

In Azure AD you can create dynamic groups based on user or device properties. Users or devices can be automatically added or removed based on the group’s definition, so you don’t have to maintain the list of users in this group manually.

Whenever any property of a user or device changes, all dynamic group rules in your Azure AD tenant are reevaluated to determine if the user or device should still remain in the group. If a user or device satisfies a rule on a group, they are added as a member and If they no longer satisfy the rule, they are removed.

Manually adding or removing users from dynamic groups is not allowed.

Why use Dynamic Groups?

Simply put, dynamic groups have query-based memberships. This helps in maintaining group membership and application access depending on the query defined. For example, A dynamic group can be defined for all Marketing department users based on the value filled in the ‘department’ attribute. The conditions can also be combined. Following the same example above, a dynamic group of all Marketing department users from New York or a dynamic group with a list of users who report to a specific manager and need access to an application.

In a scenario where you are maintaining user access to applications based on the department, location, this comes in handy.

Note: You need Azure AD P1 and above to be able to create dynamic groups.

Dynamic Groups in Azure AD

Azure AD admin center provides a rule builder to create and/or update the dynamic group rules.

In the below steps I’ll create a dynamic group in my tenant with users who are in the Marketing department,

  1. Sign in to the Azure AD admin center portal (https://aad.portal.azure.com/) as global administrator
  2. Select Azure Active Directory –> Click on the Groups tab –> New group
  3. In New Group:
    • Select Security as the group type
    • Enter ‘Marketing Department Users’ as the name and description for the group
    • Change Membership type to Dynamic User
  4. Select Owners and in the Add Owners blade search for any desired owners. Click on the desired owners to add to the selection
  5. Click Select to close the Add Owners blade
  6. Click Add dynamic query in the Dynamic user members
Creating new group
  1. On the Dynamic membership rules blade:
    • In the Property field, click on the existing value and select department
    • The Operator field as Equals
    • Select the Value field and type ‘Marketing Department Users’
membership rules

Azure AD now provides an option to validate dynamic group rules. On the Validate rules tab, you can validate your dynamic rule against sample group members to confirm the rule is working as expected. This feature is now in public preview.

validate rules

The rule builder supports the construction of up to 5 expressions. You also need to use the text editor for setting operator precedence, and for writing more complex rules. The rule builder can’t be used to reproduce every rule.

‘Add Expression’ disabled after 5 expressions defined

If the rule builder doesn’t support the rule you want to create, the text box can be used. And below are some of the scenarios to use the text box,

  • Rule with more than 5 expressions
  • Direct reports rule
    • For the rule to work, make sure the Manager property is set correctly for users. If you are syncing from your on-premise AD, make sure the Manager attribute is filled
    • When the manager’s direct reports change in the future, the group’s membership is adjusted automatically
    • This rule can’t be combined with any other membership rules
  • Setting operator precedence
    • All operators are listed below in order of precedence from highest to lowest. Operators on same line are of equal precedence:
      1. -eq -ne -startsWith -notStartsWith -contains -notContains -match –notMatch -in -notIn
      2. -not
      3. -and
      4. -or
      5. -any -all
  • Rules with complex expressions
    • Property consists of a collection of values; specifically, multi-valued properties
      • assignedPlans
      • proxyAddresses
    • Expressions use the -any and -all operators
      • -any (At least one item in the collection matches the condition)
      • -all (All items in the collection match the condition)
    • Value of the expression can itself be one or more expressions

Constructing a membership rule

Three parts of a simple rule are Property, Operator and Value

Supported properties

Three types of properties that can be used to construct a rule are Boolean, String and String collection.

The following are the user properties that can be used to create a single expression.

Boolean

PropertiesAllowed valuesUsage
accountEnabledtrue falseuser.accountEnabled -eq true
dirSyncEnabledtrue falseuser.dirSyncEnabled -eq true

String

PropertiesAllowed valuesUsage
cityAny string value or null(user.city -eq “value”)
countryAny string value or null(user.country -eq “value”)
companyNameAny string value or null(user.companyName -eq “value”)
departmentAny string value or null(user.department -eq “value”)
displayNameAny string value(user.displayName -eq “value”)
employeeIdAny string value(user.employeeId -eq “value”)
(user.employeeId -ne null)
facsimileTelephoneNumberAny string value or null(user.facsimileTelephoneNumber -eq “value”)
givenNameAny string value or null(user.givenName -eq “value”)
jobTitleAny string value or null(user.jobTitle -eq “value”)
mailAny string value or null (SMTP address of the user)(user.mail -eq “value”)
mailNickNameAny string value (mail alias of the user)(user.mailNickName -eq “value”)
mobileAny string value or null(user.mobile -eq “value”)
objectIdGUID of the user object(user.objectId -eq “11111111-eeee-1111-aaaa-111111111111”)
onPremisesSecurityIdentifierOn-premises security identifier (SID) for users
who were synchronized from on-premises to the cloud.
(user.onPremisesSecurityIdentifier -eq “S-1-1-11-1111111111-1111111111-1111111111-1111111”)
passwordPoliciesNone DisableStrongPassword DisablePasswordExpiration DisablePasswordExpiration, DisableStrongPassword(user.passwordPolicies -eq “DisableStrongPassword”)
physicalDeliveryOfficeNameAny string value or null(user.physicalDeliveryOfficeName -eq “value”)
postalCodeAny string value or null(user.postalCode -eq “value”)
preferredLanguageISO 639-1 code(user.preferredLanguage -eq “en-US”)
sipProxyAddressAny string value or null(user.sipProxyAddress -eq “value”)
stateAny string value or null(user.state -eq “value”)
streetAddressAny string value or null(user.streetAddress -eq “value”)
surnameAny string value or null(user.surname -eq “value”)
telephoneNumberAny string value or null(user.telephoneNumber -eq “value”)
usageLocationTwo lettered country/region code(user.usageLocation -eq “US”)
userPrincipalNameAny string value(user.userPrincipalName -eq “alias@domain”)
userTypemember guest null(user.userType -eq “Member”)

String Collection

PropertiesAllowed valuesUsage
otherMailsAny string value(user.otherMails -contains “alias@domain”)
proxyAddressesSMTP: alias@domain smtp: alias@domain(user.proxyAddresses -contains “SMTP: alias@domain”)

Supported expression operators

Operators can be used with or without the hyphen (-) prefix. Contains operator does partial string matches but not item in a collection matches. Following are the supported operators and their syntax for a single expression,

SyntaxOperator
-neNot Equals
-eqEquals
-notStartsWithNot Starts With
-startsWithStarts With
-notContainsNot Contains
-containsContains
-notMatchNot Match
-matchMatch
-inIn
-notInNot In

Supported values

Values used in an expression can consist of several types, including:

  • Strings
  • Boolean = true or false
  • Numbers
  • Arrays = number array, string array

To specify a null value in a rule, you can use the null value. The -not operator can’t be used as a comparative operator for null.

Common rules in a typical environment

Below, I will go over some of the rules that are typically used in production environments

“Direct reports” rule

This rule supports only the manager’s direct reports. A group consisting of manager’s direct reports and their reports can’t be created.

Use below syntax. Object ID can be found in the user’s(in this case, the user who is the manager) profile in Azure AD.

Direct Reports for "{objectID_of_manager}"
Direct reports rule

“All users” rule

Include only members of your organization and exclude guest users.

(user.objectId -ne null) -and (user.userType -eq "Member")
all users

Device Rules

A rule to select devices objects can also be created for membership in a group. Both users and devices as group members is not allowed.

Below are the device attributes,

Device attributeValuesExample(s)
accountEnabledtrue false(device.accountEnabled -eq true)
displayNameany string value(device.displayName -eq “Bob iPhone”)
(device.deviceOSType -eq “iPad”) -or (device.deviceOSType -eq “iPhone”)
(device.deviceOSType -contains “AndroidEnterprise”)
(device.deviceOSType -eq “AndroidForWork”)
(device.deviceOSType -eq “Windows”)
deviceOSVersionany string value(device.deviceOSVersion -eq “9.1”)
(device.deviceOSVersion -startsWith “10.0.1”)
deviceCategorya valid device category name(device.deviceCategory -eq “BYOD”)
deviceManufacturerany string value(device.deviceManufacturer -eq “Samsung”)
deviceModelany string value(device.deviceModel -eq “iPad Air”)
deviceOwnershipPersonal, Company, Unknown(device.deviceOwnership -eq “Company”)
enrollmentProfileNameApple Device Enrollment Profile name, Android Enterprise Corporate-owned dedicated device Enrollment Profile name, or Windows Autopilot profile name(device.enrollmentProfileName -eq “DEP iPhones”)
isRootedtrue false(device.isRooted -eq true)
managementTypeMDM (for mobile devices)(device.managementType -eq “MDM”)
deviceIda valid Azure AD device ID(device.deviceId -eq “d4fe7726-5966-431c-b3b8-cddc8fdb717d”)
objectIda valid Azure AD object ID(device.objectId -eq “76ad43c9-32c5-45e8-a272-7b58b58f596d”)
devicePhysicalIdsany string value used by Autopilot, such as all Autopilot devices, OrderID, or PurchaseOrderID(device.devicePhysicalIDs -any _ -contains “[ZTDId]”) (device.devicePhysicalIds -any _ -eq “[OrderID]:179887111881”) (device.devicePhysicalIds -any _ -eq “[PurchaseOrderId]:76222342342”)
systemLabelsany string matching the Intune device property for tagging Modern Workplace devices(device.systemLabels -contains “M365Managed”)

Update an existing rule

  1. Sign in to the Azure AD admin center portal (https://aad.portal.azure.com/) as global administrator
  2. Select Azure Active Directory –> Click on the Groups tab –> All groups
  3. Select a group to open it
  4. On the profile page for the group, select Dynamic membership rules
update an existing rule
  1. After updating the rule, select Save

Dynamic Groups with PowerShell

To create dynamic groups

Use the New-AzureADMSGroup cmdlet,

New-AzureADMSGroup -DisplayName "Sales Department Users" -Description "Sales Department Users" -MailEnabled $false -MailNickname "SalesDepartmentUsers" -SecurityEnabled $true -GroupTypes "DynamicMembership" -MembershipRule "(User.department -eq ""Sales"")" -MembershipRuleProcessingState "On"
PowerShell: New-AzureADMSGroup

To update dynamic groups

Use the Set-AzureADMSGroup cmdlet,

Set-AzureADMSGroup -Id '23c2768b-6cef-4006-a052-d9b288b4d17c' -MembershipRule "(User.department -eq ""Sales"") and (user.city -eq ""Tulsa"")"
PowerShell: Set-AzureADMSGroup

Another interesting part I came across when I was exploring dynamic groups is, I was trying to create a dynamic group of administrators to whom I can assign an Azure AD role. And it turns out, the membership type for role-assignable groups must be Assigned and can’t be an dynamic group. This makes sense as automated population of groups could lead to unwanted access being granted.

Thank you for stopping by. ✌

Teams – Reports with PowerShell – Updated

It is important to know about the current state of your Teams rollout and this is one of those which can easily get out of control in a blink of an eye. I wanted to understand and determine the current Teams state in a tenant I manage and I had to create reports to present.

The portal does give a few options to export the data but I decided to take a look at the option the Teams PowerShell module offers. I spent some time on creating a script that will output these five reports,

  • All Teams data with Channel type, Channel count, Channel count with types, Teams member count and owners count
  • Teams users data with role information
  • Channel information for each Teams with Channel types
  • Channel user information with user information and role
  • Permissions on each Teams

This report can also be scheduled to run if you already use a mechanism to store your credentials securely and pass it on to your PS scripts.

I use the ImportExcel PowerShell module for this script,

Install-Module -Name ImportExcel

Before proceeding further, make sure you have the Teams PowerShell module installed. You’ll need to run this script with Teams Administrator role.

$TeamsCred = Get-Credential
Connect-MicrosoftTeams -credential $TeamsCred

$xlsxPath = ".\Teams-Report_$((Get-Date).ToString("MMddyyyy")).xlsx"

Get-Team | Select GroupId,DisplayName,MailNickName,Archived,Visibility,Description | foreach {
        $ID = $_.GroupId
        $TeamName = $_.DisplayName
        $NickName = $_.MailNickName
        $Archived = $_.Archived
        $visibility = $_.Visibility
        $Description = $_.Description
        $ch = Get-TeamChannel -GroupId $ID
        $ChannelCount = $ch.count
        $TeamUser = Get-TeamUser -GroupId $ID
        $TeamMemberCount = $TeamUser.Count
        $TeamOwnerCount = ($TeamUser | ?{$_.role -eq "owner"}).count
        $stdchannelCount = ($ch | ?{$_.MembershipType -eq "Standard"}).count
        $privchannelCount = ($ch | ?{$_.MembershipType -eq "Private"}).count

        [PSCustomObject]@{
                  'Teams Name'=$TeamName;
                  'Teams MailNickName'=$NickName;
                  'Teams Type'=$Visibility;
                  'Description'=$Description;
                  'Archived?'=$Archived;
                  'Channel Count'=$ChannelCount;
                  'Standard Channel Count'=$stdchannelCount;
                  'Private Channel Count'=$privchannelCount;
                  'Team Members Count'=$TeamMemberCount;
                  'Team Owners Count'=$TeamOwnerCount} | Export-Excel -Path $xlsxPath -WorksheetName "All Teams Report" -TableStyle Medium16 -AutoSize -Append
}

Get-Team | foreach {
    $ID = $_.GroupId;
    $TeamName = $_.DisplayName;
    $NickName = $_.MailNickName;
    Get-TeamUser -GroupId $ID | Select User,Name,Role |
    Foreach {
		[PSCustomObject]@{
			'Teams ID' = $ID;
			'Teams Name' = $TeamName;
			'Teams MailNickName' = $NickName;
                        'User UPN' = $_.User;
			'User DisplayName' = $_.Name;
			'Role' = $_.Role
		}
    }
} | Export-Excel -Path $xlsxPath -WorksheetName "Teams_users" -TableStyle Medium16 -AutoSize

Get-Team | Foreach {
    $ID = $_.GroupId;
    $TeamName = $_.DisplayName;
    $NickName = $_.MailNickName;
    Get-TeamChannel -GroupId $ID | Select Id, DisplayName, MembershipType |
    Foreach {
		[PSCustomObject]@{
			'Teams ID' = $ID;
			'Teams Name' = $TeamName;
			'Teams MailNickName' = $NickName;
			'Channel Name' = $_.DisplayName;
			'Channel Type' = $_.MembershipType
		}
	}
} | Export-Excel -Path $xlsxPath -WorksheetName "Channels" -TableStyle Medium16  -AutoSize

Get-Team | Foreach {
    $ID = $_.GroupId;
    $TeamName = $_.DisplayName;
    $NickName = $_.MailNickName;
    Get-TeamChannel -GroupId $ID | Select DisplayName | 
            Foreach {
            $chName = $_.DisplayName;
                Get-TeamChannelUser -GroupId $ID -DisplayName $chName | Select User,Name,Role |
                    Foreach {
		                [PSCustomObject]@{
			                'Teams Name' = $TeamName;
			                'Channel Name' = $chName;
                                        'User UPN' = $_.User;
                                        'User DisplayName' = $_.Name;
                                        'User Role' = $_.Role
		    }
        }
    }
} | Export-Excel -Path $xlsxPath -WorksheetName "Channel_Users" -TableStyle Medium16  -AutoSize

Get-Team | foreach {
   $nickName = $_.MailNickName
   Get-Team -MailNickName $nickName | Select -Property * |
	Foreach {
		[PSCustomObject]@{
			'Teams ID' = $_.GroupId;
			'Teams Display Name' = $_.DisplayName;
                        'Teams MailNickName' = $nickName;
                        'Giphy Allowed?' = $_.AllowGiphy;
                        'Giphy Content Rating' = $_.GiphyContentRating;
                        'Allow Stickers And Memes' = $_.AllowStickersAndMemes;
                        'Allow Custom Memes' = $_.AllowCustomMemes;
                        'Allow Guest to Create & Update Channels' = $_.AllowGuestCreateUpdateChannels;
                        'Allow Guest to Delete Channels' = $_.AllowGuestDeleteChannels;
                        'Allow Members to Create & Update Channels' = $_.AllowCreateUpdateChannels;
                        'Allow Members to Create Private Channels' = $_.AllowCreatePrivateChannels;
                        'Allow Members to Delete Channels' = $_.AllowDeleteChannels;
                        'Allow Members to Add & Remove Apps'= $_.AllowAddRemoveApps;
                        'Allow Members to Create Update Remove tabs' = $_.AllowCreateUpdateRemoveTabs;
                        'Allow Members to Create Update Remove Connectors' = $_.AllowCreateUpdateRemoveConnectors;
                        'Allow Members to Edit Messages' = $_.AllowUserEditMessages;
                        'Allow Members to Delete Messages' = $_.AllowUserDeleteMessages;
                        'Allow Owner to Delete Messages' = $_.AllowOwnerDeleteMessages;
                        'Allow Team Mentions' = $_.AllowTeamMentions;
                        'Allow Channel Mentions' = $_.AllowChannelMentions;
                        'Show In Teams Search & Suggestions' = $_.ShowInTeamsSearchAndSuggestions
		}
    }
} | Export-Excel -Path $xlsxPath -WorksheetName "Teams_permissions" -TableStyle Medium16 -AutoSize

Hope this script was helpful in determining the current state of your Teams deployment.

Thank you for stopping by. ✌

Azure AD – Implement Single Sign-On with ServiceNow

In this post I will go over the steps required to implement Azure AD SSO integration with ServiceNow. With this in place, it is easier to control access to your ServiceNow implementation and also allow your users to login with their domain credentials.

ServiceNow also supports user account provisioning which I will cover in a later post.

I’ve updated this post for ServiceNow San Diego version. The earlier versions may have different UI options but the steps behind the integration mostly remains the same.

High level implementation steps

In Azure AD add ServiceNow to Enterprise Applications

To configure this integration, first step is to add ServiceNow from the gallery to your list of managed SaaS apps. Below are the steps,

  1. Login to Azure AD Admin Center and click on the Enterprise applications tab
  2. To add new application, Click New application
  3. In the Browse Azure AD gallery section, enter ServiceNow in the search box
  4. Select ServiceNow and you can name it to differentiate from development to production instance with a prefix but in this scenario, I’ll leave it as default as in screenshot below. Click Create
  5. It takes a few seconds for the app to be added
Search ‘ServiceNow’
add ServiceNow by clicking ‘Create’

Configure Azure AD SSO

Below steps details how to enable SSO in Azure AD portal for the ServiceNow application,

  1. On the ServiceNow application page, select SAML-based Sign-on under the Manage section. Select SAML
  2. Select the edit icon in the Basic SAML configuration section
Basic SAML config

Your ServiceNow administrator should know this information and if not, you can contact ServiceNow support. But in general, this information is easy to figure out. I’ve mentioned the format of these URLs below. and I have used my own instance’s URL in the screenshot.

Identifier (Entity ID)https://{your-instance-name}.service-now.com
Reply URLhttps://{your-instance-name}.service-now.com/navpage.do
https://{your-instance-name}.service-now.com/customer.do
Sign on URLhttps://{your-instance-name}.service-now.com/login_with_sso.do?glide_sso_id=[sys_id of sso configuration]
Logout URLhttps://{your-instance-name}.service-now.com/navpage.do

Please follow along and I have a step below on how to determine the sys_id value from ServiceNow for the Sign on URL. Refer to Step 16. under the ‘Configure ServiceNow’ section below.

Below screenshots show values from my environment. I constructed the Sign on URL based on the sys_id information I got from ServiceNow as mentioned above

  1. In the SAML Signing Certificate section, find Certificate (Base64). Click Download to download Certificate(Base64), and then save the certificate file to your computer.
Download Certificate(Base64)

Create ServiceNow test user

  1. In ServiceNow portal, go to User Administration > Users
  2. Click New, complete the properties for your new user, and click Submit

Most organizations do ‘Automated user provisioning’ and this way you won’t have to create all the users in your Azure AD domain onto ServiceNow. But to make the SSO part easier, co-ordinate with your ServiceNow administrator and create an user account in ServiceNow with the email ID of a user in your Azure AD.

Configure ServiceNow

  1. Login on to your ServiceNow application portal as an administrator
  2. In the left pane, search for the System Definition section from the search box, and then select Plugins
ServiceNow plugins
  1. Search for Integration – Multiple Provider single sign-on Installer
  2. Right-click, and select Activate/Repair
search plug-in and activate
  1. Select Activate
Click Activate
wait till activation complete
Click Close & Refresh List
  1. In the left pane, search for the Multi-Provider SSO, and then select Properties
  1. Enable multiple provider SSO option is not active as in screenshot below and this is because Account Recovery is not setup. This comes in handy if something goes wrong with the SSO configuration and prevents admins from being locked out.
Enable multiple provider SSO not active
  1. Place a checkmark next to Enable account recovery to enable it
Account recovery properties
  1. Now back on the Customization Properties for Multiple Provider SSO page, place check mark next to below options,
    • Enable multiple provider SSO
    • Enable Auto Importing of users from all identity providers into the user table
    • Enable debug logging for the multiple provider SSO integration
    • The field on the user table that…,
      • email
Customization Properties for Multiple Provider SSO options
  1. Click Save to save configuration
  2. In the left pane, search for the Multi-Provider SSO, and then select Identity Providers
  1. Click New
  1. select SAML
  1. In the Import Identity Provider Metadata, select URL
    • The Metadata Url can be found in the Azure AD ServiceNow application SAML Signing Certificate section
    • Copy the App Federation Metadata Url value
Azure AD App Federation Metadata Url
  1. Paste the App Federation Metadata Url from Azure AD under Enter the URL and click Import
Paste the App Federation Metadata Url value
  1. Right click on the grey bar at the top of the screen and click Copy sys_id and save this value in a notepad to construct your Sign on URL in Azure AD
  1. The import metadata url reads the metadata and populates all the necessary information
    • Enter a name for your configuration. I’ve named it ‘Azure AD’
    • Confirm the NameID Policy is set to urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
    • Select Advanced. In User Field, enter email
SSO config
  1. Scroll down to the Encryption And Signing tab and X.509 Certificate section, and select New
  2. Open the .cer file with notepad which was downloaded from Azure AD and saved to your PC
    • copy the entire content and leave it in the clipboard
Azure AD certificate open using notepad
  1. Paste the contents in PEM certificate section
    • Provide a Name
    • Select Format as PEM
  2. Click Submit
x.509 certificate
  1. Click Update
Click Update
  1. Click Test Connection at the upper-right corner of the page
    • Sign-in using the test user account created earlier in the ‘Create ServiceNow test user’ section
    • Click Close
  1. Click Activate
Click Activate
  1. Ensure Default and Active are checked like in screenshot below
Active enabled
  1. To ensure ServiceNow auto-redirects the users to Azure AD SSO, click on the Set as Auto Redirect IdP in the Related Links section
Set as Auto Redirect IdP
Auto Redirect IdP is enabled
  1. Click Update to save the configuration

Test SSO

  1. Open ServiceNow portal
    • Use Incognito or InPrivate mode to avoid previously saved cookies
  2. The portal should auto-redirect to login.microsoftonline.com and prompt a sign-in

Issues you may encounter and How to fix it

Error: Ensure that the user you are trying the test connection with is present in the system.
Ensure that ‘User Field’ property value corresponds to the value set in the IDP returned through ‘Subject NameID’ in the response.

Fix: I tried the SSO with a user ID that only existed in Azure AD and not in ServiceNow. The System didn’t know what to do and hence the error..duh!

Error: SAML2ValidationError: Signature cryptographic validation not successful

Fix: I imported the PEM certificate from Azure AD into ServiceNow but I forgot to save it by not clicking update

This should help you with the Azure Active Directory single (SSO) integration with ServiceNow. I believe I’ve covered everything in this process.

Thank you for stopping by.✌

Azure AD – Self-Service Sign-up for Guest Users

A Self-Service user flow defines the steps an user will follow while signing-up for an application in your tenant. These applications can be the custom built or SaaS applications. This allows users to sign-up for an app and creates a guest account in the Azure AD tenant.

These user flows cannot be used for MS apps like Teams or SharePoint.

Enable self-service sign-up

Before creating and adding self-service sign-up user flow to your applications, the feature has to be enabled. Once enabled, the necessary options become available.

  1. Login to Azure AD admin portal (https://aad.portal.azure.com/)
  2. In the left menu, click External Identities and then External collaboration settings
External collaboration settings
  1. Toggle Yes to Enable guest self-service sign up via user flows
  2. Click Save

Create user flow for self-service sign-up

Now we’re ready to create user flow for self-service sign-up and add it to an application.

  1. Under the same External identities section in the above steps, click User flows in the left menu
  2. Select New user flow
  3. Enter a Name for the user flow. The name is automatically prefixed with B2X_1_
  4. Select the Identity providers
    • Azure AD is the default identity provider, which means that users are able to sign up by default with an Azure AD account
    • Google and Facebook, Microsoft Account, and Email OTP are also options
  5. Under User attributes, choose the attributes you want to collect from the user
    • For additional attributes, click on Show more
  6. Click Create
New user flow

Select the Page Layout

We can customize the order in which the attributes are displayed on the sign-up page

  1. Click on the user flow created
  2. Click on Page Layouts under Customize in the left menu
  3. For my scenario, I’ve reordered the fields and selected optional as No for the fields I consider mandatory
  4. Click Save
Page Layout

Add Application(s) to the user flow

Now, we are ready to associate an application to the user flow,

  1. In the left menu, under Use, select Applications
  2. Select Add application
    • For my scenario, I’m adding the Salesforce application to enable users to do a self-signup
  3. Search for the application and click Select
Add application

This concludes the steps in the Azure AD admin portal

Guest User experience

We can simply provide the application URL to the guest user for them to sign-up.

In my scenario, I’m using the Salesforce application in my environment,

Salesforce login page

When user tries to login with their own credentials, they will get an error ‘This account does not exist in this organization..‘ This means that the user who is part of a different Azure AD tenant doesn’t exist in the home tenant which the Salesforce application is part of.

Login error

User clicks on Create a new one or Create one!

Select Sign up with email. Enter Email address and password

Review and click Accept in the Permissions requested by: screen

Note: See in screenshot below, Permissions requested by: is the tenant where the application lives

Fill the necessary information and click Continue

Note: This next screen is a result of how we configured the page layout earlier.

And it redirects the user to the Salesforce landing page. I don’t have anything configured within Salesforce for this specific user

Salesforce landing page

So, there are few things to note here:

  • When the user goes through a self-signup process, guest account is automatically created for the user in the home tenant
  • Like in my example, as I don’t have user provisioning enabled with Salesforce, the user has to be created within Salesforce
    • I’m only know the basics on Salesforce’s inner workings but I do have the authentication part configured with Azure AD
    • If you are following this guide and also allowing guest users to login to Salesforce, have your Salesforce administrator setup this guest user with the user’s home tenant’s email account
Guest user’s profile

Hope this post helped you in setting up the Azure AD self-service sign-up user flow to an app.

Thank you for stopping by.✌

Teams – Outbound Calling policies for Audio conferencing and user PSTN calls

This one took me a while to understand what is happening and how to resolve it. The Teams audio and calling functions are not something I deal with on a daily basis but it was good learning experience.

One of the Teams tenant I manage kept running out of pooled minutes really quickly. I wasn’t actively monitoring the usage but I did notice the emails from Microsoft that were warning us that the minutes are almost used up and users won’t be able to use the PSTN conferencing services for the rest of the calendar month unless more communication credits were added.

What is the deal here exactly?

Each user assigned an ‘Audio Conferencing’ license which provides a dial-in phone number when they schedule a meeting, is given 60 minutes per month of pooled minutes that can be used for inbound or outbound PSTN dialing for meetings. This ‘Audio Conferencing’ license is only needed for users scheduling the meetings. Meeting attendees who dial in don’t need this license. Depending on how you have deployed Teams in your organization, whether as a full blown phone system or used specifically for meetings, this pooling minutes is only for meetings and is separate from other dial plans(domestic or international) that you may have.

Users with ‘Audio Conferencing’ license are given a default invite number in the same country as what their O365 account’s usage location is set to.

In a example scenario where an organization has 100 users that have ‘Audio Conferencing’ license, 100 X 60 minutes and you get 6000 pooled minutes for your tenant to PSTN dial-in and dial-out of meetings. One the 6000 minutes are consumed users will no longer be able to dial-in or dial-out of the meetings using the number provided in the meetings.

Note: Users can still participate using the Teams meeting clients(Desktop or phone app).

Latest Update: Microsoft is extending the audio conferencing capabilities by removing the cost involved to the SKU.

Why users use the PSTN dial-in numbers for Teams online meetings

Personally I love the Teams app, both on the desktop and the phone. And I can tell Microsoft is adding new functionalities over time. I also like it how I can use the phone app for voice and also launch Teams on my desktop and I get an option to ‘add the device’ to the ongoing call on the phone. This way, I can present using the desktop.

Using this VOIP features via the Teams app(phone or desktop) doesn’t incur additional cost to the organization but there are some scenarios where including a dial-in number to meetings makes sense,

  • Poor or limited internet connectivity
  • Users moving in and out of limited data coverage where voice quality may be better
  • Users having issues with VOIP on their PC and phone app
  • Users are used to the old ways
    • Users lack training in Teams clients(Desktop or phone app)

Determine pooled minutes and usage

To check your PSTN pooled minutes, you can run usage reports in the Teams admin center,

Teams Admin Center –> Analytics & reports –> Usage reports

  • PSTN minute and SMS(preview) pools
  • PSTN and SMS(preview) usage
PSTN minute and SMS(preview) pools
PSTN and SMS(preview) usage

What is burning precious PSTN minutes

Based on the reports and further reading I realized the ‘Call me‘ feature in Teams is apparently a well known and heavily used user loved feature which seems to be a behavior that followed users from using other conferencing tools.

Users can join a meeting and have the meeting call and join them or dial in manually to the meeting.

Screen shot of the Phone audio option.
Screen shot of the Call me option on the Use phone for audio screen.

As I mentioned earlier, the users using this feature didn’t realize they can use their computer audio or the Teams app on their phone. There were others who thought this was a handy feature and more convenient. Well, what they didn’t know or didn’t care is, the outbound calls were eating those pooled PSTN minutes and affecting the entire organization for users who would really need it.

What is the fix?

This can be fixed by educating the users about the VOIP options, using the computer or phone Teams app. And yes, obviously by putting policies in the tenant.

In the Teams admin center, the dial-out from meeting can be controlled on a per-user basis

  1. In the left navigation, select Users, and then select the display name of the user from the list of available users
  2. Under Audio Conferencing, select Edit
  3. Under Dial-out from meetings, select the dial-out restriction option you desire
  4. Select Save

This may resolve the issue by assigning ‘Don’t allow’ policy for the users who are the heavy hitters of the ‘Call me’ feature but more users might start using this feature and you’ll have to constantly monitor the usage.

To prevent this, you can set a tenant level policy based on your requirements and organizational needs. Once the global policy is in place, you can assign a policy on a per-user level.

The following table provides an overview of each policy.

PowerShell cmdlet Description
DialoutCPCandPSTNInternationalUser in the conference can dial out to international and domestic numbers, and this user can also make outbound calls to international and domestic numbers.
DialoutCPCDomesticPSTNInternationalUser in the conference can only dial out to domestic numbers, and this user can make outbound calls to international and domestic numbers.
DialoutCPCDisabledPSTNInternationalUser in the conference can’t dial out. This user can make outbound calls to international and domestic numbers.
DialoutCPCInternationalPSTNDomesticUser in the conference can dial out to international and domestic numbers, and this user can only make outbound calls to domestic PSTN number.
DialoutCPCInternationalPSTNDisabledUser in the conference can dial out to international and domestic numbers, and this user cannot make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCandPSTNDomesticUser in the conference can only dial out to domestic numbers, and this user can only make outbound call to domestic PSTN numbers.
DialoutCPCDomesticPSTNDisabledUser in the conference can only dial out to domestic numbers, and this user cannot make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCDisabledPSTNDomesticUser in the conference can’t dial out, and this user can only make outbound call to domestic PSTN numbers.
DialoutCPCandPSTNDisabledUser in the conference can’t dial out, and this user can’t make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCZoneAPSTNInternationalUser in the conference can only dial out to Zone A countries and regions, and this user can make outbound calls to international and domestic numbers.
DialoutCPCZoneAPSTNDomesticUser in the conference can only dial out to Zone A countries and regions, and this user can only make outbound calls to domestic PSTN number.
DialoutCPCZoneAPSTNDisabledUser in the conference can only dial out to Zone A countries and regions, and this user can’t make any outbound calls to PSTN number besides emergency numbers.

To set the policy on the tenant level, use following cmdlet. Use the pre-defined policy from the table above for the ‘policy name’

Grant-CsDialoutPolicy -PolicyName <policy name> -Global

To check the current policy at the tenant level,

Get-CSOnlineDialOutPolicy -Identity Global

In my scenario, my plan is to set the global dial-out from meetings policy to DialoutCPCandPSTNDisabled. And assign per-user policy based on their needs.

Tenant-level policy

Note: All users of the tenant who don’t have any dial-out policy assigned will get the global policy.

To set the policy on a per-user level,

Grant-CsDialoutPolicy -Identity <username> -PolicyName <policy name>

You can set what is allowed per-user using the Teams admin center as covered earlier or you can use PowerShell to assign a policy to a list of users using this below script.

#Connect-MicrosoftTeams
$list=import-csv "c:\tmp\user.csv"

Foreach($user in $list){

Grant-CsDialoutPolicy -identity $user.UserId -PolicyName "DialoutCPCandPSTNDomestic" #Setting 'DialoutCPCandPSTNDomestic' policy to the users
}

You can also export a report of users and their Dial-Out policy assigned to them,

Get-CsOnlineUser | Select-Object UserPrincipalName,OnlineDialOutPolicy | Export-CSV "C:\tmp\userCallingPolicyReport.csv" -NoTypeInformation

Teams and its audio services are a much more detailed topic and I covered what applied to the issue I faced. Hope you’d be able to as well if you encounter this.

Thank you for stopping by.✌