Use PowerShell to Obtain Bearer Token from OAuth 2.0 API

PowerShell is a powerful scripting language and set of tools included with every major version of Windows in recent years. Microsoft is working hard to be competitive with Python and other scripting languages.

We recently did a project that required us to export a couple CSV files to disk and then transmit them to an API on the web. The API was a Swagger designed API that uses OAth2.0 for authentication.

OAuth2.0 provides several different methods or flows to connect with. In this case we were using the clientCredentials flow. This flow uses a Bearer token, but this token expires! In our testing our API request worked initially with a token we got manually but didn’t work the following Monday.

To get a new token you need to supply a client_id and client_secret to a different API that responds with a token for us to use. For our use case we are only pushing data maybe once a day or once a week so we need to get a new token every time we connect.

Lets get into the code. First we need to get our token. Here is the code snippet that gets the token.

$authSuccess = $false

$authurl = "http://api_Identity_URL_Here/connect/token"

$clientId = "your_client_id"
$clientSecret = "your_client_secret"

$authboundary = [System.Guid]::NewGuid().ToString()
$authLF = "`r`n"

$authbodyLines = (
    "--$authboundary",
    "Content-Disposition: form-data; name=`"client_id`"$authLF",
    $clientId,
    "--$authboundary",
    "Content-Disposition: form-data; name=`"client_secret`"$authLF",
    $clientSecret,
    "--$authboundary",
    "Content-Disposition: form-data; name=`"grant_type`"$authLF",
    "client_credentials",
    "--$authboundary--"
) -join $authLF

try {
    $tokenResponse = Invoke-WebRequest -Uri $authurl -Method Post -ContentType "multipart/form-data; boundary=$authboundary" -Body $authbodyLines
    $tokenResponseJSON = ConvertFrom-Json $tokenResponse.Content

    # Extract the token from the response
    $tokenBearer = $tokenResponseJSON.token_type
    $token = $tokenResponseJSON.access_token 

    $authSuccess = $true

    "  Authorized. Token is: $token"
}
catch {
    
    $authSuccess = $false
    "  ERROR - Unable to get an access token."
}

Lets break this down, there was a lot there.

The first bit is just setup for the rest of the script. Easy spots to update the URL, Client Id and Client Secret.

$authSuccess = $false

$authurl = "http://api_Identity_URL_Here/connect/token"

$clientId = "your_client_id"
$clientSecret = "your_client_secret"

This next bit is some magic that took a long time to figure out. We were using PowerShell 5.1 which doesn’t have updated functionality to support multi-part forms. This OAuth 2.0 request uses multi-part forms to send the information. So after some head bashing and some helpful blog posts we ended up with this crazy code.

A multi-part form requires the various fields be sent in the body of the HTML message and that they are separated by lines starting with “–” and some random text. So to get there we create a new GUID for the random string.

$authboundary = [System.Guid]::NewGuid().ToString()
$authLF = "`r`n"

Then we build the body of the multi-part form. Here we need to set the start boundary, include the field information, some line feeds, the information we need to submit and then the next boundary. The end of the last boundary ends with “–“.

$authbodyLines = (
"--$authboundary",
"Content-Disposition: form-data; name=`"client_id`"$authLF",
$clientId,
"--$authboundary",
"Content-Disposition: form-data; name=`"client_secret`"$authLF",
$clientSecret,
"--$authboundary",
"Content-Disposition: form-data; name=`"grant_type`"$authLF",
"client_credentials",
"--$authboundary--"
) -join $authLF

Lastly, we get the token! Here is the code. We include the URL, method is POST, content is the body, we have to include the boundary string.

The response comes back in JSON. So I ran that through the handy ConvertFrom-Json function. In the response we get the Bearer and the token, so I pull those out to variables for later use.

try {
$tokenResponse = Invoke-WebRequest -Uri $authurl -Method Post -ContentType "multipart/form-data; boundary=$authboundary" -Body $authbodyLines
$tokenResponseJSON = ConvertFrom-Json $tokenResponse.Content

# Extract the token from the response
$tokenBearer = $tokenResponseJSON.token_type
$token = $tokenResponseJSON.access_token

$authSuccess = $true

" Authorized. Token is: $token"
}
catch {

$authSuccess = $false
" ERROR - Unable to get an access token."
}

This coding would not be possible with the vast help of the Internet and the good citizens out there documenting their work and the hard things they figure out. These were some of the sources used to build this code (thanks!):