Preparing technical configuration for DPG Service
This document describes the required technical configuration for new DPG customers with Exchange Online.
The configuration must be performed by the customer, and it is the responsibility of the designated Technical Contact to act as a single point of contact and to coordinate all necessary customer resources during the DPG implementation project.
Mailboxes: Naming, users, and permissions
- A DPG system mailbox must be created as a licensed mailbox. It is
recommended to name it
dpg@<CUSTOMER.NAME>
. - One or more secure mailboxes (a.k.a. funktionspostkasser) must already
exist or be created. They are typically named
sikkerpost@<CUSTOMER.NAME>
,hr@<CUSTOMER.NAME>
,finance@<CUSTOMER.NAME>
, etc. They can be created as shared mailboxes or as licensed mailboxes. If OME (Office Message Encryption) is enabled, please use licensed mailboxes. - All users who should be able to send securely using DPG must have the following permissions set:
- Send on Behalf to only the secure mailboxes they should be able to send from
- Full Access to only the secure mailboxes they should be able to access
- A Mail-enabled Security group must be created. It is recommended to
name it
GRP-DPG-SecureMailboxes@<CUSTOMER.NAME>
. All the secure mailboxes must be members of the group.
Mailbox requirements, recommendations and best practices
The following recommendations and best practices are supported by examples.
-
Both the system mailbox and all the secure mailboxes (funktionspostkasser) must be set with a message size limit of 150MB.
How to set mailbox-level message size limits
This example shows how to set mailbox-level message size limits:
<# Set mailbox-level message size limits #> Set-Mailbox -Identity "dpg" -MaxSendSize 150MB -MaxReceiveSize 150MB <# Verify that mailbox message limits have been set to 150 MB #> Get-Mailbox -Identity "dpg" | Select MaxSendSize, MaxReceiveSize
-
The system mailbox must not be configured as resource or room mailbox.
-
Hide only the system mailbox from GAL (Hide from address lists).
How to hide a mailbox from address lists
This example shows how to hide a mailbox from address lists:
<# Hide mailbox from address lists #> Set-Mailbox -Identity "dpg" -HiddenFromAddressListsEnabled $true <# Verify that mailbox is hidden from address lists #> Get-Mailbox -Identity "dpg" | Format-List HiddenFromAddressListsEnabled
-
System mailbox language must always be set to English to prevent errors with folder names and ATP scanning.
How to set mailbox language to en-US
This example shows how to set mailbox language to en-US:
<# Set the mailbox language #> Set-MailboxRegionalConfiguration -Identity "dpg" -Language en-US ` -LocalizeDefaultFolderName -DateFormat "yyyy-MM-dd" -TimeFormat "HH:mm" <# Verify that the mailbox language is set #> Get-Mailbox -Identity "dpg" | Format-List Languages
-
Disable retention for system mailbox, keep it to a low number of days, and exclude it from retention policies. As the system mailbox is very busy, retention can result in the system mailbox running out of space.
How to identify if retention policy is enabled
This example shows a way of identifying if a retention policy is enabled.
Note: if a retention GUID exists, you must make sure to disable retention for the system mailbox – see for example "Mailbox Retention Policy", "Retention Policy" or "Inplace holds":<# See if a retention GUID exists #> Get-Mailbox -identity "dpg" | Select Name, InPlaceholds | FL
-
The system mailbox must be monitored regularly by an administrator. Look for remaining read emails (indication of mail processing failure) and ensure that the mailbox does not increase in size. In general, the system mailbox should only contain mails in the short span where DPG is processing, and once DPG has successfully finished, the mails are automatically deleted from the mailbox.
- Consider using Security Groups for managing mailbox permissions.
- Disable https://myanalytics.microsoft.com/ for the system mailbox.
DPG SaaS integration - Azure Graph and OAuth configuration
DPG connects to Azure as a Registered Application and authenticates using OAuth 2.0. Emails are retrieved from the system mailbox using Graph, and the DPG application is only permitted access to the system mailbox.
Configuration
- Log in to https://portal.azure.com as an administrator, and search for Microsoft Entra ID.
-
Go to App registrations, and select New registration. Insert a Name, set the Redirect URI to Public client/native (mobile & desktop), and set the value to
urn:ietf:wg:oauth:2.0:oob
. Select Register to finish: -
For the App registration you just created, make a note of the Application (client) ID and the Directory (tenant) ID. Both can be found in the Overview section:
-
Go to API permissions and select Add a permission. Click Microsoft Graph, and then Application permissions.
- Go to the section Mail, and select
Mail.ReadWrite
. - Go to the section User, and select
User.Read.All
- Go to the section for GroupMember, and select
GroupMember.Read.All
. - Select Add permissions to finish:
- Go to the section Mail, and select
-
Click Grant admin consent for
<customer>
. -
If prompted, accept the permissions requested.
-
Make sure all application permissions are set and granted.
-
Now select Certificates & secrets. You have two options to prove the application's identity. DPG supports both:
-
Using a certificate (recommended):
Select Upload certificate, browse for the certificate (public key)
.cer
file to be used, and select Add. It is recommended to use a.cer
file for an organization certificate to be installed in DPG.If you have access to logging in to the TIMENGO DPG portal, you can easily obtain the
.cer
version of an organization certificate (organisationscertifikat). Go to Certificate Check, look up the certificate, and select the button to download:Once completed, you will see that the certificate is installed:
Very important
Certificates expire, so the certificate must be updated whenever it is renewed. Remember that the new 'organisationscertifikat' must also be installed in the DPG service – otherwise, DPG will fail to connect!
-
Using a secret string (NOT recommended):
Select New client secret, name it "DPG client secret", set to for instance 24 months, and select Add:
The client secret (a.k.a. application password) is shown, and it is important to copy the password:
-
-
Use PowerShell to create a new
ApplicationAccessPolicy
. Update accordingly for:EMAIL_ADDRESS_OF_THE_SYSTEM_MAILBOX
APPLICTION_CLIENT_ID
$Desc = "Restrict DPG application to only the system mailbox" $DPGSystemMailbox = "EMAIL_ADRESS_OF_THE_SYSTEM_MAILBOX" $AppId = "APPLICATION_CLIENT_ID" New-ApplicationAccessPolicy -AppId $AppId -PolicyScopeGroupId ` $DPGSystemMailbox -AccessRight RestrictAccess -Description $Desc
-
Confirm that the
ApplicationAccessPolicy
is applied correctly by running the PowerShell below. Access to the system mailbox should sayGranted
, and access to a random mailbox should sayDenied
.Update accordingly for:
EMAIL_ADDRESS_OF_THE_SYSTEM_MAILBOX
EMAIL_ADDRESSS_OF_A_RANDOM_MAILBOX
APPLICATION_CLIENT_ID
$DPGSystemMailbox = "EMAIL_ADRESS_OF_THE_SYSTEM_MAILBOX" $TestUser = "EMAIL_ADDRESS_OF_A_RANDOM_MAILBOX" $AppId = "APPLICATION_CLIENT_ID" Test-ApplicationAccessPolicy -Identity $DPGSystemMailbox -AppId $AppId Write-host "Make sure this permission is set to Granted" ` -ForegroundColor Green Pause Test-ApplicationAccessPolicy -Identity $TestUser -AppId $AppId Write-host "Make sure this permission is set to Denied" ` -ForegroundColor Red
You have now completed the DPG SaaS integration - Azure Graph and OAuth configuration for DPG Service.
Additional configuration for DPG Outlook Office Addin: Enable Single sign-on (App registration)
DPG Outlook Office Addin authenticates with Azure as a Registered Application and authenticates using OAuth 2.0.
For more about this, see this Microsoft page.
There are two ways to register the app with Azure: You can run the PowerShell script provided below, or you can manually configure Azure by following step-by-step instructions.
This is the PowerShell script that can configure Azure for you:
Create-DPGAppRegistration script (zip file)
Or you can view it and copy it from here:
Create-DPGAppRegistration
# DPG Office Addin PowerShell Script Template
# Script to create Azure App Registration for DPG Office Add-in
# Requires Azure AD PowerShell module (Az.Resources) and Microsoft.Graph module
# Parameters
param(
[Parameter(Mandatory=$false)]
[string]$AppName = "DPG Office Add-in (dpgofficeaddin.dpgapi.dk)",
[Parameter(Mandatory=$false)]
[string]$RedirectUri = "https://dpgofficeaddin.dpgapi.dk",
[Parameter(Mandatory=$false)]
[string]$MicrosoftOfficeClientId = "ea5a67f6-b6f3-4338-b240-c655ddc3cc8e"
)
# Check if required modules are installed
if (-not (Get-Module -ListAvailable -Name Az.Resources)) {
Write-Host "Azure AD PowerShell module not found. Installing..."
Install-Module -Name Az.Resources -Scope CurrentUser -Force
}
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) {
Write-Host "Microsoft Graph PowerShell module not found. Installing..."
Install-Module Microsoft.Graph -Scope CurrentUser -Force
}
# Import required modules
Import-Module Az.Resources
Import-Module Microsoft.Graph.Applications
Import-Module Microsoft.Graph.Authentication
# Disconnect from Azure AD and Microsoft Graph
Write-Host "Disconnecting from Azure AD and Microsoft Graph... So we can connect with required permissions"
Disconnect-AzAccount -ErrorAction SilentlyContinue
Disconnect-MgGraph -ErrorAction SilentlyContinue
# Connect to Azure AD and Microsoft Graph with required permissions
try {
Write-Host "Connecting to Azure AD and Microsoft Graph..."
Connect-AzAccount | Out-Null
Connect-MgGraph -Scopes "Application.ReadWrite.All", "AppRoleAssignment.ReadWrite.All", "Directory.ReadWrite.All" | Out-Null
}
catch {
Write-Error "Failed to connect to Azure AD or Microsoft Graph: $_"
exit 1
}
# Resolve tenant to use
$tenants = Get-AzTenant | Select-Object Id, Name, DefaultDomain
if (-not $tenants -or $tenants.Count -eq 0) {
throw "No tenants available for the signed-in account."
}
if ($tenants.Count -gt 1) {
Write-Host "Multiple tenants found:`n"
for ($i = 0; $i -lt $tenants.Count; $i++) {
$t = $tenants[$i]
Write-Host ("[{0}] {1} ({2}) - {3}" -f ($i+1), $t.Name, $t.DefaultDomain, $t.Id)
}
do {
$choice = Read-Host "Enter the number of the tenant to use"
$parsed = 0
$validInt = [int]::TryParse($choice, [ref]$parsed)
$valid = $validInt -and ($parsed -ge 1) -and ($parsed -le $tenants.Count)
if (-not $valid) { Write-Host "Invalid choice. Try again." -ForegroundColor Yellow }
} while (-not $valid)
$selectedTenantId = $tenants[$parsed - 1].Id
}
else {
$selectedTenantId = $tenants[0].Id
}
# Ensure Az context is set to the selected tenant
Set-AzContext -Tenant $selectedTenantId | Out-Null
# Use this single tenant ID throughout
$tenantId = $selectedTenantId
Write-Host "Directory (tenant) ID selected: $tenantId"
# If multiple tenants were available, align Microsoft Graph connection to the selected tenant
if ($tenants.Count -gt 1) {
Write-Host "Aligning Microsoft Graph connection to selected tenant..."
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
Connect-MgGraph -TenantId $selectedTenantId -Scopes "Application.ReadWrite.All","AppRoleAssignment.ReadWrite.All","Directory.ReadWrite.All" | Out-Null
}
# Create the application registration
try {
# Create the application
Write-Host "Creating application registration..."
$app = New-AzADApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg"
if (-not $app) {
throw "Failed to create application"
}
Write-Host "Application created successfully!"
Write-Host "Application (client) ID: $($app.AppId)"
# Tenant ID already resolved earlier
Write-Host "Directory (tenant) ID: $tenantId"
# Update the application with redirect URIs
Update-AzADApplication -ObjectId $app.Id -SPARedirectUri $RedirectUri
# Set the Application ID URI
Write-Host "Setting Application ID URI..."
$appIdUri = "api://dpgofficeaddin.dpgapi.dk/$($app.AppId)"
Update-AzADApplication -ObjectId $app.Id -IdentifierUris $appIdUri
# Wait for the application to be available in Microsoft Graph
Write-Host "Waiting for application to be available in Microsoft Graph..."
$retryCount = 0
$maxRetries = 5
$mgApp = $null
do {
Start-Sleep -Seconds 5
$mgApp = Get-MgApplication -Filter "AppId eq '$($app.AppId)'"
$retryCount++
} while ($null -eq $mgApp -and $retryCount -lt $maxRetries)
if ($null -eq $mgApp) {
throw "Failed to find application in Microsoft Graph after $maxRetries attempts"
}
# Create scope ID that we'll use for both the scope and pre-authorized application
$scopeId = [guid]::NewGuid()
# First, create the scope
Write-Host "Adding 'Authenticated' scope..."
$scopeParams = @{
"api" = @{
"oauth2PermissionScopes" = @(
@{
"id" = $scopeId
"adminConsentDescription" = "Authenticated"
"adminConsentDisplayName" = "Authenticated"
"userConsentDescription" = "Authenticated"
"userConsentDisplayName" = "Authenticated"
"isEnabled" = $true
"type" = "User"
"value" = "Authenticated"
}
)
}
}
Update-MgApplication -ApplicationId $mgApp.Id -BodyParameter $scopeParams
# Then, add the pre-authorized application
Write-Host "Pre-authorizing Microsoft Office client..."
Start-Sleep -Seconds 5 # Wait for scope to be fully created
$preAuthParams = @{
"api" = @{
"preAuthorizedApplications" = @(
@{
"appId" = $MicrosoftOfficeClientId
"delegatedPermissionIds" = @($scopeId)
}
)
}
}
Update-MgApplication -ApplicationId $mgApp.Id -BodyParameter $preAuthParams
# Add Microsoft Graph permissions
Write-Host "Adding API permissions..."
$graphResourceId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph
$requiredResourceAccess = @{
"requiredResourceAccess" = @(
@{
"resourceAppId" = $graphResourceId
"resourceAccess" = @(
@{
"id" = "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0" # email
"type" = "Scope"
},
@{
"id" = "37f7f235-527c-4136-accd-4a02d197296e" # openid
"type" = "Scope"
},
@{
"id" = "14dad69e-099b-42c9-810b-d002981feec1" # profile
"type" = "Scope"
},
@{
"id" = "570282fd-fa5c-430d-a7fd-fc8dc98a9dca" # Mail.Read
"type" = "Scope"
},
@{
"id" = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" # User.Read
"type" = "Scope"
},
@{
"id" = "e383f46e-2787-4529-855e-0e479a3ffac0" # Mail.Send
"type" = "Scope"
},
@{
"id" = "7b9103a5-4610-446b-9670-80643382c1fa" # Mail.Read.Shared
"type" = "Scope"
},
@{
"id" = "a367ab51-6b49-43bf-a716-a1fb06d2a174" # Mail.Send.Shared
"type" = "Scope"
}
)
}
)
}
Update-MgApplication -ApplicationId $mgApp.Id -BodyParameter $requiredResourceAccess
# Update manifest to set accessTokenAcceptedVersion to 2
Write-Host "Setting accessTokenAcceptedVersion to 2..."
$manifestUpdate = @{
"api" = @{
"requestedAccessTokenVersion" = 2
}
}
Update-MgApplication -ApplicationId $mgApp.Id -BodyParameter $manifestUpdate
# Create a service principal for the application
Write-Host "Creating service principal..."
$servicePrincipal = New-MgServicePrincipal -AppId $app.AppId
Start-Sleep -Seconds 5 # Wait for service principal to be fully created
# Get Microsoft Graph service principal
Write-Host "Getting Microsoft Graph permissions..."
$graphServicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$graphResourceId'"
# Grant admin consent for all required permissions
Write-Host "Granting admin consent for permissions..."
try {
Write-Host "Service Principal ID: $($servicePrincipal.Id)"
Write-Host "Graph Service Principal ID: $($graphServicePrincipal.Id)"
New-MgOauth2PermissionGrant `
-ClientId $servicePrincipal.Id `
-ConsentType "AllPrincipals" `
-ResourceId $graphServicePrincipal.Id `
-Scope "email openid profile Mail.Read User.Read Mail.Send Mail.Read.Shared Mail.Send.Shared"
Write-Host "Successfully granted admin consent for permissions" -ForegroundColor Green
}
catch {
Write-Host "Failed to grant admin consent for permissions: $_" -ForegroundColor Red
}
Write-Host "App registration setup completed successfully!"
Write-Host ""
Write-Host "Application details for handover to Timengo DPG:"
Write-Host "Application (client) ID: $($app.AppId)"
Write-Host "Directory (tenant) ID: $tenantId"
$cwd = Split-Path -Path $PSCommandPath -Parent
Set-Content -Path $cwd\DPGOfficeAddin-TechnicalDetails.txt -Value "Application (client) ID: $($app.AppId)`nDirectory (tenant) ID: $tenantId"
write-host "Details saved to $cwd\DPGOfficeAddin-TechnicalDetails.txt"
# Disconnect from Azure AD and Microsoft Graph
Write-Host "Disconnecting from Azure AD and Microsoft Graph..."
Disconnect-AzAccount -ErrorAction SilentlyContinue | Out-Null
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
}
catch {
Write-Error "Failed to create app registration: $_"
exit 1
}
Step-by-step instructions
Following the steps to manually configure Azure helps you to understand the configuration. The script provided above is an automated version of the steps below.
Complete the following steps to configure the App registration in Azure:
- Log in to Azure as an administrator, and go to Microsoft Entra ID.
-
Specify details for the app registration
- Set Name as
DPG Office Add-in (dpgofficeaddin.dpgapi.dk)
- Select Supported account types as
Accounts in this organization directory only (Single tenant)
- Set Redirect URI to
Single-page application (SPA)
, and set the value tohttps://dpgofficeaddin.dpgapi.dk
- Finish by selecting Register.
- Set Name as
-
Make a note of the Application (client) ID and Directory (tenant) ID from the Overview section as highlighted below.
-
Select Expose an API, and select Add to create an Application ID URI.
-
Update the Application ID URI to
api://dpgofficeaddin.dpgapi.dk/<Application (client) ID>
, and finish by selecting Save:
-
Now select Add a scope in the Expose an API pane, and insert the text
Authenticated
as shown below. Make sure to select Admin and users in the Who can consent? field, and Enabled in the State field. Finish by selecting Add scope:
-
Still in the Expose an API pane, select Add a client application, and insert
ea5a67f6-b6f3-4338-b240-c655ddc3cc8e
, which pre-authorizes all Microsoft Office Application endpoints. Also select the Authorized scopes box, and finish by selecting Add application:
-
Select permissions for
email
,openid
,profile
,Mail.Read
,Mail.Send
,Mail.Read.Shared
,Mail.Send.Shared
, andUser.Read
. Finish by selecting Add permissions:
-
In the Configured permissions pane, select Grant admin consent for…, and finish by selecting Yes.
-
Once permissions have been granted, the Configured permissions view should look like this:
-
Select Manifest, and change the value for
"accessTokenAcceptedVersion"
from null to2
, and select Save to finish.
-
Select Authentication for the app registration you have created. In the section Single-page application Redirect URIs, select Add URI, and add the value
brk-multihub://dpgofficeaddin.dpgapi.dk
. Select Save to finish.
You have now completed Enable Single sign-on (App registration) configuration for DPG Outlook Office Addin.
Handover to Timengo DPG
After completing the configuration steps, you must hand over the following details to Timengo DPG as specified in the welcome letter:
- Mail address of DPG system mailbox
- Mail addresses of the secure mailboxes
- Mail address of the Mail-Enabled Security Group
- DPG SaaS integration - Azure Graph and OAuth configuration configuration details:
- Application (client) ID
- Directory (tenant) ID
- Mail address of the 'organisationscertifikat' used
- DPG Outlook Office Add-In – enable Single sign-on (App registration) configuration details:
- Application (client) ID
- Directory (tenant) ID