Skip to content

Instantly share code, notes, and snippets.

@romero126
Created May 9, 2021 21:39
Show Gist options
  • Save romero126/7b1b73072574827d131055490a8b23de to your computer and use it in GitHub Desktop.
Save romero126/7b1b73072574827d131055490a8b23de to your computer and use it in GitHub Desktop.
Connect-DeviceAuthorization
function Connect-DeviceAuthorization {
[CmdletBinding()]
param(
[Parameter(
HelpMessage = "Specify an Application ClientID defaults to the ClientID for 'AzureAD'"
)]
[string] $ClientID = '1b730954-1685-4b74-9bfd-dac224a7b894',
[Parameter(
HelpMessage = "Specify a TenantID, defaults to 'common'"
)]
[string] $TenantID = 'common',
[Parameter(
Mandatory,
HelpMessage = "Specify a Service Endpoint for Azure"
)]
[string]
$Resource
)
begin {
$null = [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
$passwordVault = New-Object Windows.Security.Credentials.PasswordVault
}
process {
# Check if there is a cached access token
try {
$cachedToken = $passwordVault.Retrieve("PSDeviceAuth", $Resource).Password | ConvertFrom-Json
if (([DateTime]$cachedToken.Expires) -gt [dateTime]::Now) {
return $cachedToken
}
}
catch {
}
$DeviceCodeParameters = @{
Method = 'POST'
Uri = "https://login.microsoftonline.com/$TenantID/oauth2/devicecode"
Body = @{
client_id = $ClientId
resource = $Resource
}
}
$DeviceCodeRequest = Invoke-RestMethod @DeviceCodeParameters -UseDefaultCredentials
Write-Host $DeviceCodeRequest.message -ForegroundColor Green
# Set Authentication Timeout
$TokenExpiration = [DateTime]::Now.AddSeconds($DeviceCodeRequest.expires_in)
$TokenParameters = @{
Method = 'POST'
Uri = "https://login.microsoftonline.com/$TenantId/oauth2/token"
Body = @{
grant_type = "urn:ietf:params:oauth:grant-type:device_code"
code = $DeviceCodeRequest.device_code
client_id = $ClientId
}
}
while ($true) {
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code#expected-errors
if ([DateTime]::Now -gt $TokenExpiration) {
Write-Host "Sign in authorization timed out." -ForegroundColor Red
break
}
# Specify Polling time
Start-Sleep -Seconds $DeviceCodeRequest.interval
try {
$TokenRequest = Invoke-RestMethod @TokenParameters
}
catch {
$exception = $_.ErrorDetails.Message | ConvertFrom-Json
if ($exception.error -ne "authorization_pending") {
throw $_
}
continue
}
break
}
# Store the data.
$Token = [PSCustomObject][Ordered]@{
Expires = [datetime]::Now.AddSeconds($TokenRequest.expires_in)
AccessToken = $TokenRequest.access_token
RefreshToken = $TokenRequest.refresh_token
}
$vault = New-Object Windows.Security.Credentials.PasswordVault
$vault.Add(
[Windows.Security.Credentials.PasswordCredential]::new(
"PSDeviceAuth",
$TokenRequest.Resource,
($Token | ConvertTo-Json)
)
)
# Return token that we store
return $Token
}
end {
}
}
#Connect-DeviceAuthorization -Resource 'https://graph.windows.net/'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment