4

I am trying to access web resource secured with HTTPBasicAuth using python3. I am providing the right credentials still it is showing 401 unauthorized error.

I am using urllib for doing it as I failed to do it using requests module because of ssl and proxy error. In urllib it just shows 401 unauthorized error hence I am able to hit that website.

Any suggestion how to solve this issue?
(I cannot post the credentials publicly for security reasons, that's why I just used *)

import urllib.request
import urllib.parse
import ssl
import requests
from requests.auth import HTTPBasicAuth
line =1
try:

    line += 1#2
    myssl = ssl.create_default_context()#Bypass SSL verification when trying to access a secured website
    myssl.check_hostname = False
    myssl.verify_mode = ssl.CERT_NONE#SSL verification disabled
    USERNAME = '******'
    PASSWORD = '******'
    login_data = dict(username=USERNAME, password=PASSWORD)


    headers = {}
    headers['User-Agent'] = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
    p = urllib.request.HTTPPasswordMgrWithPriorAuth()
    p.add_password(None,'https://bmh309668.rbeigcn.com:44330/sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/',USERNAME,PASSWORD)
    handler = urllib.request.HTTPBasicAuthHandler(p)
    opener = urllib.request.build_opener(handler)
    urllib.request.install_opener(opener)


    line += 1#3
    data = urllib.parse.urlencode(login_data)
    data = data.encode('utf-8')#while using post we can send a byte format not a string so encode it to utf-8
    line += 1#4
    req = urllib.request.Request('https://bmh309668.rbeigcn.com:44330/sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/',data=data, headers = headers)#request for the web page
    line += 1#5
    response = urllib.request.urlopen(req,context=myssl,data=data)#by using context=myssl we disable SSL verification
    line += 1#6
    #x = urllib.request.urlopen('https://bmh309668.rbeigcn.com:44330/sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/',context=myssl,data=data)
    line += 1#7
    print(response.read())#print the data

except Exception as e:
    print("Exception raised at line number: ",line)
    print(str(e))

Getting exception at line number 5

Hultner
  • 3,710
  • 5
  • 33
  • 43
  • Are you using Python 3 or 2? You tagged both. If I were you I would probably try fixing your problem with requests first as it's a much easier utility to use then urllib. – Hultner Mar 27 '18 at 12:44
  • I am using Python3, it is there in my question. Previously I was using requests, there I was not able to hit the website even. In urllib atleast I can reach the website and fail due to unauthorization. Any suggestion how I can fix this problem? – Sarthak Mahapatra Mar 28 '18 at 07:10
  • Well from glancing your code it looks like the site you're trying to to fetch doesn't have a valid TLS-cert, or a self-signed one. If it is self-signed and you want to be sure it's your trusted source you should add that certificate manually to a list of trusted sources. As you've implemented it now it would be trivial for a bad actor to replace your trusted source with an untrusted MITM or similar. Are you sure you don't want to verify the source? – Hultner Mar 28 '18 at 08:54
  • Sarthak, I added an answer which I've tested on my own basic authed server using my own credentials. It does work perfectly well for me so it should likely work for you as well considering you're providing the correct credentials. – Hultner Mar 28 '18 at 09:42
  • Hultner thanks for your code but it is still not working. Here is the exception -- HTTPSConnectionPool(host='bmh309668.rbeigcn.com', port=44330): Max retries exceeded with url: /sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] getaddrinfo failed',)). This was the error when I was using requests module previously. – Sarthak Mahapatra Mar 29 '18 at 14:03
  • What happens if you provide invalid credentials? Seems to work for me but can’t test on your particular server as I don’t have the correct credentials. – Hultner Mar 31 '18 at 09:00

2 Answers2

1

Took help from Hultner's code and then disabled the urllib3 warnings. Now it is working.

import requests
import urllib3

line = 1 #line number denotes the exact place where the exception is raised
try:
    # Your configuration
    USERNAME = "******"
    PASSWORD = "******"
    URI = "https://bmh309668.rbeigcn.com:44330/sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/"
    # specify the user agent
    USER_AGENT = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
    # verify the host. Skips verification if set to false
    CERT_FILE = False
    #diable the warnings
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    urllib3.disable_warnings(urllib3.exceptions.HTTPError)

    # Create a Session to contain you basic AUTH, it will also persist your cookies
    line += 1#2
    authed_session = requests.Session()

    # Add your credentials
    line += 1#3
    authed_session.auth = (USERNAME, PASSWORD)

    # Cert verification, will not verify on false
    line += 1#4
    authed_session.verify = CERT_FILE

    line += 1#5
    authed_session.headers.update({'User-Agent': USER_AGENT})

    # Fetch the actual data
    line += 1#6
    fetched_data = authed_session.get(URI)
    line += 1#7
    print(fetched_data.text)
except Exception as e:
    print(line)
    print(str(e))
0

I can see that you import requests but doesn't use it. It's a excellent library for this use case.

Your core problem seems to be that you want to fetch data from a site with a self signed TLS/SSL-cert which is also protected by HTTPBasicAuth.

I've verified with a similar setup on my own server that below code should work for that case.

import requests

# Your configuration
USERNAME = "***"
PASSWORD = "***"
URI = "https://bmh309668.rbeigcn.com:44330/sap/opu/odata/sap/IBAS_PLANT_MAINTENANCE_SRV/CodeGroups/"
# Do you need to specify the user agent? Does the site run a white/blacklist?
USER_AGENT = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"
# WARNING: You should point this to your cert file for the server to actually
# verify the host. Skips verification if set to false
CERT_FILE = False

# Create a Session to contain you basic AUTH, it will also persist your cookies
authed_session = requests.Session()

# Add your credentials
authed_session.auth = (USERNAME, PASSWORD)

# Cert verification, will not verify on false
authed_session.verify = CERT_FILE

authed_session.headers.update({'User-Agent': USER_AGENT})

# Fetch the actual data
fetched_data = authed_session.get(URI)
print(fetched_data.text)

It will work with CERT_FILE set to false but I highly recommend to specifying the path to the certfile for the host you use, so it can actually verify the host.

Hultner
  • 3,710
  • 5
  • 33
  • 43