Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP basic authentication not working in python 3.4

I am trying to login to a REST API using HTTP Basic Authentication but it is not working and giving the error

HTTP error 400: Bad Request

Here is my code:

import urllib.parse
import urllib.request
import urllib.response

# create an authorization handler
#auth_handler = urllib.request.HTTPPasswordMgrWithDefaultRealm()
auth_handler = urllib.request.HTTPBasicAuthHandler()


# Add the username and password.
# If we knew the realm, we could use it instead of None.

userName = "username"
passWord  = "pass"
top_level_url = "http URL"
auth_handler.add_password(None, top_level_url, userName,passWord)


# create "opener" (OpenerDirector instance)
opener = urllib.request.build_opener(auth_handler)



# Install the opener.
# Now all calls to urllib.request.urlopen use our opener.
urllib.request.install_opener(opener)

# use the opener to fetch a URL
try:
    result = opener.open(top_level_url)
    #result = urllib.request.urlopen(top_level_url)
    messages = result.read()
    print (messages)  
except IOError as e:
    print (e)
like image 497
Vab Avatar asked Apr 17 '15 20:04

Vab


People also ask

How do I use Basic HTTP Authentication with the Python requests library?

You'll need to import the following first. Part of the basic authentication header consists of the username and password encoded as Base64. In the HTTP header you will see this line Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= . The encoded string changes depending on your username and password.

How can I pass the basic HTTP authentication?

We can do HTTP basic authentication URL with @ in password. We have to pass the credentials appended with the URL. The username and password must be added with the format − https://username:password@URL.

How do I set basic authentication in HTTP header?

Basic Auth:The client sends HTTP requests with the Authorization header that contains the word Basic, followed by a space and a base64-encoded(non-encrypted) string username: password. For example, to authorize as username / Pa$$w0rd the client would send. Note: Base64 encoding does not mean encryption or hashing!


2 Answers

The following python3 code will work:

import urllib.request
import base64
req = urllib.request.Request(download_url)

credentials = ('%s:%s' % (username, password))
encoded_credentials = base64.b64encode(credentials.encode('ascii'))
req.add_header('Authorization', 'Basic %s' % encoded_credentials.decode("ascii"))

with urllib.request.urlopen(req) as response, open(out_file_path, 'wb') as 
out_file:
    data = response.read()
    out_file.write(data)
like image 145
Tobias Ernst Avatar answered Oct 21 '22 12:10

Tobias Ernst


Updated for Python 3.x compatibility.

The requests library offers a far easier way of making this sort of request:

import requests

response = requests.get('http://service.example.com',
                        auth=requests.auth.HTTPBasicAuth(
                            'username', 'password'))
print(response.text)

In my own testing this works out fine, while a solution involving urllib.request (like yours, or using the code verbatim from the examples in the documentation) will fail to send the Authentication: header.

like image 24
larsks Avatar answered Oct 21 '22 10:10

larsks