401 error using Authentification on DHL-SOAP API with zeep - python

regarding Authentification on DHL-SOAP API with zeep
i tried authenticating with the code provided by derAndre. but for me it didn't worked.
i am just trying to get the "getVersion" operation but it failed because of the Authentification.
But if i use it, i get an 401.
Server returned response (401) with invalid XML: Invalid XML content received (Space required after the Public Identifier, line 1, column 50).
Content: b'\n\n401 Unauthorized\n\nUnauthorized\nThis server could not verify that you\nare authorized to access the document\nrequested. Either you supplied the wrong\ncredentials (e.g., bad password), or your\nbrowser doesn\'t understand how to supply\nthe credentials required.\n\n'
this is the code, and i'm not getting the hang of it.
session = Session()
session.auth = HTTPBasicAuth(settings.DHL_SOAP_API_USER,settings.DHL_SOAP_API_PW)
client = Client(settings.DHL_WSDL, transport=Transport(session=session))
# Build Authentification header for API-Endpoint using zeep xsd
header = xsd.Element(
'{http://test.python-zeep.org}Authentification',
xsd.ComplexType([
xsd.Element(
'{http://test.python-zeep.org}user',
xsd.String()),
xsd.Element(
'{http://test.python-zeep.org}signature',
xsd.String()),
])
)
header_value = header(user=settings.DHL_SOAP_API_USER, signature=settings.DHL_SOAP_API_PW)
result = client.service.getVersion('majorRelease:?', 'minorRelease:?', _soapheaders=[header_value])

I was facing similar problem and found a solution by following zeep debugger
Note that, my purpose was to test data via sandbox endpoint: https://cig.dhl.de/services/sandbox/soap
However, the debugger said, it was sending request to production endpoint: https://cig.dhl.de/services/production/soap
The problem was in the wsdl file that I stored geschaeftskundenversand-api-3.2.2.wsdl locally.
If you notice, by the end of the file production address has been set to production by default.
<soap:address location="https://cig.dhl.de/services/production/soap"/>
Just set it to -
<soap:address location="https://cig.dhl.de/services/sandbox/soap"/>
Everything else are okay.
One just needs to make sure that the endpoint is okay. Because credentials are bit different for these two endpoints.

Related

Python Requests / HTTPX - Authenticate All Redirected URL - How To

I wonder if there is a way to authenticate each redirected URL when working with Python modules such as httpx or requests?
Problem Statement
I am trying to connect to an API endpoint under the company network. Due to the company's cyber security measures, the API endpoint will be randomly masked with a company proxy, which causes the 307 Redirect status code.
my current code snippet looks like the below:
import httpx
api_url = 'https://demo.vizionapi.com/carriers'
head = {
'X-API-Key':'API KEY'
}
response = httpx.get(url=api_url, verify='supporting_files/cacert.pem',
headers=head, auth=('my username', 'my password'),
follow_redirects=True)
With above code, I received the 401 authentication needed error (But auth has been passed). This error will only happen when redirection occurs due to the company proxy.
Question:
My assumption is the authentication is only being passed into the first URL not the redirected URL. Therefore, I wonder if anyone know how I can use the same auth parameter for all URLs (direct & redirect)?
Any suggestion will be deeply appracaited.
I don't know what requests behavior with regards to auth during redirect is, but the first solution to come to mind is to manually follow the redirects yourself. Put your request in a loop that checks for the 3xx response codes, and handle auth however you want to.

Python requests - download image and write to file not working due to nature of URI and authentification procedure

I am writing a script that downloads Sentinel 2 products (satellite imagery) using sentinelsat Python API.
A product's description is structured as JSON and contains the parameter quicklook_url.
Example:
https://apihub.copernicus.eu/apihub/odata/v1/Products('862619d6-9b82-4fe0-b2bf-4e1c78296990')/Products('Quicklook')/$value
Any Sentinel API calls require credentials. So does retrieving a product and also opening the link stored inside quicklook_url. When I call the example in my browser I get asked to enter username and password in order to get
with the name S2A_MSIL2A_20210625T065621_N0300_R063_T39NTJ_20210625T093748-ql.jpg.
Needless to say I am just starting with the API so I am probably missing something but
requests.post(product_description['quicklook_url'], verify=False, auth=HTTPBasicAuth(username, password)).content
yields 0KB damaged file and
requests.get(product_description['quicklook_url']).content
yields 1KB damaged file.
I have looked into requests.Session
session = requests.Session()
session.auth = (username, password)
auth = session.post('URL_FOR_LOGING_IN')
img = session.get(product_description['quicklook_url']).content
The problem is I am unable to find the URL I need to post my session authentification. I am somewhat sure that the sentinelsat API does that but my looks have not yielded any successful result.
I am currently looking into the SentinelAPI class. It has the download_quicklook() function, which I am using right now but I am still curious how to do this without the function.
I guess you don't need to sent a post request. Basic authentication works by sending a header along with each request. The following should work
session = requests.Session()
session.auth = (username, password)
img = session.get(product_description['quicklook_url']).content
Your first attempt is failed because of using POST I think.
requests.gett(product_description['quicklook_url'], verify=False, auth=HTTPBasicAuth(username, password)).content
should also work.

