HTTPDigestAuth Does not send Authorization headers

Hi I am working on a simple program to get a token-id from a router using REST API. The problem that I am facing, is that I do not see the Authorization headers when I use HTTPDigestAuth. When I use the Google App POSTMAN, I can see the headers and it work. What I am missing in my code?

My code:

```
import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth

user = 'pod1u1'
passwd = 'pass'

url = 'https://10.0.236.188/api/v1/auth/token-services'
auth = HTTPDigestAuth(user, passwd)
r = requests.post(url, auth=auth, verify=False)
print 'Request headers:', r.request.headers
print 'Status Code: ', r.status_code
print 'response Headers: ', r.headers

print '######################################'

auth = HTTPBasicAuth(user, passwd)
r = requests.post(url, auth=auth, verify=False)
print 'Request headers:', r.request.headers
print 'Status Code: ', r.status_code
print 'response Headers: ', r.headers
```

Shell commands w/ output:

My script --

```
$python digest.py 
Request headers: CaseInsensitiveDict({'Content-Length': '0', 'Accept-Encoding': 'gzip,     deflate, compress', 'Accept': '*/*', 'User-Agent': 'python-requests/2.2.0 CPython/2.7.5 Darwin/13.0.0'})
Status Code:  401
response Headers:  CaseInsensitiveDict({'date': 'Tue, 14 Jan 2014 00:28:27 GMT', 'content-length': '83', 'content-type': 'application/json', 'connection': 'keep-alive', 'server': 'nginx/1.4.2'})
######################################
Request headers: CaseInsensitiveDict({'Accept': '*/*', 'Content-Length': '0', 'Accept-    Encoding': 'gzip, deflate, compress', 'Authorization': u'Basic cG9kMXUxOkMxc2NvTDF2Mw==', 'User-Agent': 'python-requests/2.2.0 CPython/2.7.5 Darwin/13.0.0'})
Status Code:  401
response Headers:  CaseInsensitiveDict({'date': 'Tue, 14 Jan 2014 00:28:27 GMT', 'content-length': '448', 'content-type': 'text/html', 'connection': 'keep-alive', 'server': 'nginx/1.4.2'})
POSTMAN

POST /api/v1/auth/token-services HTTP/1.1
Host: 10.0.236.188
Authorization: Digest username="pod1u1", realm="pod1u1@ecatsrtpdmz.cisco.com", nonce="",     uri="/api/v1/auth/token-services", response="08ac88b7f5e0533986e9fc974f132258", opaque=""
Cache-Control: no-cache


{
    "kind": "object#auth-token",
    "expiry-time": "Tue Jan 14 00:09:27 2014",
    "token-id": "Vj7mYUMTrsuljaiXEPoNJNiXLzf8UeDsRnEgh3DvQcU=",
    "link": "https://10.0.236.188/api/v1/auth/token-services/9552418862"
}
```


Since we can't examine the service you're running, can you provide similar logging information like so:

``` python
import requests
from requests.auth import HTTPDigestAuth

user = 'pod1u1'
passwd = 'pass'

def log_info(response):
    print 'Request headers: ', r.request.headers
    print 'Status Code: ', r.status_code
    print 'Response Headers: ', r.headers

url = 'https://10.0.236.188/api/v1/auth/token-services'
auth = HTTPDigestAuth(user, passwd)
r = requests.post(url, auth=auth, verify=False)
log_info(r)

print 'History:
for response in r.history:
    log_info(response)
```

The server could be doing some bizarre things that we have no knowledge of without being able to examine it.


I ran the following and this is what I got:

import requests
from requests.auth import HTTPDigestAuth

user = 'pod1u1'
passwd = 'passwd'

def log_info(response):
    print 'Request headers: ', r.request.headers
    print 'Status Code: ', r.status_code
    print 'Response Headers: ', r.headers
    print 'Response Text: ', r.text

url = 'https://10.0.236.188/api/v1/auth/token-services'
auth = HTTPDigestAuth(user, passwd)
r = requests.post(url, auth=auth, verify=False)
log_info(r)

print 'History:'
for response in r.history:
    log_info(response)

/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python /Volumes/luflores-data/Users/luflores/Copy/Cisco/CiscoLive/Scripts/RESTAPI/test.py
Request headers:  CaseInsensitiveDict({'Content-Length': '0', 'Accept-Encoding': 'gzip, deflate, compress', 'Accept': '_/_', 'User-Agent': 'python-requests/2.2.0 CPython/2.7.5 Darwin/13.0.0'})
Status Code:  401
Response Headers:  CaseInsensitiveDict({'date': 'Wed, 15 Jan 2014 14:10:53 GMT', 'content-length': '83', 'content-type': 'application/json', 'connection': 'keep-alive', 'server': 'nginx/1.4.2'})
Response Text:  {"error-code": -1, "error-message": "No username or password found", "detail": " "}
History:

Process finished with exit code 0

-luis


That doesn't look like a service that requires Digest Auth. If Digest Auth is required, the 401 should contain a header like this: `WWW-Authenticate: Digest qop="auth"`. This does not. Instead, you're being returned a JSON body that contains an error message.

You need to reread the documentation for the webservice you're accessing to see how you're expected to get a token.


Why it is not sending the Authorization headers to begin with and why it works when I use Google Postman ?

-luis

On Jan 15, 2014, at 9:31 AM, Cory Benfield notifications@github.com wrote:

> That doesn't look like a service that requires Digest Auth. If Digest Auth is required, the 401 should contain a header like this: WWW-Authenticate: Digest qop="auth". This does not. Instead, you're being returned a JSON body that contains an error message.
> 
> You need to reread the documentation for the webservice you're accessing to see how you're expected to get a token.
> 
> —
> Reply to this email directly or view it on GitHub.


Digest Auth should not send headers on the initial message, because the server needs to inform you how to generate the digest. I invite you to open up the [section of code](https://github.com/kennethreitz/requests/blob/master/requests/auth.py#L69-L150) that generates the digest. We require the realm, nonce and qop from the server before we can correctly generate the header.

As to why it works when you use Postman, I advise you either capture the HTTP message Postman generates (using a tool like Wireshark or tcpdump), or you demonstrate to us how you're configuring Postman so that we can attempt to reproduce the behaviour on our own machines.


On Jan 15, 2014, at 12:03 PM, Cory Benfield notifications@github.com wrote:

> Digest Auth should not send headers on the initial message, because the server needs to inform you how to generate the digest. I invite you to open up the section of code that generates the digest. We require the realm, nonce and qop from the server before we can correctly generate the header.

Thanks, I did not knew that.

> As to why it works when you use Postman, I advise you either capture the HTTP message Postman generates (using a tool like Wireshark or tcpdump), or you demonstrate to us how you're configuring Postman so that we can attempt to reproduce the behaviour on our own machines.

I could try to do wireshark, but it us https :( . I just got Postman on google chrome and :

```
1. fill url with :  https://10.0.236.188/api/v1/auth/token-services
2. Click on Digest Auth and fill the following
    Username: myusername
    Real: myusername@mydomain.com
    Password: mypassword
    Algorithm: MD5
    The rest I left blank
3. Click Refresh Headers
4. Click Preview

    POST /api/v1/auth/token-services HTTP/1.1
    Host: 10.0.236.188
    Authorization: Digest username="myusername", realm="myusername@mydomain.com", 
                    nonce="", uri="/api/v1/auth/token-services", 
                    response="5a309d4b4fdfd18168c84bcecde10971", opaque=""
    Cache-Control: no-cache

5. Click send

    {
            "kind": "object#auth-token",
            "expiry-time": "Tue Jan 14 23:31:47 2014",
            "token-id": "//EBXzohJKOVFV/1BIeWBPf59GAkrvHgCZFOtslzB78=",
            "link": "https://10.0.236.188/api/v1/auth/token-services/8812089588"
    }
```

-luis

> —
> Reply to this email directly or view it on GitHub.


See, that's really interesting: you're providing Postman with all the header information we expect to get from the server on the 401. If you know who's running the server, you need to try to find out why the server isn't responding with a proper 401 challenge.


Thanks Cory, the server is on a Cisco router running REST API.

-luis

On Jan 15, 2014, at 4:09 PM, Cory Benfield notifications@github.com wrote:

> See, that's really interesting: you're providing Postman with all the header information we expect to get from the server on the 401. If you know who's running the server, you need to try to find out why the server isn't responding with a proper 401 challenge.
> 
> —
> Reply to this email directly or view it on GitHub.


I know someone who's an expert with Cisco routers. Can you give me some more details, he might be able to help me debug this.


I am in contact with Cisco DEs and will followup with them. I think the problem is that it does not support Digest Auth, just Basic Auth. http://www.cisco.com/en/US/docs/routers/csr1000/software/restapi/RESTAPIclient.html . I will keep this thread updated.

-luis

On Jan 15, 2014, at 10:08 PM, Ian Cordasco notifications@github.com wrote:

> I know someone who's an expert with Cisco routers. Can you give me some more details, he might be able to help me debug this.
> 
> —
> Reply to this email directly or view it on GitHub.