在尝试将用VB编写的.NET应用程序与qbo(quickbooks online)链接起来时,我一直在与Oauth2进行斗争。我可以得到我的代码,但我得到了一个"(400)Bad Request"尝试交换代码以进行访问和刷新令牌时的响应。这是我的请求访问令牌的代码:
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
答案 0 :(得分:1)
错误请求几乎肯定意味着您发送的数据无效。因此,解决问题的最简单方法是获取请求和响应的日志并进行分析。请求应该与OAuth2 RFC中的请求类似。
但是看一下你的代码,我发现有一件事可能导致问题 - 你发送了一个application/x-www-form-urlencoded
内容类型的请求,但你没有对其数据进行编码。如果值(auth code或redirectUri)包含诸如&符号&
之类的字符,则会无意中引入新的请求参数(&something=
)并使原始值无效。所以你的代码应该是这样的:
strPostData = "grant_type=authorization_code"
strPostData += "&code=" & HttpUtility.UrlEncode(strCode)
strPostData += "&redirect_uri=" & HttpUtility.UrlEncode(strRedirectURI)
在ReadURLwithAuthentication
方法中,Case "POST", "DELETE"
可能适用于POST
和PUT
方法,因为DELETE
请求不能包含正文。< / p>
答案 1 :(得分:0)
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.