API Auth using Base64 Encoding

I’m trying to make an API call using PowerShell , but having little to no luck making it work. I’m hoping someone here has some experience with using APIs through PowerShell to help speed me along.

For some reason, I always struggle on the authentication piece of using an API - this occasion is no different. To start off, I’m using the following code to build my authorization token.

$Credential = Get-Credential
$AuthToken = ($((Invoke-WebRequest -Method Post -Uri https://10.24.80.229/api/rest/users/login -ContentType "application/json" -Body "{ 
    `"username`": `"$($Credential.username)`", 
    `"password`":`"$($Credential.GetNetworkCredential().password)`"}").content) | 
    ConvertFrom-Json).result
$Header = @{"Authorization"="Basic $AuthToken"}

The token creation works fine and I get a “HTTP/1.1 200 OK” response. Where things start to go sideways is when I try to use the above header to pull data from the system. When I run the following command

(Invoke-RestMethod -Method Get -Headers $Header -Uri "https://10.224.8.229/api/rest/system/name").data.name

I get the following error message

Invoke-RestMethod : Apache Tomcat/7.0.85 - Error report HTTP Status 500 - Not base 64type Exception reportmessage Not base 64description The server encountered an internal error that prevented it from fulfilling this request.exception 
java.lang.IllegalArgumentException: Not base 64
	com.infinidat.mgmt.utils.java.Base64Utils.decode(Base64Utils.java:59)
	com.infinidat.mgmt.AuthenticationFilter.getUsernameAndPasswordFromHeader(AuthenticationFilter.java:258)
	com.infinidat.mgmt.AuthenticationFilter.getCreds(AuthenticationFilter.java:245)
	com.infinidat.mgmt.AuthenticationFilter.authenticate(AuthenticationFilter.java:193)
	com.infinidat.mgmt.AuthenticationFilter.doFilter(AuthenticationFilter.java:174)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.85 logs.Apache Tomcat/7.0.85
At line:7 char:2
+ (Invoke-RestMethod -Method Get -Headers $Header -Uri "https://10.224. ...
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

I’ve been researching how to convert my header to base64 and I’m using the following modification to make the conversion:

$Header = @{"Authorization"="Basic $([convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("{0}:{1} -f $authtoken")))"}

Unfortunately, doing this provides a new “unauthorized” type of error which leads me to believe I’m doing the conversion incorrectly. Any guidance is greatly appreciated.

Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.
At line:1 char:2
+ (Invoke-RestMethod -Method Get -Headers $Header -Uri "https://10.224. ...
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand


For context, this is the API I am working with:

https://support.infinidat.com/hc/en-us/articles/115005784189-Using-the-InfiniBox-API

 

I think the fundamental problem is that you are trying to use the result of the login call as an authorization token, and it isn’t according to the doco I read at https://support.infinidat.com/hc/en-us/articles/360002106537-Using-the-InfiniBox-API. It tells me that the login api endpoint is only to validate credentials.

To continue using other api endpoints you need to add the authorization header as per this wikipedia entry.

My first thought would be check if the Infinibox responds with a 401 unauthorized error when you hit it with the browser. If it does then the powershell cmdlets should pass whatever credential you specify as basic auth. Try something like what I have below.

$cred = get-credential
(Invoke-RestMethod -Method Get -Uri "https://10.224.8.229/api/rest/system/name" -credential $cred).data.name

If that doesn’t work you’ll have to construct the authorization header value and set it for each call.

$cred = get-credential
$userpass = "$($cred.UserName):$($cred.GetNetworkCredential().Password)"
$b64 = [System.Convert]::ToBase64String([System.Text.encoding]::ASCII.GetBytes($userpass))
$auth = "Basic $b64"
(Invoke-RestMethod -Method Get -Headers @{"Authorization" = $auth} -Uri "https://10.224.8.229/api/rest/system/name").data.name