views:

1469

answers:

3

I am creating an application in .NET that will serve as a second UI for my already-deployed Django app. For some operations users need to authenticate themselves (as Django users). I used a super-simple way to do this (without encrypting credentials for simplicity):-

Step 1. I created a django view that accepted the username and password through two HTTP GET parameters and passed them on to django.contrib.auth.authenticate() as keyword arguments. See the code below:

    def authentication_api(request, raw_1, raw_2):
        user = authenticate(username=raw_1, password=raw_2)
        if user is not None:
            if user.is_active:
                return HttpResponse("correct", mimetype="text/plain")
            else:
                return HttpResponse("disabled", mimetype="text/plain")
        else:
            return HttpResponse("incorrect", mimetype="text/plain")

Step 2. I called this using the following code in .NET. The 'strAuthURL' in the following representes a simple django URL mapped to the django view above:

    Dim request As HttpWebRequest = CType(WebRequest.Create(strAuthURL), HttpWebRequest)
    Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
    Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
    Dim result As String = reader.ReadToEnd()
    HttpWResp.Close()

This works flawlessly, although it is nothing more than a proof-of-concept.

Now I want to do this via HTTP POST so I have done the following: -

I created a django view for the doing authentication using POST data

    def post_authentication_api(request):
        if request.method == 'POST':
            user = authenticate(username=request.POST['username'], password=request.POST['password'])
            if user is not None:
                if user.is_active:
                    return HttpResponse("correct", mimetype="text/plain")
                else:
                    return HttpResponse("disabled", mimetype="text/plain")
            else:
                return HttpResponse("incorrect", mimetype="text/plain")

I have tested this using restclient and this view works as expected. However I can't get it to work from the .NET code below:

    Dim request As HttpWebRequest = CType(WebRequest.Create(strAuthURL), HttpWebRequest)
    request.ContentType = "application/x-www-form-urlencoded"
    request.Method = "POST"
    Dim encoding As New UnicodeEncoding
    Dim postData As String = "username=" & m_username & "&password=" & m_password
    Dim postBytes As Byte() = encoding.GetBytes(postData)
    request.ContentLength = postBytes.Length
    Try
        Dim postStream As Stream = request.GetRequestStream()
        postStream.Write(postBytes, 0, postBytes.Length)
        postStream.Close()
        Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
        Dim responseStream As New StreamReader(response.GetResponseStream(), UnicodeEncoding.Unicode)
        result = responseStream.ReadToEnd()
        response.Close()
    Catch ex As Exception
        MessageBox.Show(ex.ToString)
    End Try

The server is giving me a 500 internal server error. My guess is that the POST request is not properly set up in .NET. So I basically need some guidance on how to call the django view from .NET sending POST data.

Thanks, CM

+1  A: 

Looks ok to me. I recommend using Wireshark to see what your restclient is sending in the headers and and see what your app sending in the headers.

Strelok
+2  A: 

If you aren't doing any session sharing between the two sites and the .Net site has access to the Django app's DB you could authenticate straight against the db. This question is about how to go from Python to .Net but it should help you out when your hashes don't exactly match up.

Sam Corder
A: 

It's working now. The HTTP headers were OK, the source of the problem were the following lines:

    Dim encoding As New UnicodeEncoding
    .
    Dim postBytes As Byte() = encoding.GetBytes(postData)

Essentially, this was resulting in a data stream with null bytes between the character bytes. That of course is not what Django authentication expects in the parameters. Changing to ASCIIEncoding solved the problem.

> Looks ok to me. I recommend using Wireshark to see what your restclient is sending in the headers and and see what your app sending in the headers.

This set me off on the right path towards troubleshooting this. I tried with Wireshark, but then used HTTP Debugger which seemed more suited for the job.

The right tools can save one hours!

chefsmart
That's true, there are awesome HTTP debugging tools out there. I'm just used to Wireshark, all the way back from its days as Ethereal.
Strelok