Skip to content

t3blake/working-time-cmdlets

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 

Repository files navigation

WorkingTimeCmdlets

PowerShell cmdlets for managing Microsoft 365 frontline worker working time via the Microsoft Graph workingTimeSchedule API.

Sends start-of-shift and end-of-shift signals to Microsoft Graph, which Intune app protection policies act on (blocking or warning users outside of working hours). These cmdlets control the signal — they don't define a schedule.


Prerequisites

Requirement Notes
PowerShell 7+ Install
Microsoft.Graph.Authentication module Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Entra ID app registration With application permissions — see App Registration
Intune app protection policy Required for the signals to have any effect — see App Protection Policies

App Registration

The workingTimeSchedule API requires application permissions (not delegated). You need an Entra ID app registration with client credentials.

Required permissions

Permission Type App Role ID
Schedule-WorkingTime.ReadWrite.All Application 0b21c159-dbf4-4dbb-a6f6-490e412c716e
User.Read.All Application df021288-bdef-4463-88db-98f22de89214

Both permissions require admin consent.

Creating an app registration

If you don't have an existing app registration, here's how to create one:

  1. Go to Entra admin centerApp registrationsNew registration
  2. Name it anything (e.g., "Working Time Cmdlets")
  3. Set Supported account types to "Accounts in this organizational directory only"
  4. Click Register
  5. Go to API permissionsAdd a permissionMicrosoft GraphApplication permissions
  6. Add User.Read.All
  7. For Schedule-WorkingTime.ReadWrite.All: this permission is hidden in the UI. Grant it via PowerShell:
    # Connect with admin permissions
    Connect-MgGraph -Scopes "Application.ReadWrite.All", "AppRoleAssignment.ReadWrite.All"
    
    # Get your app's service principal
    $sp = Get-MgServicePrincipal -Filter "appId eq '<YOUR_APP_CLIENT_ID>'"
    $graphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
    
    # Grant the permission
    New-MgServicePrincipalAppRoleAssignment `
        -ServicePrincipalId $sp.Id `
        -PrincipalId $sp.Id `
        -ResourceId $graphSp.Id `
        -AppRoleId "0b21c159-dbf4-4dbb-a6f6-490e412c716e"
  8. Click Grant admin consent for User.Read.All (the other was consented via the PowerShell command above)
  9. Go to Certificates & secrets → create a client secret or upload a certificate

Installation

From source

git clone https://github.com/t3blake/working-time-cmdlets.git
Import-Module ./working-time-cmdlets/WorkingTimeCmdlets

Copy to your modules path (optional)

Copy-Item -Recurse ./working-time-cmdlets/WorkingTimeCmdlets "$HOME/Documents/PowerShell/Modules/"

Then it loads automatically:

Import-Module WorkingTimeCmdlets

Connecting

Connect to Microsoft Graph with your app registration before using any cmdlets. The module does not manage connections — use Connect-MgGraph however you prefer.

With a client secret

$secret = ConvertTo-SecureString "your-client-secret" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("your-client-id", $secret)

Connect-MgGraph -TenantId "your-tenant-id" -ClientSecretCredential $credential

With a certificate

Connect-MgGraph -TenantId "your-tenant-id" -ClientId "your-client-id" -CertificateThumbprint "your-thumbprint"

Usage

Check a user's working time schedule

Get-WorkingTimeSchedule -UserId "john.doe@contoso.com"
UserId                  Status        Id
------                  ------        --
john.doe@contoso.com    Configured    da5f72af-450e-56fc-10d7-afc9acb40cc0

If the user doesn't have a schedule configured yet:

Get-WorkingTimeSchedule -UserId "jane.smith@contoso.com"
UserId                   Status           Id
------                   ------           --
jane.smith@contoso.com   NotConfigured

Check multiple users at once

"john.doe@contoso.com", "jane.smith@contoso.com" | Get-WorkingTimeSchedule
UserId                   Status           Id
------                   ------           --
john.doe@contoso.com     Configured       da5f72af-450e-56fc-10d7-afc9acb40cc0
jane.smith@contoso.com   NotConfigured

Start working time (on-shift)

Signal that a user's working hours have started. This triggers Intune's "on-shift" app protection policies.

Start-WorkingTime -UserId "john.doe@contoso.com"
UserId                  Action              Result
------                  ------              ------
john.doe@contoso.com    StartWorkingTime    Success

Stop working time (off-shift)

Signal that a user's working hours have ended. This triggers Intune's "off-shift" app protection policies (e.g., blocking app access).

Stop-WorkingTime -UserId "john.doe@contoso.com"
UserId                  Action              Result
------                  ------              ------
john.doe@contoso.com    StopWorkingTime     Success

Bulk operations with Get-MgUser

Pipe users from Get-MgUser to any cmdlet. Useful for targeting a department, group, or filtered set of users.

# End the shift for all users in the Retail department
Get-MgUser -Filter "department eq 'Retail'" | Stop-WorkingTime
UserId                      Action              Result
------                      ------              ------
john.doe@contoso.com        StopWorkingTime     Success
jane.smith@contoso.com      StopWorkingTime     Success
alex.jones@contoso.com      StopWorkingTime     Success
# Start the shift for a specific set of users
Get-MgUser -Filter "city eq 'Seattle'" | Start-WorkingTime

Bulk operations from a file

Create a text file with one UPN per line:

john.doe@contoso.com
jane.smith@contoso.com
alex.jones@contoso.com

Then pipe it in:

Get-Content users.txt | Stop-WorkingTime

Preview changes with WhatIf

Start-WorkingTime and Stop-WorkingTime support -WhatIf to preview what would happen without making any changes:

Get-MgUser -Filter "department eq 'Retail'" | Stop-WorkingTime -WhatIf
What if: Performing the operation "Stop working time" on target "john.doe@contoso.com".
What if: Performing the operation "Stop working time" on target "jane.smith@contoso.com".
What if: Performing the operation "Stop working time" on target "alex.jones@contoso.com".

Demo / testing workflow

For testing Intune app protection policies on a specific device:

# 1. Connect to Graph
$secret = ConvertTo-SecureString "your-client-secret" -AsPlainText -Force
$cred = New-Object PSCredential("your-client-id", $secret)
Connect-MgGraph -TenantId "contoso.onmicrosoft.com" -ClientSecretCredential $cred

# 2. Import the module
Import-Module ./WorkingTimeCmdlets

# 3. Check current status
Get-WorkingTimeSchedule -UserId "john.doe@contoso.com"

# 4. Signal off-shift — the user's device should now show restrictions
Stop-WorkingTime -UserId "john.doe@contoso.com"

# 5. Signal on-shift — restrictions should lift
Start-WorkingTime -UserId "john.doe@contoso.com"

App Protection Policies

These cmdlets control the signal (on-shift / off-shift). For the signal to have any effect, you need Intune app protection policies configured with non-working-time conditions.

Without a policy, the start/end calls succeed but nothing happens on the device.

See: Configure app protection policies for working time


Troubleshooting

Error Cause Fix
"Not connected to Microsoft Graph" No Connect-MgGraph session Run Connect-MgGraph with client credentials
"Connected with delegated permissions" Used interactive/delegated auth Reconnect with -ClientSecretCredential or -CertificateThumbprint
"Access denied" / 403 Missing permission or no admin consent Add Schedule-WorkingTime.ReadWrite.All and User.Read.All with admin consent
NotConfigured status on GET No schedule resource for that user Expected for users not targeted by a working time policy
"Not found" / 404 on Start/End Invalid user ID or UPN Verify the user exists in the tenant

Cmdlet Reference

Cmdlet Description Pipeline
Get-WorkingTimeSchedule Get schedule status for a user Accepts -UserId from pipeline
Start-WorkingTime Signal start of working hours (on-shift) Accepts -UserId from pipeline
Stop-WorkingTime Signal end of working hours (off-shift) Accepts -UserId from pipeline

All cmdlets accept UPN (user@contoso.com) or Entra object ID as -UserId. Pipeline input works from strings, Get-MgUser output, or any object with UserPrincipalName or Id properties.

About

PowerShell cmdlets for managing Microsoft 365 frontline worker working time via Microsoft Graph

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors