Jump to content

HTTP POST Request, Dell Warranty API


Recommended Posts

First I'm sorry for my lack of knowledge, but I found the below powershell code and it's working just fine, but what I can't figure out is, what's missing in the code above for that to work? 😳

When I run it the above code I get this error: "There were no credentials available for the client certificate"

 

#https://www.reddit.com/r/PowerShell/comments/cvu7z9/all_getdellwarrantyps1_users_should_read_this/
#
#Usage:
#Run with Single ServiceTag as a Parameter or multiple ServiceTags 
#as a Parameter in quotes separated by comma. 
#Example: .\Get-DellWarrantyInfo.ps1 "TAG1, TAG2, TAG3"
#Or
#Run with no parameters and enter a single ServiceTag or multiple
#ServiceTags seperated by comma without quotes.
#Example: Enter ServiceTag [TAG] : TAG1, TAG2, TAG3
#Run with no parameters and press enter at the prompt without entry 
#to get warranty info on the machine where script is run. 
#Use API Key and Secret as parameters 2 and 3 or edit the below
#to include your API Key and Secret.

Param(  
    [Parameter(Mandatory = $false)]  
    $ServiceTags,
    [Parameter(Mandatory = $false)]  
    $ApiKey,
    [Parameter(Mandatory = $false)]  
    $KeySecret
)

#API Key Expiration: 01/01/2021
$ORG_API_Key=""
$ORG_API_Secret=""

$bios = gwmi win32_bios
$st = $bios.SerialNumber

if (!$ServiceTags) {
$ServiceTags = Read-Host -Prompt "Enter ServiceTag [$st] "
}
if (!$ServiceTags) {
$ServiceTags = $st
}
if (!$ApiKey) {
$ApiKey = $ORG_API_Key
}
if (!$ApiKey) {
$ApiKey = Read-Host -Prompt 'Enter API Key '
}
if (!$KeySecret) {
$KeySecret = $ORG_API_Secret
}
if (!$KeySecret) {
$KeySecret = Read-Host -Prompt 'Enter Key Secret '
}

[String]$servicetags = $ServiceTags -join ", "

Write-Host "Access Token is: $token`n"

$headers = @{"Accept" = "application/json" }
$headers.Add("Authorization", "Bearer $token")

$params = @{ }
$params = @{servicetags = $servicetags; Method = "GET" }

Try {
    $Global:response = Invoke-RestMethod -Uri "https://apigtwb2c.us.dell.com/PROD/sbil/eapi/v5/asset-entitlements" -Headers $headers -Body $params -Method Get -ContentType "application/json"
}
Catch {
    $AuthURI = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
    $OAuth = "$ApiKey`:$KeySecret"
    $Bytes = [System.Text.Encoding]::ASCII.GetBytes($OAuth)
    $EncodedOAuth = [Convert]::ToBase64String($Bytes)
    $Headers = @{ }
    $Headers.Add("authorization", "Basic $EncodedOAuth")
    $Authbody = 'grant_type=client_credentials'
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    $AuthResult = Invoke-RESTMethod -Method Post -Uri $AuthURI -Body $AuthBody -Headers $Headers
    $Global:token = $AuthResult.access_token
    $Global:response = Invoke-RestMethod -Uri "https://apigtwb2c.us.dell.com/PROD/sbil/eapi/v5/asset-entitlements" -Headers $headers -Body $params -Method Get -ContentType "application/json"
}
Finally{
    foreach ($Record in $response) {
    $servicetag = $Record.servicetag
    $Json = $Record | ConvertTo-Json
    $Record = $Json | ConvertFrom-Json 
    $Device = $Record.productLineDescription
    $ShipDate = $Record.shipDate
    $EndDate = ($Record.entitlements | Select -Last 1).endDate
    $Support = ($Record.entitlements | Select -Last 1).serviceLevelDescription
    $ShipDate = $ShipDate | Get-Date -f "MM-dd-y"
    $EndDate = $EndDate | Get-Date -f "MM-dd-y"
    $today = get-date
    $type = $Record.ProductID

    if ($type -Like '*desktop') { 
        $type = 'desktop'        
    }
    elseif ($type -Like '*laptop') { 
        $type = 'laptop'
    }

    Write-Host -ForegroundColor White -BackgroundColor "DarkRed" $Computer
    Write-Host "Service Tag   : $servicetag"
    Write-Host "Model         : $Device"
    Write-Host "Type          : $type"
    Write-Host "Ship Date     : $ShipDate"
    if ($today -ge $EndDate) { Write-Host -NoNewLine "Warranty Exp. : $EndDate  "; Write-Host -ForegroundColor "Yellow" "[WARRANTY EXPIRED]" }
    else { Write-Host "Warranty Exp. : $EndDate" } 
    if (!($ClearEMS)) {
        $i = 0
        foreach ($Item in ($($WarrantyInfo.entitlements.serviceLevelDescription | select -Unique | Sort-Object -Descending))) {
            $i++
            Write-Host -NoNewLine "Service Level : $Item`n"
        }

    }
    else {
        $i = 0
        foreach ($Item in ($($WarrantyInfo.entitlements.serviceLevelDescription | select -Unique | Sort-Object -Descending))) {
            $i++
            Write-Host "Service Level : $Item`n"
        }
    }
}
}

 

