Sales
Denmark +45 7944 7000
Europe +45 7944 7000
North America +1 (202)-536-4165
Support
Denmark +45 7944 7002
North America +1 (202)-536-4165

Combined Entra Id app for reservation and mail with RBAC

Modified on Wed, 15 Jan at 11:16 AM

Summary

During the configuration of Digital Sign Service (DSS) for the Server with Microsoft Graph in O365 (Entra ID), we need to create an application registration with rights to read Entra ID objects and read/write calendar entries and send emails in your O365 tenant. 

The sections below explains the process of setting up the app with Powershell, and it is important that the script snippets are used in the same powershell session to ensure that variables and variable values are carried over from one section to the next.

Note: Making use of this script requires prior knowledge about Powershell, and it is your responsibility to understand the script before using it. Add-On Products do not take any responsibility for the consequences of improper use.


Prepare powershell environment.

This guide explains the process of setting up the Entra ID application and associated RBAC in Exchange Online using Powershell, and hence it is important that certain modules are available on your machine.

In order to complete this task you will need the following components:

  • Powershell 7
  • ExchangeOnlineManagement module
  • Microsoft.graph module

Complete script is attached as zip.

Below scriptblock checks for installed modules and installs them if they are not present on your machine.


#Install required modules if missing
if(-not (Get-InstalledModule Microsoft.Graph.Authentication)){
  Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Force
  }

if(-not (Get-InstalledModule Microsoft.Graph.Applications)){
  Install-Module Microsoft.Graph.Applications -Scope CurrentUser -Force
  }

if(-not (Get-InstalledModule Microsoft.Graph.Identity.DirectoryManagement)){
  Install-Module Microsoft.Graph.Identity.DirectoryManagement -Scope CurrentUser -Force
  }

if(-not (Get-InstalledModule Microsoft.Graph.Identity.signins)){
    Install-Module Microsoft.Graph.Identity.signins -Scope CurrentUser -Force
    }

#Import Module
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Applications
Import-Module Microsoft.Graph.Identity.DirectoryManagement
Import-Module Microsoft.Graph.Identity.signins


Define script variables

Before creating the Entra ID app you must define a set of variables.

  • AppName - Define the name of the Entra ID app
  • ServerName - DNS name of the DS server
  • SecretDuration - Set expiration timeline of the Entra ID secret in months
  • ExchangeResourceGroupName - Name of the Exchange group containing the resources to be used in DS
  • ExchangeMailGroupName - Name of the Exchange group containing the mailbox used for mail sending from DS


$AppName =  "Addon DS Reservation Sync"
$ServerName = "Addon.add-on.com"
$SecretDuration = 120
$ExchangeResourceGroupName = "resources"
$ExchangeMailGroupName = "MailAccount"


Create Entra ID application

Now it is time to create the Entra ID application according to the variables above.

The script below will create the application, but will exit in case an application with the same name already exists and leave it to you to manually delete that existing application or choose a different name for this new application.

The values of the application will be stored in a text file in Downloads folder and notepad will open presenting the values.


###############################################################################
#Connect to your tenant with Graph and required scopes
###############################################################################
Connect-MgGraph -Scopes "Application.Read.All","Application.ReadWrite.All","User.Read.All","Domain.Read.All", "AppRoleAssignment.ReadWrite.All"
Get-MgContext
Write-Host "Tenant Name: " (Get-MgDomain | Where-object {$_.IsInitial -eq $true}).id

###############################################################################
#Create AAD Application
###############################################################################
$ExistingApp = Get-MgApplication -Filter "startswith(displayName,'$AppName')"
If ($ExistingApp){
	Write-Warning -Message "Applicaiton already exist - Exiting script"
	Write-Warning -Message "Please delete application $($ExistingApp.AppId) before you proceed with this script"
    break
}Else{
	$App = New-MgApplication -DisplayName $AppName 
}
$APPObjectID = $App.Id

###############################################################################
#Add Current user as Owner
###############################################################################
$User = get-mguser -UserId (Get-MgContext).Account 
$ObjectId = $User.ID
$NewOwner = @{
  "@odata.id"= "https://graph.microsoft.com/v1.0/directoryObjects/{$ObjectId}"
  }
New-MgApplicationOwnerByRef -ApplicationId $APPObjectID -BodyParameter $NewOwner

###############################################################################
#Add a ClientSecret
###############################################################################
$passwordCred = @{
  "displayName" = "ClientSecret"
  "endDateTime" = (Get-Date).AddMonths(+$SecretDuration)
}
$ClientSecret = Add-MgApplicationPassword -ApplicationId $APPObjectID -PasswordCredential $passwordCred

###############################################################################
#Add redirect URI's for auth purposes
###############################################################################
#Redirect URI
$RedirectURI = @()
$RedirectURI += "https://" + $ServerName + "/DigitalSignService/Domain/Authorize"
$RedirectURI += "https://" + $ServerName + "/DigitalSignService/Admin/LoginWithSSOCallback"

$params = @{
  RedirectUris = @($RedirectURI)
  implicitGrantSettings = @{
        enableIdTokenIssuance = $true
        enableAccessTokenIssuance = $false
  }
}
Update-MgApplication -ApplicationId $APPObjectID -Web $params 

###############################################################################
#Add App Permissions
###############################################################################

$requiredGrants = New-Object -TypeName System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess]
$requiredResourceAccess = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess
$requiredResourceAccess.ResourceAppId = "00000003-0000-0000-c000-000000000000"
$requiredResourceAccess.ResourceAccess+=@{ Id = "dbb9058a-0e50-45d7-ae91-66909b5d4664"; Type = "Role" }
$requiredResourceAccess.ResourceAccess+=@{ Id = "98830695-27a2-44f7-8c18-0c3ebc9698f6"; Type = "Role" }
$requiredResourceAccess.ResourceAccess+=@{ Id = "df021288-bdef-4463-88db-98f22de89214"; Type = "Role" }
$requiredResourceAccess.ResourceAccess+=@{ Id = "913b9306-0ce1-42b8-9137-6a7df690a760"; Type = "Role" }
$requiredResourceAccess.ResourceAccess+=@{ Id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"; Type = "Scope" }
$requiredGrants.Add($requiredResourceAccess)

Update-MgApplication -ApplicationId $APPObjectID -RequiredResourceAccess $requiredGrants

###############################################################################
#Create Service Principal if it does not exist.
###############################################################################

$Principal = Get-MgServicePrincipal -Filter "appId eq '$($App.appId)'"
if (-not $Principal) {
  Write-Host "Creating client app's service principal"
  $Principal = New-MgServicePrincipal -AppId $App.appId -Description $App.DisplayName
}
Write-Host "Client: '$($Principal.displayName)' (appId: $($Principal.appId))"

###############################################################################
#Grant Admin Consent 
###############################################################################
$Resource = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'"

# Grant consent for delegated Graph permission User.Read
$params = @{
  "ClientId" = $Principal.Id
  "ConsentType" = "AllPrincipals"
  "ResourceId" = $Resource.id
  "Scope" = "User.Read"
  }

New-MgOauth2PermissionGrant -BodyParameter $params | Format-List Id, ClientId, ConsentType, ResourceId, Scope

# Grant consent to the application permission
New-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $Principal.Id -PrincipalId $Principal.Id -ResourceId $Resource.id -AppRoleId "dbb9058a-0e50-45d7-ae91-66909b5d4664"
New-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $Principal.Id -PrincipalId $Principal.Id -ResourceId $Resource.id -AppRoleId "98830695-27a2-44f7-8c18-0c3ebc9698f6"
New-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $Principal.Id -PrincipalId $Principal.Id -ResourceId $Resource.id -AppRoleId "df021288-bdef-4463-88db-98f22de89214"
New-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $Principal.Id -PrincipalId $Principal.Id -ResourceId $Resource.id -AppRoleId "913b9306-0ce1-42b8-9137-6a7df690a760"

###############################################################################
#App details to be used
###############################################################################

$ResultFile = "" + (New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path + "\" + $AppName + ".txt"
$resultset=@"
Application name: $($app.DisplayName)
Tenant ID: $((Get-MgOrganization).Id)
Tenant Name: $((Get-MgDomain | Where-object {$_.IsInitial -eq $true}).id)
Client ID: $($app.AppID)
Client Secret: $($clientSecret.SecretText)
"@

$resultset | out-file -FilePath $ResultFile
Invoke-Item $ResultFile


Create RBAC setup in Exchange Online

Next step is to dynamically assign the two required application permission roles and target them to the Exchange Online groups defined in the variables above, and it is important that the names are correct for the commands to work.

This method relies on a service principal in Exchange Online associated with the newly created Entra ID application above, and the script below uses variables from above and must hence be executed in the same process for the variables to still be loaded into memory.

# Configure RBAC permissions for Exchange access
Connect-ExchangeOnline
$RBACPrincipal = New-ServicePrincipal -AppId $Principal.AppId -ServiceId $Principal.Id -DisplayName "EXO Serviceprincipal $($Principal.Displayname)"

New-ManagementRoleAssignment -Name "DS Service Resource CalendarAccess"  -App $RBACPrincipal.AppId -Role "Application Calendars.ReadWrite" -RecipientGroupScope $ExchangeResourceGroupName
New-ManagementRoleAssignment -Name "DS Service Resource Mail" -App $RBACPrincipal.AppId -Role "Application Mail.Send" -RecipientGroupScope $ExchangeMailGroupName



Implement application settings in DS

Once the app described above has been created, you must collect this information for configuration in DS Service.

  • Tenant Name must be entered in “Tenant name” field. (xx.onmicrosoft.com)
  • Application (Client) ID must be entered in “Application Client ID” field.
  • Secret Key must be entered in “Client Secret” field.


Properties

Applies to: DSS for Server 4+
Reference: TFS #204048
Knowledge base ID: 0297
Last updated: Jan 01, 2025

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article