Skip to content

Instantly share code, notes, and snippets.

@FriedrichWeinmann
Created April 5, 2022 10:37
Show Gist options
  • Save FriedrichWeinmann/31240c4480165d3e1181735ed77f3abc to your computer and use it in GitHub Desktop.
Save FriedrichWeinmann/31240c4480165d3e1181735ed77f3abc to your computer and use it in GitHub Desktop.
Custom Connect to azure AD using the DeviceCode flow
function Connect-DeviceCode {
<#
.SYNOPSIS
Connects to Azure AD using the Device Code authentication workflow.
.DESCRIPTION
Connects to Azure AD using the Device Code authentication workflow.
.PARAMETER ClientID
The ID of the registered app used with this authentication request.
.PARAMETER TenantID
The ID of the tenant connected to with this authentication request.
.PARAMETER Scopes
The scopes to request.
.EXAMPLE
PS C:\> Connect-DeviceCode -ClientID $clientID -TenantID $tenantID -Scopes 'api://d9b68662-0add-46ec-aab2-0123456788910/.default'
Connects to the specified tenant using the specified client, prompting the user to authorize via Browser.
Requestss the default scopes for the specified custom API
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$ClientID,
[Parameter(Mandatory = $true)]
[string]
$TenantID,
[Parameter(Mandatory = $true)]
[string[]]
$Scopes
)
try {
$initialResponse = Invoke-RestMethod -Method POST -Uri "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/devicecode" -Body @{
client_id = $ClientID
scope = $Scopes -join " "
} -ErrorAction Stop
}
catch {
throw
}
Write-Host $initialResponse.message
$paramRetrieve = @{
Uri = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"
Method = "POST"
Body = @{
grant_type = "urn:ietf:params:oauth:grant-type:device_code"
client_id = $ClientID
device_code = $initialResponse.device_code
}
ErrorAction = 'Stop'
}
$limit = (Get-Date).AddSeconds($initialResponse.expires_in)
while ($true) {
if ((Get-Date) -gt $limit) {
throw "Timelimit exceeded, device code authentication failed"
}
Start-Sleep -Seconds $initialResponse.interval
try { $authResponse = Invoke-RestMethod @paramRetrieve }
catch {
if ($_ -match '"error":"authorization_pending"') { continue }
$PSCmdlet.ThrowTerminatingError($_)
}
if ($authResponse) {
break
}
}
$authResponse
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment