Graph API & PowerShell: Function To Use A Refresh Token To Renew An Access Token

In the process of updating my library of standard scripts and functions, I’ve taken the opportunity to change a lot of them to use Graph API rather than legacy EWS or PowerShell Modules. Using Graph helps to make them much more efficient and flexible and a lot of the functionality that I need is there anyway.

One challenge I came across with Graph was when running with delegated permissions and avoiding authenticating constantly for unattended scripts. When running as an app we can pipe in our App Registration details and away we go but when you bring delegated permissions and MFA into the loop, that becomes a challenge.

I’ve put together the below function (located here on GitHub) to allow me to use a refresh token and renew my access token to keep access alive. When using access tokens, they will by default last for an hour, needing to be renewed after that. Refresh tokens (which last 14 days) can then be used to renew this access token and get a new refresh token in the process.

The function itself takes in the following values:

-Token: The existing refresh token

-tenantID: The ID of your tenant (

-ClientID: Client ID of your App Reg

-Secret: The secret of your app reg

-Scope: A comma delimited list of your access scope

It will then pass back a new token object complete with renewed access and refresh tokens. I generally store these tokens in Azure Key Vault and update them at refresh time. This means my apps can refresh tokens when they need to and save them securely, only accessing at run time.

function RefreshAccessToken{



Refreshes an access token based on refresh token


Returns a refreshed access token


-Token is the existing refresh token


-This is the tenant ID eg.


-This is the app reg client ID


-This is the client secret


-A comma delimited list of access scope, default is: "Group.ReadWrite.All,User.ReadWrite.All"



[parameter(Mandatory = $true)]



[parameter(Mandatory = $true)]



[parameter(Mandatory = $true)]



[parameter(Mandatory = $false)]


$Scope = "Group.ReadWrite.All,User.ReadWrite.All",

[parameter(Mandatory = $true)]




$ScopeFixup = $Scope.replace(',','%20')

$apiUri = "$tenantID/oauth2/v2.0/token"

$body = "client_id=$ClientID&scope=$ScopeFixup&refresh_token=$Token&redirect_uri=http%3A%2F%2Flocalhost%2F&grant_type=refresh_token&client_secret=$Secret"

write-verbose $body -Verbose

$Refreshedtoken = (Invoke-RestMethod -Uri $apiUri -Method Post -ContentType 'application/x-www-form-urlencoded' -body $body )

return $Refreshedtoken


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s