MicrosoftGraphAPI.psm1

<#
.Synopsis
    Get a oAuth token to access Microsoft Graph API
.DESCRIPTION
    Get a oAuth token to access Microsoft Graph API. Token will be valid for 2 hours.
.EXAMPLE
    Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
.NOTES
This is a preview/beta version. Please send any comments to jgs@coretech.dk
Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
#>

function Get-GraphAuthToken {
    [CmdletBinding(DefaultParameterSetName = 'Default', 
        SupportsShouldProcess = $false, 
        PositionalBinding = $false,
        HelpUri = 'http://www.runbook.guru/')]
    param (
        #"Name": "AADTenantName"
        #"Name": "ClientId"
        #"Name": "RedirectUri"
        #"Name": "UserName"
        #"Name": "Password"
        [Parameter(Mandatory = $true, ParameterSetName = 'User')] 
        [Parameter(Mandatory = $true, ParameterSetName = 'App')] 
        [String] $AADTenant, 
        [Parameter(Mandatory = $true, ParameterSetName = 'User')] 
        [String] $RedirectUri, 
        [Parameter(Mandatory = $true, ParameterSetName = 'User')]
        [PSCredential] $Credential,
        [Parameter(Mandatory = $true, ParameterSetName = 'User')]
        [Parameter(Mandatory = $true, ParameterSetName = 'App')]
        [String] $ClientId,
        [Parameter(Mandatory = $true, ParameterSetName = 'User')]
        [Parameter(Mandatory = $true, ParameterSetName = 'App')]
        [String] $ClientSecret
    )
  
    <#
   $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
   $uc = new-object Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential -ArgumentList $Credential.Username,$Credential.Password
 
   $authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,$uc)
   #>

    <# try {
        $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
        $userCredentials = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential -ArgumentList $Credential.Username, $Credential.Password
        $authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext, $resourceAppIdURI, $ClientId, $userCredentials);
 
 
        $certCredentials = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential -ArgumentList
        if ($authResult.Result.AccessToken) {
            return $authResult.Result
 
        }
        elseif ($authResult.Exception) {
            throw "An error occured getting access token: $($authResult.Exception.InnerException)"
        }
    }
    catch {
        throw $_.Exception.Message
    }
   #>

   

   
    <#Runbook.giuru dev data
$AADTenant = "ba61f14a-6f38-49ac-bb4c-26281ae25fc5"
$clientId = $AppId = "43dc4e3e-0b3f-4e9e-994f-45cdecae827c"
$clientSecret = "h76d3VYy/pM+NfAEUpyXbtMcbsnoT8BWl55TMjHO+nY="
$username = "jakob@runbook.guru"
$passwordSec = "Start123!" | ConvertTo-SecureString -Force -AsPlainText
#>

    $loginURL = "https://login.microsoft.com"
    $resource = "https://graph.microsoft.com"




    switch ($PSCmdlet.ParameterSetName) {
        "User" {
            write-verbose "User mode (delegated)"
            $username = $Credential.UserName
            $passwordSec = $Credential.Password
            $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwordSec)
            $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

            $body = @{
                grant_type    = "password"
                resource      = $resource 
                client_id     = $ClientID 
                client_secret = $ClientSecret
                username      = $UserName
                password      = $Password
            }
            #$body = grant_type=password&username=api%40ws102enablement.onmicrosoft.com&password=xxx&client_id=fd6036fc-b82b-4e19-87b3-4b1bd1557213&scope=files.readwrite.all&client_secret=yyy
        }
        "App" {
            write-verbose "App mode"
            $body = @{
                grant_type = "client_credentials"; 
                resource = $resource; 
                client_id = $ClientID; 
                client_secret = $ClientSecret
            }

        }
    }

    try {
        $oauth = Invoke-RestMethod -Method Post -Uri "$loginURL/$AADTenant/oauth2/token?api-version=1.0" -Body $body
    }
    catch { 
        throw $_.Exception.Message 
    }

    if ($oauth.access_token -ne $null) {
        return $oauth
    }
    else {
        throw "ERROR: No Access Token"
    }
}

<#
.Synopsis
    Invoke a request to the Microsoft Graph API
.DESCRIPTION
    Invoke a request to the Microsoft Graph API using the Token and setting content type to correct format (JSON)
.EXAMPLE
    $Token = Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
    Invoke-GraphRequest -url "https://graph.microsoft.com/beta/subscriptions/303d5e85-d6c2-4c2d-9ed3-bd6b2fb5ecf1" -Token $Token -Method DELETE
.NOTES
    This is a preview/beta version. Please send any comments to jgs@coretech.dk
    Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
#>

Function Invoke-GraphRequest {
    param($Token, $url, $Method, $Body, $customHeaders)
    
    try {
        $headers = @{ }
        $headers.Add('Authorization', 'Bearer ' + $Token)

        if (!$customHeaders) {
            $headers.Add('Content-Type', "application/json")
        }
        else {
            $headers += $customHeaders
        }

        if ($Body) {
            $response = Invoke-WebRequest -Uri $url -Method $Method -Body $Body -Headers $headers -UseBasicParsing
        }
        else {
            $response = Invoke-WebRequest -Uri $url -Method $Method -Headers $headers -UseBasicParsing
        }

        return (ConvertFrom-Json $response.Content)
    }
    catch {
        $CurrentError = $error[0]
        #throw ($error[0].Exception.Response)
        # if ($_.Exception.Response) {
        # try {
        # $result = $_.Exception.Response.GetResponseStream()
        # $reader = New-Object System.IO.StreamReader($result)
        # $responseBody = $reader.ReadToEnd();
        # throw "Error: $($CurrentError.Exception.Message)`n $($CurrentError.InvocationInfo.PositionMessage) - Reponse:`n $responsebody"
        # } catch {
        # throw $CurrentError
        # }
        # }
        # else {
        throw $_
        # }

    }
   
}
Function Invoke-GraphGet {
    [CmdletBinding()]
    param($Token, $url, $Body, $customHeaders, [switch] $All)
            
    try {
        $headers = @{ }
        $headers.Add('Authorization', 'Bearer ' + $Token)
        if (!$customHeaders) {
            $headers.Add('Content-Type', "application/json")
        }
        else {
            $headers += $customHeaders
        }

        $response = Invoke-WebRequest -Uri $url -Method Get -Headers $headers -UseBasicParsing

        $result = (ConvertFrom-Json $response.Content)
         
        $returnList = [System.Collections.ArrayList]::new()
        $null = $returnList.AddRange($result.value)
    
        if ($All) {
            while ($result.'@odata.nextLink') {
                $response = Invoke-WebRequest -Uri $result.'@odata.nextLink' -Method Get -Body $Body -Headers $headers -UseBasicParsing 
                $result = (ConvertFrom-Json $response.Content)
                $null = $returnList.AddRange($result.value)
            } 
        }
        return  $returnList
    }
    catch {
        $CurrentError = $error[0]
        #throw ($error[0].Exception.Response)
        # if ($_.Exception.Response) {
        # $result = $_.Exception.Response.GetResponseStream()
        # $reader = New-Object System.IO.StreamReader($result)
        # $responseBody = $reader.ReadToEnd();
        # throw "Error: $($CurrentError.Exception.Message)`n $($CurrentError.InvocationInfo.PositionMessage) - Reponse:`n $responsebody"
        # }
        # else {
        throw $_
        # }
        
    }
           
}
    
<#
.Synopsis
    Gets a subscription object from Microsoft Graph API
.DESCRIPTION
    Gets a subscription object from Microsoft Graph API
.EXAMPLE
    $Token = Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
    Get-GraphSubscription -Token $Token -SubscriptionId "b539f640-7a5b-462e-960d-e7cb6a3460f6"
.NOTES
    This is a preview/beta version. Please send any comments to jgs@coretech.dk
    Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/resources/subscription/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/api/subscription_get/
#>

Function Get-GraphSubscription {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)] 
        [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult] $Token, 
        [Parameter(Mandatory = $true)] 
        [String] $SubscriptionId
    )
  
    $url = "https://graph.microsoft.com/beta/subscriptions"
    $responseBody = Invoke-GraphRequest -url "https://graph.microsoft.com/beta/subscriptions/$SubscriptionId" -Token $Token -Method Get
    return $responseBody

}

<#
.Synopsis
    Creates a new subscription object in the Microsoft Graph API
.DESCRIPTION
    Creates a new subscription object in the Microsoft Graph API
