87

I'm trying to use basic HTTP authentication in python. I am using the Requests library:

auth = requests.post('http://' + hostname, auth=HTTPBasicAuth(user, password))
request = requests.get('http://' + hostname + '/rest/applications')

Response form auth variable:

<<class 'requests.cookies.RequestsCookieJar'>[<Cookie JSESSIONID=cb10906c6219c07f887dff5312fb for appdynamics/controller>]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})

But when I try to get data from different location, - I'm got 401 error

<<class 'requests.cookies.RequestsCookieJar'>[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})

As far as I understand - in second request are not substituted session parameters.

mit
  • 10,728
  • 10
  • 45
  • 74
oleksii
  • 947
  • 1
  • 8
  • 11

6 Answers6

95

You need to use a session object and send the authentication each request. The session will also track cookies for you:

session = requests.Session()
session.auth = (user, password)

auth = session.post('http://' + hostname)
response = session.get('http://' + hostname + '/rest/applications')
Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
  • 3
    Thanks for your reply, but it's doesn't work too :( Error is the same as previous – oleksii Nov 05 '14 at 00:01
  • 1
    @oleksii: define 'does not work'. And when you use POST (with no parameters, I note), does the server return any token or anything that you'd need to use for the REST API here? In other words, what does the *documentation for the API* state you need to do? – Martijn Pieters Nov 05 '14 at 08:38
  • @Sarit how so? Note that I link to the official documentation in my answer. – Martijn Pieters Jan 08 '18 at 08:22
  • @MartijnPieters Sorry I was taking about this page http://docs.python-requests.org/en/master/user/authentication/ – joe Jan 08 '18 at 08:37
  • @Sarit that page deals with all different forms of HTTP authentication. Cluttering it with session handling would cloud matters. Not all use cases need to make multiple HTTP requests, and you can get the same effect by passing in the auth info manually with every request. – Martijn Pieters Jan 08 '18 at 08:43
  • 1
    @MartijnPieters After read your comment 10th fimes. I still not understand. I can use basicAuth in the Postman. Postman will digest username/password into header `Authorization: Basic <....>`. But I could not be able to connect why I need session here, but it works! What's wrong with @oleksii attempt? – joe Jan 08 '18 at 09:17
  • 3
    @Sarit: The header needs to be included in *every request* that you send to the server; usually the only way the server can authenticate you based on the header being present, no other info. The *easiest* way to add the header to every request is to use a session. You don't *have* to, but then you have to include the header manually in each request. – Martijn Pieters Jan 08 '18 at 11:58
  • @MartijnPieters Thank you very much. New knowledge for me today. +1 – joe Jan 09 '18 at 02:50
  • Kudos! This is what I was looking for! – tavalendo May 28 '18 at 14:45
56
import requests

from requests.auth import HTTPBasicAuth
res = requests.post('https://api.github.com/user', verify=False, auth=HTTPBasicAuth('user', 'password'))
print(res)

Note: sometimes, we may get SSL error certificate verify failed, to avoid, we can use verify=False

phoenix
  • 5,738
  • 3
  • 33
  • 41
Kuppuram
  • 569
  • 4
  • 3
  • why verify failed? Browser visit shows certificate is verified. – liang May 28 '19 at 16:16
  • 3
    Consider avoiding `verify=False` since it makes the app vulnerable to MitM attacks on https protocol. – Victor Miroshnikov Jul 15 '19 at 10:37
  • 3
    Upvoted for the usage of `HTTPBasicAuth` as authentication, that was what I was looking for. I would not use `verify=False` in production. – Alvin Sartor Oct 27 '20 at 14:09
  • 1
    ```requests.posts``` does not work for me but ```requests.get``` does, there is also a shorter version ```requests.get(url, auth=(username, password))``` – Marcin Kulik Dec 14 '20 at 09:37
25

In Python3 it becomes easy:

import requests
response = requests.get(uri, auth=(user, password))
4

Below one worked for me

#!/usr/bin/python3
import xml.etree.ElementTree as ET
import requests
from requests.auth import HTTPBasicAuth

url = 'http://172.25.38.135:600/service/xx/users'      # my URL     
response = requests.get(url, auth=HTTPBasicAuth('admin', 'adminpass!'))

string_xml = response.content
tree = ET.fromstring(string_xml)
ET.dump(tree)
Anto
  • 2,192
  • 1
  • 14
  • 13
2

for python 2:

base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')

request = urllib2.Request(url)

request.add_header("Authorization", "Basic %s" % base64string) 

result = urllib2.urlopen(request)
        data = result.read()
Aaron
  • 2,177
  • 3
  • 27
  • 33
vc2310
  • 105
  • 1
  • 6
0

The following worked for me

from requests.auth import HTTPDigestAuth
url = 'https://someserver.com'
requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
codeaprendiz
  • 1,542
  • 16
  • 29