Public/Get-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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<#
    .NOTES
    ===========================================================================
     Created with: SAPIEN Technologies, Inc., PowerShell Studio 2017 v5.4.135
     Created on: 2/8/2017 10:26 AM
     Created by: Mark Kraus
     Organization: Mitel
     Filename: Get-GraphOauthAccessToken.ps1
    ===========================================================================
    .DESCRIPTION
        Get-GraphOauthAccessToken Function
#>


<#
    .SYNOPSIS
        Retieves an OAuth Access Token from Microsoft
    
    .DESCRIPTION
        A detailed description of the Get-GraphOauthAccessToken function.
    
    .PARAMETER AuthenticationCode
        The Authentication Code returned from Get-GraphOauthAuthorizationCode
    
    .PARAMETER BaseURL
        The Base URL used for retrieving OAuth Acces Tokens. This is not required. the default is
        
        https://login.microsoftonline.com/common/oauth2/token
    
    .PARAMETER Resource
        The resource for which the OAuth Access token will be requested. The default is
        
            https://graph.microsoft.com
    
        You must set the resource to match the endpoints your token will be valid for.

            Microsft Graph: https://outlook.office.com
            Azure AD Graph API: https://graph.windows.net
            Office 365 Unified Mail API: https://outlook.office.com
        
        If you need to access more than one resrouce, you will need to request multiple OAuth Access Tokens and use the correct tokens for the correct endpoints.
    
    .PARAMETER ResultVariable
        Name of a varibale to store the result from the Invoke-WebRequest. This should be used for debugging only as it stores the access_token and refresh_tokens in memory as plain text.
    
    .EXAMPLE
        PS C:\> $GraphAccessToken = Get-GraphOauthAccessToken -AuthenticationCode $GraphAuthCode
    
    .OUTPUTS
        MSGraphAPI.Oauth.AccessToken
    
    .NOTES
        See Export-GraphOauthAccessToken for exporting Graph Acess Token Objects
        See Import-GraphOauthAccessToken for importing exported Graph AcessToken Objects
        See Update-GraphOauthAccessToken for refreshing the Graph Access Token
    
    .LINK
        Export-GraphOauthAccessToken
        Import-GraphOauthAccessToken
        Update-GraphOauthAccessToken
#>

function Get-GraphOauthAccessToken {
    [CmdletBinding(ConfirmImpact = 'Low',
                   SupportsShouldProcess = $true)]
    [OutputType('MSGraphAPI.Oauth.AccessToken')]
    param
    (
        [Parameter(Mandatory = $true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [pstypename('MSGraphAPI.Oauth.AuthorizationCode')]
        [ValidateNotNullOrEmpty()]
        [Alias('AuthCode')]
        $AuthenticationCode,
        
        [Parameter(Mandatory = $false,
                   ValueFromPipelineByPropertyName = $true)]
        [Alias('URL')]
        [string]$BaseURL = 'https://login.microsoftonline.com/common/oauth2/token',
        
        [Parameter(Mandatory = $false,
                   ValueFromPipelineByPropertyName = $true)]
        [string]$Resource = 'https://graph.microsoft.com',
        
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$ResultVariable
    )
    
    Process {
        $Application = $AuthenticationCode.Application
        if (-not $pscmdlet.ShouldProcess($Application.ClientID)) {
            return
        }
        $Client_Id = [System.Web.HttpUtility]::UrlEncode($Application.ClientID)
        $Redirect_uri = [System.Web.HttpUtility]::UrlEncode($Application.RedirectUri)
        $Resource_encoded = [System.Web.HttpUtility]::UrlEncode($Resource)
        $AuthCode = [System.Web.HttpUtility]::UrlEncode($AuthenticationCode.GetAuthCode())
        $Body = @(
            'grant_type=authorization_code'
            '&redirect_uri={0}&' -f $Redirect_uri
            '&client_id={0}' -f $Client_Id
            '&code={0}' -f $AuthCode
            '&resource={0}' -f $Resource_encoded
            '&client_secret={0}' -f [System.Web.HttpUtility]::UrlEncode(
                $Application.GetClientSecret())
        ) -join ''
        Write-Verbose "Body: $Body"
        $RequestedDate = Get-Date
        $Params = @{
            Uri = $BaseURL
            Method = 'POST'
            ContentType = "application/x-www-form-urlencoded"
            Body = $Body
            ErrorAction = 'Stop'
            SessionVariable = 'Session'
        }
        try {
            Write-Verbose "Retrieving OAuth Access Token from $BaseURL..."
            $Result = Invoke-WebRequest @Params
            if ($ResultVariable) {
                Write-Verbose "Setting result variable '$ResultVariable'"
                Set-Variable -Name $ResultVariable -Scope 'Global' -Value $Result
            }
        }
        catch {
            $ErrorMessage = $_.Exception.Message
            $Message = "Requesting OAuth Access Token Failed: {0} " -f $ErrorMessage
            Write-Error -Message $Message
            return
        }
        try {
            $Content = $Result.Content | ConvertFrom-Json -ErrorAction Stop
        }
        Catch {
            $ErrorMessage = $_.Exception.Message
            $Message = "Failed to convert response from JSON: {0}" -f $ErrorMessage
            Write-Error $Message
            Write-Error $Result.Content
            return
        }
        $AccessTokenCredential = [pscredential]::new('access_token', $($Content.access_token | ConvertTo-SecureString -AsPlainText -Force))
        $RefreshTokenCredential = [pscredential]::new('refresh_token', $($Content.refresh_token | ConvertTo-SecureString -AsPlainText -Force))
        $Params = @{
            Application = $Application
            AccessTokenCredential = $AccessTokenCredential
            RefreshTokenCredential = $RefreshTokenCredential
            RequestedDate = $RequestedDate
            Response = $Content | Select-Object -property * -ExcludeProperty access_token, refresh_token
            ResponseHeaders = $Result.Headers
            LastRequestDate = $RequestedDate
            Session = $Session
            #ResultObject = $Result
            GUID = [guid]::NewGuid()
        }
        New-GraphOauthAccessToken @Params
    }
}