Build PowerShell scripts with Microsoft Graph
This tutorial teaches you how to build a PowerShell script that uses the Microsoft Graph API to access data on behalf of a user.
Note
To learn how to use Microsoft Graph to access data using app-only authentication, see this app-only authentication tutorial.
In this tutorial, you will:
Tip
As an alternative to following this tutorial, you can download the completed code through the quick start tool, which automates app registration and configuration. The downloaded code works without any modifications required.
You can also download or clone the GitHub repository and follow the instructions in the README to register an application and configure the project.
Prerequisites
Before you start this tutorial, you should have PowerShell installed on your development machine. PowerShell 5.1 is the minimum requirement, but PowerShell 7 is recommended.
You should also have a Microsoft work or school account with an Exchange Online mailbox. If you don't have a Microsoft 365 tenant, you might qualify for one through the Microsoft 365 Developer Program; for details, see the FAQ. Alternatively, you can sign up for a 1-month free trial or purchase a Microsoft 365 plan.
Note
This tutorial was written with PowerShell 7.2.2 and Microsoft Graph PowerShell SDK version 1.9.5. The steps in this guide may work with other versions, but that has not been tested.
Register the app in the portal
In this exercise you will register a new application in Azure Active Directory to enable user authentication. You can register an application using the Microsoft Entra admin center, or by using the Microsoft Graph PowerShell SDK.
Register application for user authentication
In this section you will register an application that supports user authentication using device code flow.
Note
Registering an application for user authentication for the Microsoft Graph PowerShell SDK is optional. The SDK has it's own application registration and corresponding client ID. However, using your own application ID allows for greater control over permission scopes for a particular PowerShell script.
Open a browser and navigate to the Microsoft Entra admin center and login using a Global administrator account.
Select Microsoft Entra ID in the left-hand navigation, expand Identity, expand Applications, then select App registrations.
Select New registration. Enter a name for your application, for example,
Graph User Auth Tutorial
.Set Supported account types as desired. The options are:
Option Who can sign in? Accounts in this organizational directory only Only users in your Microsoft 365 organization Accounts in any organizational directory Users in any Microsoft 365 organization (work or school accounts) Accounts in any organizational directory ... and personal Microsoft accounts Users in any Microsoft 365 organization (work or school accounts) and personal Microsoft accounts Leave Redirect URI empty.
Select Register. On the application's Overview page, copy the value of the Application (client) ID and save it, you will need it in the next step. If you chose Accounts in this organizational directory only for Supported account types, also copy the Directory (tenant) ID and save it.
Select Authentication under Manage. Locate the Advanced settings section and change the Allow public client flows toggle to Yes, then choose Save.
Note
Notice that you did not configure any Microsoft Graph permissions on the app registration. This is because the sample uses dynamic consent to request specific permissions for user authentication.
Add user authentication
In this section you will authenticate a PowerShell session as a user for Microsoft Graph. This is required to obtain the necessary OAuth access token to call the Microsoft Graph.
The Microsoft Graph PowerShell SDK provides two authentication methods for user authentication: interactive browser and device code authentication. Interactive browser authentication uses a device's default browser to allow the user to sign in. Device code authentication allows authentication in environments that do not have a default browser. In this exercise you will use device code authentication.
Important
If you do not already have the Microsoft Graph PowerShell SDK installed, install it now before proceeding.
Authenticate the user
Open PowerShell and use the following command to set the
$clientID
session variable, replacing <your-client-id> with the client ID of your app registration.$clientId = <your-client-id>
Set the
$tenantId
session variable. If you chose the option to only allow users in your organization to sign in when registering your application, replace <tenant-id> with your organization's tenant ID. Otherwise, replace withcommon
.$tenantId = <tenant-id>
Set the
$graphScopes
session variable.$graphScopes = "user.read mail.read mail.send"
Use the following command to authenticate the user inside the current PowerShell session.
# Authenticate the user Connect-MgGraph -ClientId $clientId -TenantId $tenantId -Scopes $graphScopes -UseDeviceAuthentication
Tip
If you would prefer to use interactive browser authentication, omit the
-UseDeviceAuthentication
parameter.Open a browser and browse to the URL displayed. Enter the provided code and sign in.
Important
Be mindful of any existing Microsoft 365 accounts that are logged into your browser when browsing to
https://microsoft.com/devicelogin
. Use browser features such as profiles, guest mode, or private mode to ensure that you authenticate as the account you intend to use for testing.Once completed, return to the PowerShell window. Run the following command to verify the authenticated context.
# Get the Graph context Get-MgContext
ClientId : 2fb1652f-a9a0-4db9-b220-b224b8d9d38b TenantId : 601faea3-be45-4960-898f-92b379b17cd9 CertificateThumbprint : Scopes : {Mail.Read, Mail.Send, openid, profile…} AuthType : Delegated AuthProviderType : DeviceCodeProvider CertificateName : Account : [email protected] AppName : PowerShell Graph Tutorial ContextScope : CurrentUser Certificate : PSHostVersion : 2022.4.1 ClientTimeout : 00:05:00
Get user
In this section you will get the authenticated user.
In your authenticated PowerShell session, run the following command to get the current context. The context provides information to identify the authenticated user.
$context = Get-MgContext
Run the following command to get the user from Microsoft Graph.
# Get the authenticated user by UPN $user = Get-MgUser -UserId $context.Account -Select 'displayName, id, mail, userPrincipalName'
Tip
You can add the
-Debug
switch to the previous command to see the API request and response.Run the following commands to output user information.
Write-Host "Hello," $user.DisplayName # For Work/school accounts, email is in Mail property # Personal accounts, email is in UserPrincipalName Write-Host "Email:", ($user.Mail ?? $user.UserPrincipalName)
Hello, Megan Bowen! Email: [email protected]
Code explained
Consider the command used to get the authenticated user. It's a seemingly simple command, but there are some key details to notice.
Accessing 'me'
The Get-MgUser
command builds a request to the Get user API. This API is accessible two ways:
GET /me
GET /users/{user-id}
The Microsoft Graph PowerShell SDK does not support the GET /me
API endpoint. In order to use the GEt /users/{user-id}
endpoint, we must provide a value for the {user-id}
parameter. In the example above, the $context.Account
value is used. This value contains the authenticated user's user principal name (UPN).
Requesting specific properties
The function uses the -Select
parameter on the command to specify the set of properties it needs. This adds the $select query parameter to the API call.
Strongly-typed return type
The function returns a MicrosoftGraphUser
object deserialized from the JSON response from the API. Because the command uses -Select
, only the requested properties will have values in the returned object. All other properties will have default values.
List inbox
In this section you will list messages in the user's email inbox.
In your authenticated PowerShell session, verify that the
$user
variable is set.PS > $user.DisplayName Megan Bowen
Run the following command to list the user's inbox.
Get-MgUserMailFolderMessage -UserId $user.Id -MailFolderId Inbox -Select ` "from,isRead,receivedDateTime,subject" -OrderBy "receivedDateTime DESC" ` -Top 25 | Format-Table Subject,@{n='From';e={$_.From.EmailAddress.Name}}, ` IsRead,ReceivedDateTime
Review the output.
Subject From IsRead ReceivedDateTime ------- ---- ------ ---------------- Updates from Ask HR and other communities Contoso Demo on Yammer False 4/19/2022 10:19:02 PM Employee Initiative Thoughts Patti Fernandez False 4/19/2022 3:15:56 PM Voice Mail (11 seconds) Alex Wilber False 4/18/2022 2:24:16 PM Our Spring Blog Update Alex Wilber True 4/18/2022 1:52:03 PM Atlanta Flight Reservation Alex Wilber False 4/13/2022 2:30:27 AM Atlanta Trip Itinerary - down time Alex Wilber False 4/12/2022 4:46:01 PM
Code explained
Consider the command used to list the user's inbox
Accessing well-known mail folders
The Get-MgUserMailFolderMessage
command builds a request to the List messages API, specifically using the GET /users/{user-id}/mailFolders/{folder-id}/messages
endpoint. Using that endpoint, the API only returns messages in the requested mail folder. In this case, because the inbox is a default, well-known folder inside a user's mailbox, it's accessible via its well-known name: -MailFolderId Inbox
. Non-default folders are accessed the same way, by replacing the well-known name with the mail folder's ID property. For details on the available well-known folder names, see mailFolder resource type.
Accessing a collection
Unlike the Get-MgUser
command from the previous section, which returns a single object, this method returns a collection of messages. Most APIs in Microsoft Graph that return a collection do not return all available results in a single response. Instead, they use paging to return a portion of the results while providing a method for clients to request the next "page".
Default page sizes
APIs that use paging implement a default page size. For messages, the default value is 10. Clients can request more (or less) by using the $top query parameter. In the Microsoft Graph PowerShell SDK, this is accomplished with the -Top 25
parameter.
Note
The value passed via -Top
is an upper-bound, not an explicit number. The API returns a number of messages up to the specified value.
Sorting collections
The function uses the -OrderBy
parameter on the request to request results sorted by the time the message is received (receivedDateTime
property). It includes the DESC
keyword so that messages received more recently are listed first. This adds the $orderby query parameter to the API call.
Send mail
In this section you will send an email message as the authenticated user.
In your authenticated PowerShell session, verify that the
$user
variable is set.PS > $user.DisplayName Megan Bowen
Use the following command to define an object representing the request body for the Send mail API.
$sendMailParams = @{ Message = @{ Subject = "Testing Microsoft Graph" Body = @{ ContentType = "text" Content = "Hello world!" } ToRecipients = @( @{ EmailAddress = @{ Address = ($user.Mail ?? $user.UserPrincipalName) } } ) } }
Use the following command to send the message.
Send-MgUserMail -UserId $user.Id -BodyParameter $sendMailParams
Note
If you are testing with a developer tenant from the Microsoft 365 Developer Program, the email you send might not be delivered, and you might receive a non-delivery report. If this happens to you, please contact support via the Microsoft 365 admin center.
To verify the message was received, repeat the
Get-MgUserMailFolderMessage
command from the previous step.
Code explained
Consider the commands used to send a message.
Sending mail
The Send-MgUserMail
command builds a request to the Send mail API.
Creating objects
Unlike the previous calls to Microsoft Graph that only read data, this call creates data. To do this with the SDK you create an object representing the request body, set the desired properties, then pass it in the BodyParameter
parameter.
Optional: add your own code
In this section you will use your own Microsoft Graph PowerShell SDK commands. This could be a code snippet from Microsoft Graph documentation or Graph Explorer, or code that you created. This section is optional.
Choose an API
Find an API in Microsoft Graph you'd like to try. For example, the Create event API. You can use one of the examples in the API documentation, customize an API request in Graph Explorer and use the generated snippet, or use the Find-MgGraphCommand
command to find the corresponding command.
For example, one of the API endpoints to create an event is POST /users/{id | userPrincipalName}/events
. You can use this to find the corresponding PowerShell command.
PS > Find-MgGraphCommand -Uri "/users/{id | userPrincipalName}/events" -Method "POST"
APIVersion: v1.0
Command Module Method URI OutputType Permissions Variants
------- ------ ------ --- ---------- ----------- --------
New-MgUserEvent Calendar POST /users/{user-id}/events IMicrosoftGraphEvent {Calendars.ReadWrite} {Create1, CreateExp…
APIVersion: beta
Command Module Method URI OutputType Permissions Variants
------- ------ ------ --- ---------- ----------- --------
New-MgUserEvent Calendar POST /users/{user-id}/events IMicrosoftGraphEvent1 {Calendars.ReadWrite} {Create, CreateExp…
The output indicates that the New-MgUserEvent
command is the corresponding command.
Configure permissions
Check the Permissions section of the reference documentation for your chosen API to see which authentication methods are supported. Some APIs don't support user (delegated) authentication, or personal Microsoft accounts, for example.
Disconnect the current session (Disconnect-MgGraph
) and reconnect with the required permission in the -Scopes
parameter.
Tip
Using the -ForceRefresh
parameter with the Connect-MgGraph
command ensures that newly configured permissions are applied.
Run the command
Now that you are connected with the required permissions, run your chosen command.
Congratulations!
You've completed the PowerShell Microsoft Graph tutorial. Now that you have a working app that calls Microsoft Graph, you can experiment and add new features.
- Learn how to use app-only authentication with the Microsoft Graph PowerShell SDK.
- Visit the Overview of Microsoft Graph to see all of the data you can access with Microsoft Graph.
Have an issue with this section? If so, please give us some feedback so we can improve this section.