The MyTimetable calendar push integration is able to connect to a user's calendar using service accounts. This page describes how to create a service account and how to grant calendar permissions to this service account. MyTimetable will then be able to access calendars without explicit consent of a user.

This page applies to both Microsoft Exchange (on-premises) and Microsoft Office 365.

Table of Contents

Office 365 / Azure AD prerequisites

The following installs are required when managing Office 365 / Azure AD through Powershell.

You must be a tenant admin on your Office 365 tenant to run the cmdlets.

Connecting to Office 365 using Powershell

We are going to connect to Office 365 using Powershell. For this, we have to set up a remote Powershell session. First, we need to check if we are allowed to do so:

PS C:\> Get-ExecutionPolicy
Restricted
PS C:\> Set-ExecutionPolicy RemoteSigned
Execution Policy Change
The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): Y

Now we are able to start a remote Powershell session to Office 365:

PS C:\> $O365Cred = Get-Credential
PS C:\> $O365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $O365Cred -Authentication Basic -AllowRedirection
WARNING: Your connection has been redirected to the following URI:
"https://ps.outlook.com/PowerShell-LiveID?PSVersion=4.0 "
PS C:\> Import-PSSession $O365Session -AllowClobber
WARNING: The names of some imported commands from the module 'tmp_eiaj1j0m.dcw' include unapproved verbs that might
make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the
Verbose parameter. For a list of approved verbs, type Get-Verb.
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     1.0        tmp_eiaj1j0m.dcw                    {Add-AvailabilityAddressSpace, Add-DistributionGroupMember...

Global steps

  1. Create one or multiple service accounts, depending on the number of users using the integration.
  2. Create a mail-enabled universal security group containing the created service account(s).
  3. Delegate calendar permissions to the security group for all users using the integration.

Creating a service account

A service account is needed to access the user's mailboxes. An account can be created in your on-premises Active Directory, or in Azure AD.

On-premises Exchange

Using the Exchange Management Console

Using Powershell

PS C:\> New-Mailbox -DisplayName "MyTimetable" -Name "MyTimetable Exchange Service Account 1" -Alias "sa-mytt-exch-1" -UserPrincipalName "sa-mytt-exch-1@dev.eveoh.local" -Password (Read-Host -AsSecureString "Password") -ResetPasswordOnNextLogon $false
Password: *******

Office 365

Create the account

Using the Azure Management Portal
Using Powershell

Create a service account using the following Powershell command. Of course you can also create an account in the Azure Portal.

PS C:\> Connect-MsolService
PS C:\> New-MsolUser -DisplayName "MyTimetable" -Name "MyTimetable Exchange Service Account 1" -UserPrincipalName "sa-mytt-exch-1@eveoh.onmicrosoft.com" -Password "xxx" -PasswordNeverExpires $true -StrongPasswordRequired $true

Assigning an Exchange Online license

The service account needs to have a Exchange Online license assigned. After assigning a license, the service account will have a mailbox.

Using the Office 365 Admin portal

Using Powershell
PS C:\> Connect-MsolService
PS C:\> Get-MsolAccountSku
AccountSkuId                    ActiveUnits     WarningUnits    ConsumedUnits
------------                    -----------     ------------    -------------
Eveoh:DEVELOPERPACK             1               0               1
Eveoh:ENTERPRISEPACK            5               0               2
PS C:\> Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq "Eveoh:ENTERPRISEPACK"} | ForEach-Object {$_.ServiceStatus}
ServicePlan                             ProvisioningStatus
-----------                             ------------------
INTUNE_O365                             PendingActivation
YAMMER_ENTERPRISE                       PendingInput
RMS_S_ENTERPRISE                        Success
OFFICESUBSCRIPTION                      Success
MCOSTANDARD                             Success
SHAREPOINTWAC                           Success
SHAREPOINTENTERPRISE                    Success
EXCHANGE_S_ENTERPRISE                   Success
PS C:\> $O365Licences = New-MsolLicenseOptions -AccountSkuId Eveoh:ENTERPRISEPACK -DisabledPlans INTUNE_O365, YAMMER_ENTERPRISE, RMS_S_ENTERPRISE, OFFICESUBSCRIPTION, MCOSTANDARD, SHAREPOINTWAC, SHAREPOINTENTERPRISE
PS C:\> Set-MsolUserLicense -UserPrincipalName "sa-mytt-exch-1@eveoh.onmicrosoft.com" -AddLicenses "Eveoh:ENTERPRISEPACK" -LicenseOptions $O365Licences

Creating a mail-enabled universal security group

It is recommended to create a mail-enabled universal security group containing the previously created service account. Microsoft throttles the number of requests allowed to Exchange Web Services on a per account basis. By using multiple service accounts, we are able to increase the number of requests to EWS. In the next step, we will delegate calendar permissions to the security group, instead of delegating permissions to the separate service accounts.

On-premises Exchange

Using the Exchange Management Console

Using Powershell

PS C:\> New-DistributionGroup -Name "Service Accounts MyTimetable Exchange" -Type Security -PrimarySmtpAddress "sa-mytt-exch-secgroup@dev.eveoh.local" -DisplayName "MyTimetable" -MemberDepartRestriction Closed -MemberJoinRestriction Closed
Name                          DisplayName                   GroupType                     PrimarySmtpAddress
----                          -----------                   ---------                     ------------------
Service Accounts MyTimetab... MyTimetable                   Universal, SecurityEnabled    sa-mytt-exch-secgroup@dev....
PS C:\> Set-DistributionGroup -Identity "sa-mytt-exch-secgroup@dev.eveoh.local" -HiddenFromAddressListsEnabled $true
PS C:\> Add-DistributionGroupMember -Identity "sa-mytt-exch-secgroup@dev.eveoh.local" -Member "sa-mytt-exch-1@dev.eveoh.local"

Office 365

Using the Office 365 Admin portal

Using Powershell

PS C:\> New-DistributionGroup -Name "Service Accounts MyTimetable Exchange" -Type Security -PrimarySmtpAddress "sa-mytt-exch-secgroup@eveoh.onmicrosoft.com" -DisplayName "MyTimetable" -MemberDepartRestriction Closed -MemberJoinRestriction Closed
Name                          DisplayName                   GroupType                     PrimarySmtpAddress
----                          -----------                   ---------                     ------------------
Service Accounts MyTimetab... MyTimetable                   Universal, SecurityEnabled    sa-mytt-exch-secgroup@eveo...
PS C:\> Set-DistributionGroup -Identity "sa-mytt-exch-secgroup@eveoh.onmicrosoft.com" -HiddenFromAddressListsEnabled $true
PS C:\> Add-DistributionGroupMember -Identity "sa-mytt-exch-secgroup@eveoh.onmicrosoft.com" -Member "sa-mytt-exch-1@eveoh.onmicrosoft.com"

Delegating calendar permissions to the security group

Finally, we need to give the security group containing the service account(s) delegated calendar permissions on the mailboxes of the users. We assume that all users that are allowed to use the calendar integration are member of an existing security group.

Exchange on-premises

PS C:\> $mailboxes = Get-ADGroupMember -Identity staff | Get-ADUser | ForEach-Object {Get-Mailbox -Identity $_.UserPrincipalName -errorAction silentlyContinue}
PS C:\> $secgroup = "sa-mytt-exch-secgroup@dev.eveoh.local"
foreach ($m in $mailboxes)
{
    $path = ($m | Select-Object -ExpandProperty PrimarySmtpAddress).ToString() + ":\" + (Get-MailboxFolderStatistics $m.UserPrincipalName | Where-Object { $_.Foldertype -eq "Calendar" } | Select-Object -First 1).Name
    $permissions = @(Get-MailboxFolderPermission -Identity $path -User $secgroup -ErrorAction SilentlyContinue).count
    if ($permissions -eq 0) {
        # not in ACL, add permission
        Add-MailboxFolderPermission -Identity $path -User $secgroup -AccessRights Author
    }
    else {
        # user is already in ACL, change permission
        Set-MailboxFolderPermission -Identity $path -User $secgroup -AccessRights Author
    }
}

Office 365

PS C:\> Get-MsolGroup | Where-Object {$_.DisplayName -eq "Staff"}
ObjectId                               DisplayName                GroupType                  Description
--------                               -----------                ---------                  -----------
64731c32-f1df-4b92-8dbe-1809c23ff85b   Staff                      Security
PS C:\> $mailboxes = Get-MsolGroupMember -GroupObjectId 64731c32-f1df-4b92-8dbe-1809c23ff85b | Get-MsolUser | ForEach-Object {Get-Mailbox -Identity $_.UserPrincipalName -errorAction silentlyContinue}
PS C:\> $secgroup = "sa-mytt-exch-secgroup@eveoh.onmicrosoft.com"
foreach ($m in $mailboxes)
{
    $path = $m.PrimarySmtpAddress + ":\" + (Get-MailboxFolderStatistics $m.PrimarySmtpAddress | Where-Object { $_.Foldertype -eq "Calendar" } | Select-Object -First 1).Name
    $permissions = @(Get-MailboxFolderPermission -Identity $path -User $secgroup -ErrorAction SilentlyContinue).count
    if ($permissions -eq 0) {
        # not in ACL, add permission
        Add-MailboxFolderPermission -Identity $path -User $secgroup -AccessRights Author
    }
    else {
        # user is already in ACL, change permission
        Set-MailboxFolderPermission -Identity $path -User $secgroup -AccessRights Author
    }
}