Yours sincerely

Kenneth.

Link to comment
Share on other sites

  • 2 weeks later...
On 11/18/2021 at 4:01 PM, 5g6tdcv4 said:

Not pretty, but you can create a functional warranty lookup from it.

 

#include <HTTP.au3>
$url = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
$postdata = "client_id=" & "YOURID" & "&" & "client_secret=" & "YOURSECRET" & "&" & "grant_type=client_credentials"
$test = _HTTP_Post1($url, $postdata)
ConsoleWrite($test)   ;this consolewrite will show you your new token if its older than an hour

$token ="3997b2f1-1781-426d-bc1f-bd7e0bd9011f"    ;will need to be updated with latest token
$ans = _http_get1("https://apigtwb2c.us.dell.com/PROD/sbil/eapi/v5/asset-entitlements?servicetags=YOUR SERIAL")
MsgBox(0,"",$ans)

Func _HTTP_Post1($url, $postdata = '')
    Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    $oHTTP.Open("POST", $url, False)
    If @error Then Return SetError(1, 0, 0)

    $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    $oHTTP.Send($postdata)
    If @error Then Return SetError(2, 0, 0)

    Local $sReceived = $oHTTP.ResponseText
    Local $iStatus = $oHTTP.Status
    If $iStatus = 200 Then Return $sReceived

    Return SetError(3, $iStatus, $sReceived)
EndFunc   ;==>_HTTP_Post

Func _HTTP_Get1($url)
    Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    Local $res = $oHTTP.Open("GET", $url, False)
    If @error Then Return SetError(1, 0, 0)
    #forceref $res
    $oHTTP.SetRequestHeader("Content-Type", "application/json")
    $oHTTP.SetRequestHeader("Authorization", "Bearer " &$token)

    $oHTTP.Send()
    If @error Then Return SetError(2, 0, 0)

    Local $sReceived = $oHTTP.ResponseText
    Local $iStatus = $oHTTP.Status
    If $iStatus = 200 Then Return $sReceived

    Return SetError(3, $iStatus, $sReceived)
EndFunc   ;==>_HTTP_Get

 

@5g6tdcv4

Is still working? I can't get it to work.

Yours sincerely

Kenneth.

Link to comment
Share on other sites

@Valnurat i've been working for something similar on excel vba
to get authenticated with Dell API you must do the following

url = https://apigtwb2c.us.dell.com/auth/oauth/v2/token

APIclient = abc123

APIsecret = zxy098

the above you must place it like this APIclient:APIsecret, the : are important

then you must encode APIclient:APIsecret to base64, i'll call it encodedAPI

now you must past the following in the headers

    "Content-Type", "application/x-www-form-urlencoded"

    "Authorization", "Basic encodedAPI" 

now you must past the following in the body

    "grant_type=client_credentials"

and send the POST request

 

Link to comment
Share on other sites

@Valnurat PM I'll help you with it for free. Just send me credentials by PM we can share code here later.

 

Saludos

 

Link to comment
Share on other sites

Link to comment
Share on other sites

On 2/10/2024 at 1:50 PM, Valnurat said:

So you got your project to work?

I don't see any info in my documentation that it need to encode it to base64.

 

yes and no 😅

if i run my code with the api / secret within the vba i get error 400 but if i remove it and leave it filled with any data, excel asks me to login in this case i use for the username the api and password i use the secret, it connects and works without issues

