Reputation: 1
I have been battling with Oauth2 while trying to link up a .NET application written in VB with qbo (quickbooks online). I can get my code but I get a "(400) Bad Request" response when trying to exchange the code for my access and refresh token. Here is my code for requesting the access token:
Function GetTokens(strCode As String, strURL As String, strClientID As String, strClientSecret As String, strRedirectURI As String) As Boolean
Dim strBasic, strPostData As String
Dim strResponse As String
strBasic = strClientID & ":" & strClientSecret
Dim byt As Byte() = System.Text.Encoding.UTF8.GetBytes(strBasic)
strBasic = Convert.ToBase64String(byt)
strPostData = "grant_type=authorization_code"
strPostData += "&code=" & strCode
strPostData += "&redirect_uri=" & strRedirectURI
strResponse = ReadURLwithAuthentication("POST", strURL, strPostData, strBasic)
Response.Write(strResponse)
Return True
End Function
Function ReadURLwithAuthentication(strMethod As String, strURL As String, strPostData As String, strToken As String) As String
Dim wrX As WebRequest = WebRequest.Create(strURL)
'request method
wrX.Method = strMethod
'protocal version
CType(wrX, HttpWebRequest).ProtocolVersion = HttpVersion.Version11
'accept
CType(wrX, HttpWebRequest).Accept = "application/json"
'authorization
wrX.Headers.Add("Authorization", "Basic " + strToken)
'content type
wrX.ContentType = "application/x-www-form-urlencoded"
'host
CType(wrX, HttpWebRequest).Host = "oauth.platform.intuit.com"
'contentbody only supplied for POST
Select Case strMethod
Case "POST", "DELETE"
'convert post data to a byte array.
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(strPostData)
'content length
wrX.ContentLength = byteArray.Length
'get the stream that holds the request
Dim smX As Stream = wrX.GetRequestStream()
'write the data to the stream object
smX.Write(byteArray, 0, byteArray.Length)
'close the stream
smX.Close()
End Select
'get the response object
Dim strResponse As String
Try
Dim respX As WebResponse = wrX.GetResponse()
'get response stream
Dim smY As Stream = respX.GetResponseStream
'examine the results
Dim encode As Encoding = System.Text.Encoding.GetEncoding("utf-8")
Dim sw As New StreamReader(smY, encode)
strResponse = sw.ReadToEnd
'close stream
smY.Close()
'close the response object
respX.Close()
'close stream reader
sw.Close()
Catch ex As Exception
strResponse = ex.Message.ToString
End Try
Return strResponse
End Function
Upvotes: 0
Views: 644
Reputation: 1
It turns out the main problem was that I was submitting two different redirect_uri's. Since Jan Halasa kindly provided the link to the OAuth2 RFC, I learned that the redirect_uri has to be exactly the same for the code request and the follow-up token request. The httputility.encode() was not necessary since my redirect_uri did not include any ampersands or other special characters.
Upvotes: 0
Reputation: 8431
Bad request almost certainly means you are sending invalid data. So the easiest way to solve the problem would be to get a log of the request and response and analyze it. The request should look like the one from the OAuth2 RFC.
But looking at your code, I see one thing that could cause the problem - you are sending a request with application/x-www-form-urlencoded
content type, but you don't encode its data. If the values (auth code or redirectUri) contain characters such as the ampersand &
, it will unintentionally introduce new request parameters (&something=
) and make the original values invalid. So your code should be something like this:
strPostData = "grant_type=authorization_code"
strPostData += "&code=" & HttpUtility.UrlEncode(strCode)
strPostData += "&redirect_uri=" & HttpUtility.UrlEncode(strRedirectURI)
And in the ReadURLwithAuthentication
method, the Case "POST", "DELETE"
should probably be for POST
and PUT
methods, because a DELETE
request cannot have a body.
Upvotes: 1