SecureAuth IdP Version Affected: 8.2 and higher
Description:
This article describes how to generate an authorization header for the SecureAuth Authentication API using Powershell
Cause:
GitHub contains C# and Javascript SDKs for the API but if implementing the API in a different language or not using the SDK, it can be useful to see a simple working example in Powershell for testing and demonstration purposes.
Powershell is also relatively easy to understand and translate to other languages.
Resolution:
This script is also attached as a text file:
# Generate-IdP-API-Authorization-Header-via-Powershell
# Copyright (c) 2018, SecureAuth
# All rights reserved.
# More information: https://docs.secureauth.com/display/91docs/Authentication+API+Guide
# Variables
$IdPVersion92orHigher = $True # Set to FALSE for IdP 9.1 and lower
$AppId = '4068954873794549a4acb0569aaf5af5' # Change to use your AppId
$AppKey = '4c58595befbe30e40b661a46f554bee9dc3dbcdc8c5ad916dbc4eadf8f8e6183' # Change to use your AppKey
$Method = 'GET'
$ResourceUri = '/secureauth82/api/v1/users/user1/factors' # Change the realm number to the realm you are using, and user1 to the user account you want to test with
$UriPrefix = 'https://idp.secureauthlab.com' # Change FQDN to match your IdP's FQDN
If($IdPVersion92orHigher){$RequestDate = (Get-Date).ToUniversalTime().ToString('ddd, dd MMM yyyy HH:mm:ss.fff') + " GMT"}
Else{$RequestDate = (Get-Date).ToUniversalTime().ToString('ddd, dd MMM yyyy HH:mm:ss') + " GMT"}
# Functions
function Test-Json
{
<#
.SYNOPSIS
Tests if a string is in valid JSON format
.DESCRIPTION
Test-Json takes an input string and tests for JSON validity.
.PARAMETER InputString
String to be evaluated for JSON format.
.OUTPUTS
Boolean True if Input string is valid JSON
#>
param
(
$InputString
)
try {
$TempObject = ConvertFrom-Json $InputString -ErrorAction Stop;
$IsJson = $true
} catch {
$IsJson = $false
}
return $IsJson
}
function Convert-HexToByte-HexString
{
<#
.SYNOPSIS
Converts a Hex string into a byte array
.DESCRIPTION
Convert-HexToByte-HexString takes a hex number string and converts each 2 hex characters into a single byte within an array of bytes.
.PARAMETER HexString
Hex string to be converted. Must be an even number of hex values.
.OUTPUTS
byte[]
.EXAMPLE
Convert-HexToByte-HexString -HexString '4c58595befbe30e40b661a46f554bee9dc3dbcdc8c5ad916dbc4eadf8f8e6183'
#>
param
(
[string]$HexString
)
$numberChars=$HexString.Length;
[byte[]]$keyBytes=New-Object byte[] 32
for([int]$i=0;$i-lt$numberChars;$i=$i+2)
{
$keyBytes[$i/2]=[Convert]::ToByte($HexString.Substring($i,2),16);
}
return $keyBytes;
}
function New-SecureAuthAuthorizationHeader
{
<#
.SYNOPSIS
Builds a SecureAuth REST API authorisation header.
.DESCRIPTION
New-SecureAuthAuthorizationHeader takes 5 mandatory parameters with an optional request body and produces an authorization header that can be used with the SecureAuth API.
.PARAMETER AppId
Hex string containing the Application ID as configured on the IdP realm
.PARAMETER AppKey
Hex string containing the Application Key as configured on the IdP realm
.PARAMETER ResourceUri
The URI to the API end point. This should not contain the protocol or the FQDN of the IdP but the part of the URL immediately following.
.PARAMETER RequestDate
String containing the request datetime in GMT.
Format for IdP version 9.2+ should include milliseconds: ddd, dd MMM yyyy HH:mm:ss.fff plus a space then "GMT" for IdP v9.2+
e.g.: Mon, 17 Dec 2018 11:51:30.934 GMT
Format for 9.1 and lower should omit milliseconds: ddd, dd MMM yyyy HH:mm:ss plus a space then "GMT"
e.g.: Mon, 17 Dec 2018 11:51:30 GMT
.PARAMETER Method
The HTTP Method being used, must be one of 'GET','POST', 'PUT' or 'DELETE'. Must be Uppercase.
.PARAMETER RequestBody
The request body in JSON format
#>
param
(
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$AppId,
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$AppKey,
[Parameter(Mandatory=$true)][Uri]$ResourceUri,
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$RequestDate,
[Parameter(Mandatory=$true)][ValidateSet('GET','POST', 'PUT', 'DELETE')]$Method,
[Parameter(Mandatory=$false)]$RequestBody
)
begin
{
if([string]::IsNullOrEmpty($RequestBody))
{
$hasBody=$false;
}
else
{
$hasBody=$true;
}
$appKeyByte=(Convert-HexToByte-HexString $AppKey);
$dateString=$RequestDate
}
process
{
$pathstr = $ResourceUri
if($hasBody)
{
if(Test-Json $RequestBody)
{
$RequestBodyJson = $RequestBody
}
else
{
$RequestBodyJson = $RequestBody | ConvertTo-Json -Compress
}
$message="$Method`n$dateString`n$AppId`n$pathstr`n$RequestBodyJson"
}
else
{
$message="$Method`n$dateString`n$AppId`n$pathstr"
}
write-host "`nMessage:`n$message"
set-content -Path "c:\temp\hmac.txt" -Value $message
$messageByte=[System.Text.Encoding]::UTF8.GetBytes($message);
$hmacProvider=New-Object -TypeName 'System.Security.Cryptography.HMACSHA256'-ArgumentList @(,$appKeyByte);
$hmac=[System.Convert]::ToBase64String($hmacProvider.ComputeHash($messageByte));
write-host "`nHMAC: $hmac"
$headerValue="Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(("{0}:{1}"-f $AppId,$hmac)));
return $headerValue;
}
}
#Main
# Build authorization header
$authHeaderParams= @{
"AppId"=$AppId
"AppKey"=$AppKey
"Method"=$Method
"ResourceUri"=$ResourceUri
"RequestDate"=$RequestDate
}
$authHeader = New-SecureAuthAuthorizationHeader @authHeaderParams;
Write-host "`nAuthorization Header: $authHeader"
# Build headers
if($IdPVersion92orHigher){
$headers = @{
'Authorization' = $authHeader
'X-SA-Ext-Date' = $RequestDate
'Content-Type' = 'application/json'
}
}
else{
$headers = @{
'Authorization' = $authHeader
'X-SA-Date' = $RequestDate
'Content-Type' = 'application/json'
}
}
write-host "`n`nHeaders:"
$headers
# Make HTTP request to API using created headers
write-host "`n`n`nResponse:" -ForegroundColor Green
$response = Invoke-RestMethod -Method $Method -Uri "$UriPrefix$ResourceUri" -Headers $headers | ConvertTo-Json -Depth 10
$response
Output from the above:
More information:
SecureAuth API:
https://docs.secureauth.com/display/91docs/Authentication+API+Guide
SecureAuth GitHub:
https://github.com/SecureAuthCorp
SecureAuth Knowledge Base Articles provide information based on specific use cases and may not apply to all appliances or configurations. Be advised that these instructions could cause harm to the environment if not followed correctly or if they do not apply to the current use case.
Customers are responsible for their own due diligence prior to utilizing this information and agree that SecureAuth is not liable for any issues caused by misconfiguration directly or indirectly related to SecureAuth products.
Comments
Would you be able to post the text file on github to provide more feedback directly on the example provided? I was able to trim it by about 60% and still submit GET requests with the headers, but unable to use it as-is to POST with a body (Invalid credentials)
Please sign in to leave a comment.