after the above is used, i can add back the api and secret to the section where i have it setup and it would connect without issues until i close the excel document

the PowerShell script posted above also converts to base64 

Link to comment
Share on other sites

Does it provide api demo? I can solve for sure but You're not talking about it too much 😅

 

Saludos

Link to comment
Share on other sites

i figure out my problem, my base64 isnt encoding correctly hence giving me the error 400
if i add a "Authorization", "Basic bDdlNDg5..." manually with  a correctly encoded base64 api:secret, i can authenticate with the dell api without issues

 

Public Sub httpclient()

    Sheets("Sheet1").Unprotect
    
    Dim xmlhttp As New MSXML2.XMLHTTP60, DellAPIUrl As String, strHead As String, strBody As String, ApiKey As String, ApiSecret As String
    
    ApiKey = "removed"
    ApiSecret = "removed"
    
    strHead = ApiKey & ":" & ApiSecret
    DellAPIUrl = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
    
    xmlhttp.Open "POST", DellAPIUrl, False
    
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.setRequestHeader "Authorization", "Basic " & EncodeBase64(strHead) ' need to figure out how to properly encode to base64

    ' Send the request
    xmlhttp.Send "grant_type=client_credentials" ' sending the post request and a body message of grant_type
    
    If xmlhttp.Status = 200 Then
        ' If successful, store the response text
        MsgBox (xmlhttp.responseText)
    Else
        ' If request is not successful, handle errors appropriately
        Dim responseText As String
        responseText = xmlhttp.responseText
        
        ' Include additional information about the bad request in the MsgBox
        MsgBox "Error: " & xmlhttp.Status & " - " & xmlhttp.statusText & vbCrLf & _
               "Response Text: " & responseText, vbCritical
    End If
    
End Sub

here is my code for authentication on excel vba

Edited by TopoX
Link to comment
Share on other sites

17 hours ago, TopoX said:

 

yes and no 😅

if i run my code with the api / secret within the vba i get error 400 but if i remove it and leave it filled with any data, excel asks me to login in this case i use for the username the api and password i use the secret, it connects and works without issues

after the above is used, i can add back the api and secret to the section where i have it setup and it would connect without issues until i close the excel document

the PowerShell script posted above also converts to base64 

Yes, it's true that in the powershell it's converts to base64. Still I don't know why as in the documentation I got from Dell it is not mentioned.

Anyway in the powershell there's this:

$OAuth = "$ApiKey`:$KeySecret"

You see this " ` " I'm not sure what it does, but if I print out the converted base64 credentials in the powershell, I get the same converted base64 credentials with @trancexx function for base64 encoding. _base64encode-_base64decode

Global $__g_oHTTP_ErrorHandler = ObjEvent("AutoIt.Error", __HTTP_OnError) ; Install a custom error handler

$url = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
$postdata = "grant_type=client_credentials"
$ApiKey = "removed"
$KeySecret = "removed"
$test = _HTTP_Post($url,$postdata)
ConsoleWrite($test)


Func _HTTP_Post($url, $postdata)
    Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    $oHTTP.Open("POST", $url, False)
    If @error Then Return SetError(1, 0, 0)

    $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    $oHTTP.SetRequestHeader("Authorization", "Basic " & _Base64Encode($ApiKey & ":" & $KeySecret))
    $oHTTP.Send($postdata)
    If @error Then Return SetError(2, 0, 0)

    Local $sReceived = $oHTTP.ResponseText
    Local $iStatus = $oHTTP.Status
    If $iStatus = 200 Then Return $sReceived

    Return SetError(3, $iStatus, $sReceived)
EndFunc   ;==>_HTTP_Post

; Custom error handler will set @error variable to 1 if a COM error is intercepted
; and will print out the error informations by the Console
Func __HTTP_OnError(ByRef $oMyError)
    Local $HexNumber = Hex($oMyError.number, 8)
    ConsoleWrite("We intercepted a COM Error !" & @LF & _
            "Number is: " & $HexNumber & @LF & _
            "Windescription is: " & $oMyError.windescription & _
            "Err.description is: " & $oMyError.description _
            )
    Return SetError(5, $HexNumber, 0)
EndFunc   ;==>__HTTP_OnError

; Trancexx :
Func _Base64Encode($input)
    $input = Binary($input)
    Local $struct = DllStructCreate("byte[" & BinaryLen($input) & "]")
    DllStructSetData($struct, 1, $input)
    Local $strc = DllStructCreate("int")
    Local $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _
            "ptr", DllStructGetPtr($struct), _
            "int", DllStructGetSize($struct), _
            "int", 1, _
            "ptr", 0, _
            "ptr", DllStructGetPtr($strc))
    If @error Or Not $a_Call[0] Then
        Return SetError(1, 0, "") ; error calculating the length of the buffer needed
    EndIf
    Local $a = DllStructCreate("char[" & DllStructGetData($strc, 1) & "]")
    $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _
            "ptr", DllStructGetPtr($struct), _
            "int", DllStructGetSize($struct), _
            "int", 1, _
            "ptr", DllStructGetPtr($a), _
            "ptr", DllStructGetPtr($strc))
    If @error Or Not $a_Call[0] Then
        Return SetError(2, 0, ""); error encoding
    EndIf
    Return DllStructGetData($a, 1)
EndFunc   ;==>_Base64Encode

Func _Base64Decode($input_string)
    Local $struct = DllStructCreate("int")
    Local $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", _
            "str", $input_string, _
            "int", 0, _
            "int", 1, _
            "ptr", 0, _
            "ptr", DllStructGetPtr($struct, 1), _
            "ptr", 0, _
            "ptr", 0)
    If @error Or Not $a_Call[0] Then
        Return SetError(1, 0, "") ; error calculating the length of the buffer needed
    EndIf
    Local $a = DllStructCreate("byte[" & DllStructGetData($struct, 1) & "]")
    $a_Call = DllCall("Crypt32.dll", "int", "CryptStringToBinary", _
            "str", $input_string, _
            "int", 0, _
            "int", 1, _
            "ptr", DllStructGetPtr($a), _
            "ptr", DllStructGetPtr($struct, 1), _
            "ptr", 0, _
            "ptr", 0)
    If @error Or Not $a_Call[0] Then
        Return SetError(2, 0, ""); error decoding
    EndIf
    Return DllStructGetData($a, 1)
EndFunc   ;==>_Base64Decode
;---------------------------------------------------------------------------------

The outcome from the code I have done is:

We intercepted a COM Error !
Number is: 80070057
Windescription is: The parameter is incorrect.

But if I do what you do by adding a "Authorization", "Basic bDc0N2Zh..." manually with  an encoded base64 api:secret, it is not working for me and I get this error:
We intercepted a COM Error !
Number is: 80020009
Windescription is: Exception occurred.
Err.description is: No credentials were available in the client certificate.

If I do this, to see the converted base64 string

$test = _Base64Encode($ApiKey & ":" & $KeySecret)
ConsoleWrite($test)

The outcome is on 2 lines like there's a line break. 

Should it not just be 1 line?

 

Yours sincerely

Kenneth.

Link to comment
Share on other sites

5 hours ago, Valnurat said:

Yes, it's true that in the powershell it's converts to base64. Still I don't know why as in the documentation I got from Dell it is not mentioned.

Anyway in the powershell there's this:

$OAuth = "$ApiKey`:$KeySecret"

You see this " ` " I'm not sure what it does, but if I print out the converted base64 credentials in the powershell, I get the same converted base64 credentials with @trancexx function for base64 encoding. _base64encode-_base64decode

If I do this, to see the converted base64 string

$test = _Base64Encode($ApiKey & ":" & $KeySecret)
ConsoleWrite($test)

The outcome is on 2 lines like there's a line break. 

Should it not just be 1 line?

 

in the PowerShell the use of the " ` " is used to escape the colon (:) character, allowing it to be treated as a literal character within the string.

yes, the outcome should be a single line; i was having the same issue on my vba i had to play different ways to encode to base64 until i was able to get the whole thing on a single line

run this code in PowerShell, it will spit up the encoded authentication
 

function Get-DellEncodedAuth {

    $ApiKey = "removed"
    $KeySecret = "removed"
    $AuthURI = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
    $OAuth = "$ApiKey`:$KeySecret"
    $Bytes = [System.Text.Encoding]::ASCII.GetBytes($OAuth)
    $EncodedOAuth = [Convert]::ToBase64String($Bytes)
    $Headers = @{ }
    $Headers.Add("authorization", "Basic $EncodedOAuth")
    $Authbody = 'grant_type=client_credentials'
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    Try {
        $AuthResult = Invoke-RESTMethod -Method Post -Uri $AuthURI -Body $AuthBody -Headers $Headers
        $Global:token = $AuthResult.access_token
    }
    Catch {
        $ErrorMessage = $Error[0]
        Write-Error $ErrorMessage
        BREAK        
    }
    Write-Host "Access Token is: $token`n"
    Write-Host $EncodedOAuth
    
}; Get-DellEncodedAuth

try this code, for testing grab the encoded auth from the powershell above and paste it $oHTTP.SetRequestHeader("Authorization", "Basic ENCODEDAUTHHERE") on the code below, if that works then you know the base64 encoding needs to be worked on ;)

Func _HTTP_Post($url, $postdata)
    ; Append grant_type=client_credentials to the $postdata
    $postdata &= "&grant_type=client_credentials"

    Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    $oHTTP.Open("POST", $url, False)
    If @error Then Return SetError(1, 0, 0)

    $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    $oHTTP.SetRequestHeader("Authorization", "Basic " & _Base64Encode($ApiKey & ":" & $KeySecret))
    $oHTTP.Send($postdata)
    If @error Then Return SetError(2, 0, 0)

    Local $sReceived = $oHTTP.ResponseText
    Local $iStatus = $oHTTP.Status
    If $iStatus = 200 Then Return $sReceived

    Return SetError(3, $iStatus, $sReceived)
EndFunc   ;==>_HTTP_Post

 

added $postdata &= "&grant_type=client_credentials"

Edited by TopoX
Link to comment
Share on other sites

I have tried it and no errors with the parameters but the same error is:

We intercepted a COM Error !
Number is: 80020009
Windescription is: Exception occurred.
Err.description is: No credentials were available in the client certificate.

Yours sincerely

Kenneth.

Link to comment
Share on other sites

9 hours ago, Valnurat said:

I have tried it and no errors with the parameters but the same error is:

We intercepted a COM Error !
Number is: 80020009
Windescription is: Exception occurred.
Err.description is: No credentials were available in the client certificate.

@Valnurat

go to this page 

 and download UDFB64.au3, place it under C:\Program Files (x86)\AutoIt3\Include

test this code below, it is working for me and encoding to base64 with the file above spits it out in a single line which is what we want/need
 

#include <MsgBoxConstants.au3>
#include <UDFB64.au3>

$url = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token"
$postdata = "grant_type=client_credentials"
$ApiKey = "removed"
$KeySecret = "removed"
$test = _HTTP_Post($url,$postdata)

Func _HTTP_Post($url, $postdata)
    Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
    $oHTTP.Open("POST", $url, False)
    If @error Then Return SetError(1, 0, 0)

    $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    $oHTTP.SetRequestHeader("Authorization", "Basic " & B64Encode($ApiKey & ":" & $KeySecret))
    MsgBox($MB_OK, "Encoded Authorization",  B64Encode($ApiKey & ":" & $KeySecret))
    $oHTTP.Send($postdata)
    If @error Then Return SetError(2, 0, 0)

    Local $sReceived = $oHTTP.ResponseText
    Local $iStatus = $oHTTP.Status
    If $iStatus = 200 Then
        MsgBox($MB_OK, "Server Response", "Status Code: " & $iStatus & @CRLF & "Response Body: " & $sReceived)
        Return $sReceived
    Else
        MsgBox($MB_OK, "Server Response", "Status Code: " & $iStatus & @CRLF & "Response Body: " & $sReceived)
        Return $sReceived
    EndIf
EndFunc   ;==>_HTTP_Post


see imgs for confirmation, hope this helps, there might be some lines not needed, I'm a total noob to AutoIt

capture1.png.dd2a4cdb0a239b8f4119651efa10e367.pngcapture2.png.594fd6ff86c41e5875865d4d5c9abc69.png

Edited by TopoX
Link to comment
Share on other sites

28 minutes ago, Valnurat said:

Yes, you are right. I get 1 line of converted string now, but it drives me nuts that I still get the same error. I don't get the the responds you get.

I just don't get it.

maybe create a new file and copy my full code for previous post and test it that way :)
hopefully that works

Link to comment
Share on other sites

19 minutes ago, Valnurat said:

If I do that I get this error:
==> The requested action with this object has failed.:

 

$oHTTP.Send($postdata)
$oHTTP^ ERROR

i wonder if it a version thing
im running version 3.3.16.1 of Autit

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...