Streamlabs API 405 response code

I'm trying to use Streamlabs API. Streamlabs API uses Oauth2 for creating apps. So first I send whoever's using my app to an authorization link containing my app's client id and the scopes I want to use.
(Something like this: streamlabs.com/api/v1.0/authorize?client_id=CLIENT-ID-HERE&redirect_uri=REDIRECT-URI&response_type=code&scope=SOME+SCOPES+HERE)
Once I've done that I receive a code at the redirect uri specified. I then use that code to get the access token for permanent access to the connected user's account. I then receive the access token from a POST request that works perfectly... Now I run into the problem. When getting the temporary code before the access token I specified the scopes: "donations.read +donations.create+alerts.write+alerts.create".
When authorizing, the app asks for permission to the different scopes. The scope in focus is "alerts.write" so that I can send test alerts using POST requests. But this doesn't work for some reason. To send a test alert I have to send a POST request to this url: "https://streamlabs.com/api/alerts/send_test_alert"
I've tried doing that in two different ways.
1:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert"
data = {
"access_token":"UserAccessTokenHere",
"type":"donation"
}
response = requests.post(url=url, data=data)
print(response.text)
2:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert?access_token=UserAccessTokenHere&type=donation"
response = requests.post(url=url)
print(response.text)
If I do print(response) it prints "Response [405]".
But if I do print(response.text) I get a long HTML document for this page: Error response page
Any ideas what's going wrong with my Python requests? send_test_alert documentation here: Link
I've contacted support and looks like you've made the same error as me.
You're not actually sending a request to the right URL.
You are a sending a request to: "https://streamlabs.com/api/alerts/send_test_alert"
You should be using the URL: "https://streamlabs.com/api/v1.0/alerts/send_test_alert"

Amazon Kinesis Video GetMedia/PutMedia

I used python 3.6 and I want to post video stream to aws kinesis with API.
I used python aws client to create stream and GetDataEndPoint but when I want to post my data with my custom request (PutMedia doesn't include in python client actually), I get an error Unable to determine service/operation name to be authorized.
I've follow the api doc of aws kinesis video media PutMedia and GetMedia.
So I start by getting endpoint with GetDataEndPoint with client method:
response = client.get_data_endpoint( # aws client method
StreamName=STREAM_NAME,
APIName='PUT_MEDIA'
)
end_point = response['DataEndpoint'] # https://s-EXAMPLE.kinesisvideo.eu-west-1.amazonaws.com
and I post my data at this url:
headers = {
"x-amzn-stream-arn": STREAM_ARN,
"x-amzn-fragment-timecode-type": "ABSOLUTE",
"x-amzn-producer-start-timestamp": start_tmstp
}
# Sign header...
response = requests.post(end_point, data=data, headers=headers) # 403 - Unable to determine service/operation name to be authorized
So I don't understand why I get this error... I've found this troubleshooting on aws doc. But they say we must specify ApiName parameter. What I do...
This error might occur if the endpoint is not properly specified. When you are getting the endpoint, be sure to include the following parameter in the GetDataEndpoint call, depending on the API to be called:
I'm also wondering if the GetMedia method is actually implemented in client as they say here because when I debug this method, client don't call GetDataEndPoint and so make request at https://kinesisvideo.region.amazonaws.com insteed of https://ID_EXAMPLE.kinesisvideo.region.amazonaws.com. So method get error Unable to determine service/operation name to be authorized as explained in troubleshooting
The error you're getting is because you're probably providing the endpoint without the "action" that in your case would be putMedia.
Try to append /putMedia to your endpoint and don't forget to specify the "content-type": "application/json" header.
Btw you have also to generate the v4 signatures for your request. You can use a lib or follow this python guide to do it.

Bad Request (400) error while trying to access REST API using requests in python

This error is so common that I found several hits on this error. However, couldn't find a solution to my problem.
I am trying to consume a REST API (not one of the publicly available ones) using requests module in Python. However, the specifications for the API consumption indicates that I call a POST method with URI, Content-type = 'application/xml' and body "<authCommand><userID> </userID><password> </password></authCommand>".
I tried this in the Python using requests:
r1 = requests.post('https://abc.360.net/rest/auth/1/login.xml',data= None, auth=('sdm#company.com','*********'), headers = {'content-type':'application/xml'})
When I run this, I receive a bad request error.
Is this the correct approach? Why am I receiving this error?
auth argument is to set Authorization header (basic http authentication by default). The API expects credentials in the body:
r = request.post(url, data=xml, headers={'Content-Type': 'application/xml'})
where xml=b"<authCommand><userID>sdm#company.com</authCommand>...".

Categories