For some scenarios, you might need to get REST API access in a user context by using the device authorization flow. The steps to set this up have been documented in PowerShell, but any language will do. Here is how it works:
Query the well-known OpenID configuration endpoint to retrieve the server’s token and device authorization endpoints:
try {
$wellKnownResponse = Invoke-RestMethod -Method Get -Uri $wellKnownEndpoint
$tokenEndpoint = $wellKnownResponse.token_endpoint
$deviceCodeEndpoint = $wellKnownResponse.device_authorization_endpoint
} catch {
Write-Error "Error obtaining server information"
exit
}
Send a request to the device authorization endpoint for a device code, a user code, a verification URL, and a complete verification URL, as well as details regarding how long the codes are valid and how often to check. Then, either open a browser to the complete verification URL, or direct the user to manually enter his or her user code and approve the device access request:
$body = "client_id=$clientId&scope=$([uri]::EscapeDataString($scope))"
try {
$deviceCodeResponse = Invoke-RestMethod -Method Post -Uri $deviceCodeEndpoint `
-ContentType "application/x-www-form-urlencoded" -Body $body
} catch {
Write-Error "Failed to obtain device code: $_"
exit
}
# Extract values from the response (field names may vary by provider)
$device_code = $deviceCodeResponse.device_code
$user_code = $deviceCodeResponse.user_code
$verification_uri = $deviceCodeResponse.verification_uri
$verification_uri_complete = $deviceCodeResponse.verification_uri_complete
$interval = 10 # in seconds
$expires_in = $deviceCodeResponse.expires_in # in seconds
# Provide a default interval if none was returned or if it's zero/null
if (-not $interval -or $interval -eq 0) {
$interval = 5
Write-Host "Interval not provided or invalid; defaulting to $interval seconds."
}
# Instead of instructing the user, open the browser to the verification_uri_complete
if ($verification_uri_complete) {
Write-Host "Opening browser for device authorization..."
Start-Process $verification_uri_complete
} else {
Write-Host "verification_uri_complete not provided. Please manually go to $verification_uri and enter the code: $user_code"
}
Start a loop that periodically sends a request to the token endpoint with the device code and client ID until the server returns an access token:
$startTime = Get-Date
$tokenResponse = $null
while (((Get-Date) - $startTime).TotalSeconds -lt $expires_in) {
Start-Sleep -Seconds $interval
try {# Build the POST body to exchange the device code for an access token
$tokenBody = "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=$clientId&device_code=$device_code"
$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType "application/x-www-form-urlencoded" -Body $tokenBody
if ($tokenResponse.access_token) {
Write-Host "Access token obtained:" $tokenResponse.access_token
break
}
}
catch {# Instead of reading the response content (which may be disposed), use the exception message.
$errorMessage = $_.Exception.Message
# Check if the exception message indicates that authorization is still pending.
if ($errorMessage -match "authorization_pending") {
Write-Host "Authorization pending..."
continue
}
else {
Write-Error "Error during token polling: $errorMessage"
break
}
}
}
if (-not $tokenResponse -or -not $tokenResponse.access_token) {
Write-Host "Failed to obtain an access token or authorization expired."
}
When needed, use the refresh token obtained during step #1 to request a new token from the token endpoint, ensuring continued access to the application:
$body = "grant_type=refresh_token&authorization=bearer $($tokenResponse.access_token)&refresh_token=$($tokenResponse.refresh_token)&client_id=dvls"
try {
$refreshResponse = Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType "application/x-www-form-urlencoded" -Body $body
if ($refreshResponse.access_token) {
Write-Host "Access token obtained:" $tokenResponse.access_token
break
}
} catch {
Write-Error "Failed to obtain device code: $_"
exit
}
See Okta's documentation for more information on the Device Authorization Flow.