PDA

View Full Version : Using HTTP POST from ASP.NET



maxeq
09-21-2006, 06:03 PM
I'm trying to do the https post to the da api from an asp.net application on a remote server. With every method I try, i'm getting a 401 unauthorized error.

Any suggestions? Thanks!



Public Function CreateUser( _
ByVal UserName As String, _
ByVal Email As String, _
ByVal Password As String, _
ByVal Domain As String, _
ByVal Package As String, _
Optional ByVal IP As String = sIP, _
Optional ByVal Notify As Boolean = True _
) As String

Dim sSubmissionURL As String = sURL & "CMD_ACCOUNT_USER"
Dim sQueryString As String = "action=create&add=Submit"

' Build the query string
sQueryString += "&username=" & UserName
sQueryString += "&email=" & Email
sQueryString += "&passwd=" & Password
sQueryString += "&passwd2=" & Password
sQueryString += "&domain=" & Domain
sQueryString += "&package=" & Package
sQueryString += "&ip=" & IP

If Notify = True Then
sQueryString += "&notify=yes"
Else
sQueryString += "&notify=no"
End If

Dim web As New System.Net.WebClient
Web.Headers.Add("Content-Type", "application/x-www-form-urlencoded")


Dim d As Byte() = System.Text.Encoding.ASCII.GetBytes(sQueryString)

' In case of problem with certificate
System.Net.ServicePointManager.CertificatePolicy = New MyCertificateValidation

web.Credentials = New NetworkCredential(sAdminUser, sAdminPwd)

Dim res As Byte() = Web.UploadData(sSubmissionURL, sMethod, d)

fwpeter
09-22-2006, 12:08 AM
In fact you could write it in every language. Make sure you're logged on to the DA system and check the output of your POST-command.

maxeq
09-22-2006, 06:32 AM
I logged into DirectAdmin and took a look at the logs. I don't know if i'm interpreting this correctly, but to me it looks like the app on the windows server isn't passing the username (and maybe password) for some reason.


Error Log:

2006:09:21-22:07:22: Can't connect to ssl!
2006:09:21-22:07:22: ->error ssl


Security Log:

2006:09:21-22:15:48: *** [remote ip address] has tried to login with an invalid username: '(null)' ***

fwpeter
09-22-2006, 06:57 AM
Did you set sAdminUser and sAdminPwd?



web.Credentials = New NetworkCredential(sAdminUser, sAdminPwd)

maxeq
09-22-2006, 07:01 AM
Yes. I tried using them each as plain text, and also tried base64 encoding them using the following function.



Public Function Base64Encode(ByVal StringToEncode As String) As String
Dim data() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(StringToEncode)
Dim str As String = Convert.ToBase64String(data)

Return str
End Function

maxeq
09-22-2006, 11:49 AM
Figured this out, just thought I'd post what the problem was in case anyone else has trouble with it.

Found this posted on Google Groups:

http://groups.google.com/group/microsoft.public.dotnet.general/browse_thread/thread/c8b05c4a2c650487/7a4e73e3824d75ef%237a4e73e3824d75ef



The reason you are not seeing the credentials passed on the
inital request to the web server is because Microsoft is following
section 2 of RFC 2617(http://www.faqs.org/rfcs/rfc2617.html)


Hereís the main benefit of using pre-authenticate. Suppose Iím going to
make 50
requests to <http://server/path/> and this URL is protected with Basic
authentication. On the first request, the client gets challenged by the
server and
sends back a second request which contains information that the server
accepts
(assuming auth succeeds) so it can send back the requested resource.
With the pre-authenticate property set to true:
The remaining 49 requests will include the authorization information in the
first
request they send to the server so the server will not challenge the client
and
force it to do another round trip before getting the resource.
The total number of roundtrips between client and server will be 51.
With the pre-authenticate property set to false:
The remaining 49 requests will not include the authorization information in
the
first request and will therefore be challenged by the server on each first
request
and will only get the desired resource after sending the authorization
header in
the second request.
The total number of roundtrips between client and server will be 100.
In other words, pre-authenticate=true is one request shy of taking half the
time of
pre-authenticate=false. Note that pre-authentication only works for Digest
and
Basic in v1.0. It canít work for NTLM because it is connection-based
however the
fact that it is connection based means that youíll only get challenged once
per
connection so it isnít an issue if you are caching connections. In the
Whidbey
release of the .NET Framework weíll also support pre-authentication for
Kerberos.


In order to get the inital request to send credentials, you will need to
use the
workaround of overriding the GetWebRequest method in the proxy code.


(Hack code obtained from the Internet)
The PreAuthenticate property on .NET's
System.Web.Services.Protocols.SoapHttpClientProtocol is supposed to force
the SOAP
client proxy to send credentials with the first request, rather than doing
the
challenge/response exchange. If you add the following code to your SOAP
Client
proxy, you can make PreAuthenticate work (this example is for basic
authentication):
protected override System.Net.WebRequest
GetWebRequest(Uri uri) {
System.Net.HttpWebRequest request =
(System.Net.HttpWebRequest)base.GetWebRequest(uri);
if (this.PreAuthenticate) {
System.Net.NetworkCredential nc =
this.Credentials.GetCredential(uri,"Basic");
if (nc != null) {
byte[] credBuf =
new System.Text.UTF8Encoding().
GetBytes(nc.UserName + ":" + nc.Password);
request.Headers["Authorization"] =
"Basic " + Convert.ToBase64String(credBuf);
}
}
return request;
}


This work around modifies the web service proxy class which is
automatically generated. This means every time someone updates a "web
reference" in
Dev Studio, they would need to reinsert the "hack" code.


Let me know if you have any questions or conerns.


Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.


so intead of


web.Credentials = New NetworkCredential(sAdminUser, sAdminPwd)

I had to do something like this:



web.Headers.Add("Authorization", "basic " & Base64Encode(sAdminUser & ":" & sAdminPwd))


Hope this helps someone out, it was driving me crazy for about a full day.