.EXAMPLE
    $Token = Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
    $webhook = "https://demo.azurewebsites.net/api/webhooks?code=dffdsfdj6pqfrldb6pghzxrihse1zm7vutbj4i&token=VYa2bgSAPCt9NoIx8%2f%2fmG2HrVMvp46vta5Zq6%2bo468Q%3d"
    $resource = "me/mailFolders('Inbox')/messages"
    New-GraphSubscription -Token $Token -ResourceUri $resource -WebhookUri $webhook -ChangeType Created,Deleted,Updated
.NOTES
This is a preview/beta version. Please send any comments to jgs@coretech.dk
Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/resources/subscription/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/api/subscription_post_subscriptions/
#>

Function New-GraphSubscription {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)] 
        [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult] $Token, 
        [Parameter(Mandatory = $true)] 
        [String] $ResourceUri, 
        [Parameter(Mandatory = $true)] 
        [String] $WebhookUri, 
        [ValidateSet("Created", "Updated", "Deleted")]
        [String[]] $ChangeType = "Created", 
        [DateTime] $ExpiratetionDateTime = (get-date).ToUniversalTime().AddMinutes(4230), 
        [String] $ClientState = "DefaultClientState"
    )
  
    $url = "https://graph.microsoft.com/beta/subscriptions"

    $FormattedDate = $ExpiratetionDateTime.ToString("yyyy-MM-ddThh:mm:ss.FFFFFFFZ")

    $Request = @"
{
   "changeType": "$($ChangeType -join ",")",
   "notificationUrl": "$WebhookUri",
   "resource": "$ResourceUri",
   "expirationDateTime":"$FormattedDate",
   "clientState": "$ClientState"
}
"@


    $responseBody = Invoke-GraphRequest -Token $Token -url $Url -Method Post -Body $Request

    return $responseBody

}


<#
.Synopsis
    Removes a subscription object from Microsoft Graph API
.DESCRIPTION
    Removes a subscription object from Microsoft Graph API
.EXAMPLE
    $Token = Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
    Remove-GraphSubscription -Token $Token -SubscriptionId "b539f640-7a5b-462e-960d-e7cb6a3460f6"
.NOTES
    This is a preview/beta version. Please send any comments to jgs@coretech.dk
    Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/resources/subscription/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/api/subscription_delete/
#>

Function Remove-GraphSubscription {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)] 
        [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult] $Token, 
        [Parameter(Mandatory = $true)] 
        [String] $SubscriptionId
    )
  
    $url = "https://graph.microsoft.com/beta/subscriptions"
    $responseBody = Invoke-GraphRequest -url "https://graph.microsoft.com/beta/subscriptions/$SubscriptionId" -Token $Token -Method DELETE
    return $responseBody

}

<#
.Synopsis
Updates a subscription object in Microsoft Graph API
.DESCRIPTION
Updates a subscription object in Microsoft Graph API
.EXAMPLE
$Token = Get-GraphAuthToken -AADTenant "runbookguru.onmicrosoft.com" -ClientId "cdec3c46-b1cd-4ce7-859a-b6fac1ceafee" -RedirectUri "http://www.runbook.guru" -Credential (get-credential)
Remove-GraphSubscription -Token $Token -SubscriptionId "b539f640-7a5b-462e-960d-e7cb6a3460f6"
.NOTES
This is a preview/beta version. Please send any comments to jgs@coretech.dk
Developed by MVP Jakob Gottlieb Svendsen - jakob@runbook.guru - jgs@coretech.dk
.LINK
    http://graph.microsoft.io/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/resources/subscription/
.LINK
    http://graph.microsoft.io/en-us/docs/api-reference/beta/api/subscription_update/
#>

Function Update-GraphSubscription {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)] 
        [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult] $Token, 
        [Parameter(Mandatory = $true)] 
        [String] $SubscriptionId,
        [DateTime] $ExpiratetionDateTime = (get-date).ToUniversalTime().AddMinutes(4230)
    )
  
    $url = "https://graph.microsoft.com/beta/subscriptions"
    $FormattedDate = $ExpiratetionDateTime.ToString("yyyy-MM-ddThh:mm:ss.FFFFFFFZ")

    
    $Request = @"
    {
       "expirationDateTime":"$FormattedDate",
    }
"@


    $responseBody = Invoke-GraphRequest -url "https://graph.microsoft.com/beta/subscriptions/$SubscriptionId" -Token $Token -Method PATCH -Body $Request
    return $responseBody

}