Skip to content

Instantly share code, notes, and snippets.

@sebastienlevert
Last active May 1, 2021 05:11
Show Gist options
  • Save sebastienlevert/3131c19b63ca1be2101f to your computer and use it in GitHub Desktop.
Save sebastienlevert/3131c19b63ca1be2101f to your computer and use it in GitHub Desktop.
Call Office 365 API Endpoints from PowerShell
<#
.DESCRIPTION
Gets an access token for an App-Only Azure AD Application
.PARAMETER TenantId
The TenantId of the Azure AD Application
Can be set globally with $global:AzureADApplicationTenantId
.PARAMETER ClientId
The ClientId of the Azure AD Application
Can be set globally with $global:AzureADApplicationClientId
.PARAMETER CertificatePath
The path to the *.pfx certificate used in your Azure AD Application
Can be set globally with $global:AzureADApplicationCertificatePath
.PARAMETER CertificatePassword
The password used to secure your *.pfx certificate
Can be set globally with $global:AzureADApplicationCertificatePassword
.PARAMETER ResourceUri
The resource URI you want to authenticate against
.EXAMPLE
Get-AccessToken -TenantId "00000000-0000-0000-0000-000000000000" -ClientId "00000000-0000-0000-0000-000000000000" -CertificatePath "C:\Certificate.pfx" -CertificatePassword "Password" -ResourceUri "https://outlook.office365.com/"
.EXAMPLE
Get-AccessToken -ResourceUri "https://outlook.office365.com/"
#>
function Get-AccessToken()
{
Param(
[Parameter(Mandatory=$true, ParameterSetName="UseLocal")]
[Parameter(Mandatory=$false, ParameterSetName="UseGlobal")]
[ValidateNotNullOrEmpty()]
[String]
$TenantId = $global:AzureADApplicationTenantId,
[Parameter(Mandatory=$true, ParameterSetName="UseLocal")]
[Parameter(Mandatory=$false, ParameterSetName="UseGlobal")]
[ValidateNotNullOrEmpty()]
[String]
$ClientId = $global:AzureADApplicationClientId,
[Parameter(Mandatory=$true, ParameterSetName="UseLocal")]
[Parameter(Mandatory=$false, ParameterSetName="UseGlobal")]
[ValidateNotNullOrEmpty()]
[String]
$CertificatePath = $global:AzureADApplicationCertificatePath,
[Parameter(Mandatory=$true, ParameterSetName="UseLocal")]
[Parameter(Mandatory=$false, ParameterSetName="UseGlobal")]
[ValidateNotNullOrEmpty()]
[String]
$CertificatePassword = $global:AzureADApplicationCertificatePassword,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$ResourceUri
)
#region Validations
#-----------------------------------------------------------------------
# Validating the TenantId
#-----------------------------------------------------------------------
if(!(Is-Guid -Value $TenantId))
{
throw [Exception] "TenantId '$TenantId' is not a valid Guid"
}
#-----------------------------------------------------------------------
# Validating the ClientId
#-----------------------------------------------------------------------
if(!(Is-Guid -Value $ClientId))
{
throw [Exception] "ClientId '$ClientId' is not a valid Guid"
}
#-----------------------------------------------------------------------
# Validating the Certificate Path
#-----------------------------------------------------------------------
if(!(Test-Path -Path $CertificatePath))
{
throw [Exception] "CertificatePath '$CertificatePath' does not exist"
}
#-----------------------------------------------------------------------
# Validating the availability of Azure Active Directory Assemblies
#-----------------------------------------------------------------------
if(!(Test-Path -Path "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"))
{
throw [Exception] "Azure Active Directory Assemblies are not available"
}
#endregion
#region Initialization
#-----------------------------------------------------------------------
# Loads the Azure Active Directory Assemblies
#-----------------------------------------------------------------------
Add-Type -Path "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" | Out-Null
#-----------------------------------------------------------------------
# Constants
#-----------------------------------------------------------------------
$keyStorageFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet
#-----------------------------------------------------------------------
# Building required values
#-----------------------------------------------------------------------
$authorizationUriFormat = "https://login.windows.net/{0}/oauth2/authorize"
$authorizationUri = [String]::Format($authorizationUriFormat, $TenantId)
#endregion
#region Process
#-----------------------------------------------------------------------
# Building the necessary context to acquire the Access Token
#-----------------------------------------------------------------------
$authenticationContext = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authorizationUri, $false
$certificate = New-Object -TypeName "System.Security.Cryptography.X509Certificates.X509Certificate2" -ArgumentList $CertificatePath, $CertificatePassword, $keyStorageFlags
$assertionCertificate = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate" -ArgumentList $ClientId, $certificate
#-----------------------------------------------------------------------
# Ask for the AccessToken based on the App-Only configuration
#-----------------------------------------------------------------------
$authenticationResult = $authenticationContext.AcquireToken($ResourceUri, $assertionCertificate)
#-----------------------------------------------------------------------
# Returns the an AccessToken valid for an hour
#-----------------------------------------------------------------------
return $authenticationResult.AccessToken
#endregion
}
<#
.DESCRIPTION
Invokes a REST Method by including its Access Token as Bearer
.PARAMETER Method
The Method to use on the Request
.PARAMETER AccessToken
The AccessToken to inject in the Request Headers
.PARAMETER EndpointUri
The Endpoint Uri to make the Request upon
.EXAMPLE
Invoke-SecuredRestMethod -Method "GET" -AccessToken "" -EndpointUri "https://outlook.office365.com/api/v1.0/users('admin@tenant.onmicrosoft.com')/folders/inbox/messages"
#>
function Invoke-SecuredRestMethod()
{
Param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$Method,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$AccessToken,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$EndpointUri
)
$headers = @{ "Authorization" = [String]::Format("Bearer {0}", $AccessToken) }
$results = Invoke-RestMethod -Uri $EndpointUri -Method $Method -Headers $headers
return $results
}
<#
.DESCRIPTION
Validates if a specified String is a Guid
.PARAMETER Value
The value to validate
.EXAMPLE
Is-Guid -Value "00000000-0000-0000-0000-000000000000"
#>
function Is-Guid()
{
Param(
[Parameter()]
[String]
$Value
)
$guid = [System.Guid]::Empty
return [System.Guid]::TryParse($Value, [ref]$guid)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment