Public/Update-GraphOauthAccessToken.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<#
    .NOTES
    ===========================================================================
     Created with: SAPIEN Technologies, Inc., PowerShell Studio 2017 v5.4.135
     Created on: 2/9/2017 7:43 AM
     Created by: Mark Kraus
     Organization: Mitel
     Filename: Update-GraphOauthAccessToken.ps1
    ===========================================================================
    .DESCRIPTION
        Update-GraphOauthAccessToken Function
#>


<#
    .SYNOPSIS
        Refreshes a Graph Oauth Access Token
    
    .DESCRIPTION
        Requests a refresh of the Graph OAuth Access Token from Graph.
    
    .PARAMETER AccessToken
        Graph OAUth Access Token Object created by Get-GraphOAuthAccessToken.
    
    .PARAMETER BaseUrl
        Base Url for the OAuth Submission end point. This is not required. Defaults to
            https://login.microsoftonline.com/common/oauth2/token
    
    .PARAMETER Force
        By default, a Token will not be renewed if it is not expired. Using force will attempt a token refresh the token even if it is not expired.
    
    .PARAMETER PassThru
        Indicates that the cmdlet sends items from the interactive window down the pipeline as input to other commands. By default, this cmdlet does not generate any output.
    
    .PARAMETER RenewalPeriod
        The renewal period in seconds. The default is 300 (5 minutes). This is the number of seconds before the expiration date that a token will be refreshed. This will prevent the access_token from being expired should the time between the token provider and the local system be offset. If the token is already expired, this will be ignored.

    .EXAMPLE
        PS C:\> $GraphToken = $GraphToken | Update-GraphOAuthAccessToken
    
    .OUTPUTS
        MSGraphAPI.Oauth.AccessToken
    
    .NOTES
        Ses Get-GraphOauthAccessToken for retrieving an OAuth Access Token from Graph

    .LINK
        http://psmsgraph.readthedocs.io/en/latest/functions/Update-GraphOauthAccessToken
    .LINK
        http://psmsgraph.readthedocs.io/en/latest/functions/Get-GraphOauthAccessToken
    .LINK
        http://psmsgraph.readthedocs.io/en/latest/functions/Export-GraphOauthAccessToken
    .LINK
        http://psmsgraph.readthedocs.io/en/latest/functions/Import-GraphOauthAccessToken
#>

function Update-GraphOauthAccessToken {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification = "Converts plaintext returned from API to secure string.")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Impliments Force param. Updates in memory object only.")]
    [CmdletBinding(ConfirmImpact = 'Low',
                   HelpUri = 'http://psmsgraph.readthedocs.io/en/latest/functions/Update-GraphOauthAccessToken')]
    [OutputType('MSGraphAPI.Oauth.AccessToken')]
    param
    (
        [Parameter(Mandatory = $true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [pstypename('MSGraphAPI.Oauth.AccessToken')]
        [Alias('Token')]
        [System.Management.Automation.PSObject[]]$AccessToken,
        
        [Parameter(Mandatory = $false)]
        [ValidateScript({
                [system.uri]::IsWellFormedUriString(
                    $_, [System.UriKind]::Absolute
                )
            })]
        [string]$BaseUrl = 'https://login.microsoftonline.com/common/oauth2/token',
        
        [int]$RenewalPeriod = 300,
        
        [switch]$Force,
        
        [switch]$PassThru
    )
    
    process {
        Foreach ($RefreshToken in $AccessToken) {
            Write-Verbose "Processing token '$($RefreshToken.GUID.ToString())'"
            If (!$AccessToken.isExpired -and !$Force -and (get-date) -lt $AccessToken.Expires.addseconds(-$RenewalPeriod)) {
                Write-Verbose "Token is not expired. Skipping"
                Continue
            }
            $Body = @(
                'grant_type=refresh_token'
                '&redirect_uri={0}' -f [System.Web.HttpUtility]::UrlEncode($RefreshToken.Application.RedirectUri)
                '&client_id={0}' -f [System.Web.HttpUtility]::UrlEncode($RefreshToken.Application.ClientID)
                '&client_secret={0}' -f [System.Web.HttpUtility]::UrlEncode($RefreshToken.Application.GetClientSecret())
                '&refresh_token={0}' -f [System.Web.HttpUtility]::UrlEncode($RefreshToken.GetRefreshToken())
                '&resource={0}' -f [System.Web.HttpUtility]::UrlEncode($RefreshToken.Resource)
            ) -join ''
            $Params = @{
                Uri = $BaseUrl
                WebSession = $RefreshToken.Session
                Method = 'POST'
                Body = $Body
            }
            $RequestTime = Get-Date
            try {
                $WebRequest = Invoke-WebRequest @Params
            }
            catch {
                $ErrorMessage = $_.Exception.Message
                Write-Error "Failed to refresh token: $ErrorMessage"
                continue
            }
            try {
                $Content = $WebRequest.Content | ConvertFrom-Json -ErrorAction Stop
            }
            Catch {
                $ErrorMessage = $_.Exception.Message
                $Message = "Failed to convert response from JSON: {0}" -f $ErrorMessage
                Write-Error $Message
                Write-Error $WebRequest.Content
                return
            }
            $RefreshToken.AccessTokenCredential = [pscredential]::new('access_token', $($Content.access_token | ConvertTo-SecureString -AsPlainText -Force))
            $RefreshToken.Response = $Content | Select-Object -property * -ExcludeProperty access_token, refresh_token
            $RefreshToken.RequestedDate = $RequestTime
            
            if ($PassThru) {
                Write-Verbose "Sending Token to the Pipeline"
                $RefreshToken
            }
        }
    }
}