I am trying to do PKI based authentication over proxy.
It works well without proxy, but asa I add proxy info it returns 401 error.
proxies = {
'http': "http://10.192.72.155:8080",
'https': "http://10.192.72.155:8080",
}
def open_url(url, key, cert):
headers = {"User-Agent": "<custom>", "Accept": "<custom>"}
response = requests.get(url, headers=headers, cert=(cert,key), timeout=300)
print response.headers, response
open_url("https://api.example.com/product/LatestUpdate", "/usr/bin/dev_certs/test_cert.key", "/usr/bin/dev_certs/test_cert.pem")
The above implementation works well, untill I add proxies to the requests.get()
response = requests.get(url, headers=headers, proxies=proxies, cert=(cert,key), timeout=300)
which returns following error:
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm=""
Server: SomeServer
Connection: Keep-Alive
Content-Length: 35
The issue was my proxy setup, it was also decrypting HTTPS traffic, because of which it was not passing the original Certificate. It worked after I disable HTTPS decryption.
Related
I trying to scraping data from this url:
https://rgis.mosreg.ru/v3/swagger/map/layer?SERVICE=GeoJSON&layer=34&bbox=37.51027598519073,55.58991,37.84716401480926,55.89414999999997&zoom=11
In web browser, if I visit main page https://rgis.mosreg.ru first (to get cookies), and next - go to this url - all works fine.
But when I trying to perform this request in Postman - its fault with 401 "Unautorized" error.
In Postman I use all same headers and cookies, like in web-browser, but it does not help.
All cookies and headers are synced with browser using Postman INTERCEPTOR
What I missing out?
Chrome screen with headers
Postman screen. Header "mojo" looks line auth header
The server seems to only accept HTTP/2 and reject HTTP/1.1 call. If you have curl compiled with http2 support, you can test this directly:
curl --http2 'https://rgis.mosreg.ru/v3/swagger/map/layer?SERVICE=GeoJSON&layer=34&bbox=37.51027598519073,55.58991,37.84716401480926,55.89414999999997&zoom=11'
Output
< HTTP/2.0 200
< server:nginx/1.19.5 (MOGT Edition # rgis-pub-app-01)
otherwise it returns 401
At the moment, you can't run this request in Postman, because Postman doesn't have http2 support yet
You can also test it with python using the httpx package (pip install httpx[http2]):
import httpx
import asyncio
url = 'https://rgis.mosreg.ru/v3/swagger/map/layer?SERVICE=GeoJSON&layer=34&bbox=37.51027598519073,55.58991,37.84716401480926,55.89414999999997&zoom=11'
r = httpx.get(url)
print(r.http_version)
print(r.status_code)
client = httpx.AsyncClient(http2=True)
async def get():
response = await client.get(url)
print(response.http_version)
print(response.status_code)
asyncio.run(get())
Output
HTTP/1.1
401
HTTP/2
200
I am getting "The remote server returned an error: (401) Unauthorized." when using the servicestack utils to call a remote API. It requires auth basic or JWT. Calling the same API from PostMan works fine.
var json = $"http://localhost:5000/API/Proxy/IsValidGuidForSetupDevice?Guid=82870f2ca21148739bff0854b306415c".GetJsonFromUrl(requestFilter: webReq => { webReq.AddBasicAuth("DevAdmin", "test1"); });
if i call below with the same user pass in a browser window. i get a valid connect and a bearer token back. The user\pass is good.
http://localhost:5000/auth/credentials?username=DevAdmin&password=test1&format=json
AM I missing something in request filter of the Util? Maybe I should be calling it differently and using a bearer token?
Update after tracing with fiddler
I moved the code into a unit test in the same project as the servicestack service. Just to remove any variables.
Fiddler shows me that : No Proxy-Authenticate Header is present. WWW-Authenticate Header is present: Basic realm="/auth/apikey" GET http://localhost:5000/auth
Raw View
HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
DNT: 1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: ss-opt=perm; loginLevel=none; X-UAId=2; ss-id=XPc7ivcCrXuN5tEWwARG; ss-pid=TDeEjUiKck82foJGLGtX
Playing around with it. I can get it to login by calling the URL directly with user and pass. The i get the bearer token back and I am able to pass it.
var json = $"http://localhost:5000//auth/credentials?username=DevAdmin&password=test1".GetJsonFromUrl();
var o = JsonObject.Parse(json);
var token = o.Get<string>("bearerToken");
var jsonr = $"http://localhost:5000/API/Proxy/IsValidGuidForSetupDevice?Guid=bc464658d6a640febbd53ba17c351919".GetJsonFromUrl(
requestFilter: webReq => { webReq.AddBearerToken(token); });
I still can't call this in one call with auth headers and I still don't know why.
Whenever diagnosing different behavior between HTTP Requests of different clients you should inspect the raw HTTP Traffic between the different clients using a HTTP Packet sniffer like Fiddler or WireShark, or if the request is made from a browser you can use their built-in Web Network Inspector tools.
Seeing and comparing raw HTTP Request/Responses are the best way to identify how the requests differ.
The AddBasicAuth() extension method lets you add HTTP Basic Auth to the Web Request, if you want to send the JWT Token instead you would use the AddBearerToken() method instead.
I am trying to verify an ID Token using the Firebase Admin SDK as per instructions. My current auth code looks like this (in Vue):
// Auth.vue, inside the firebaseui config callback
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
authResult.user
.getIdToken(/* forceRefresh */ true)
.then(function(idToken) {
// Send token to your backend via HTTPS
// ...
console.log(idToken);
})
.catch(function(error) {
// Handle error
console.log(error);
});
The login works fine and I can get authResult perfectly. However, it seems the function getIdToken is the problem, as I get the following error on my console:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at
https://securetoken.googleapis.com/v1/token?key=AIzaSyApp5yu051vMJlNLoQ1ngVSd-f2k7Pdavc.
(Reason: CORS request did not succeed).
In my request list, the one hanging is an OPTIONS method, with the following headers:
OPTIONS /v1/token?key=AIzaSyApp5yu051vMJlNLoQ1ngVSd-f2k7Pdavc HTTP/1.1
Host: securetoken.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,pt-BR;q=0.5,de;q=0.3
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-client-version
Origin: http://localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
I am not even sure where the problem lies. Is it coming from the Vue side? I am running it in a dev server (by simple yarn serve, vue cli 3). Would the solution be when I run Vue on a production server where I can actually configure cors?
Any light on the matter is extremely welcome...
Thanks!!
Figured it out.
I was calling it in the wrong place. What helped was this thread, which pointed me out to Preflighted Requests which is what the OPTIONS request is:
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data.
So I realized I should not be sending this request within my Post request where I got the authorization in the first place. Moving it to another method made it work.
i have a page that is hosted on both HTTP and HTTPS, and it makes a HTTP call with jquery to a local http server on the client computer with the following code:
var url = "http://127.0.0.1:1234/Ping";
var ajaxSettings = {
url: url,
timeout: 1000
};
return $.ajax(ajaxSettings);
the client application has the following headers:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Accept, Origin, Content-type
This works great when using http but when using https i get a error.
Is there any way to solve this? (generating a ssl certificate and registering it seems a bit overkill)
Here's what happens on the local server when application invokes HTTP request on local IIS.
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.PreAuthenticate = true;
request.KeepAlive = true;
When I execute the request, I can see the following series of HTTP calls in Fiddler:
Request without authorization header, results in 401 with WWW-Authenticate NTLM+Negotiate
Request with Authorization: Negotiate (Base64 string 1), results in 401 with WWW-Authenticate: Negotiate (Base64 string 2)
Request with Authorization: Negotiate (Base64 string 3), results in 401 with WWW-Authenticate: Negotiate (Base64 string 4)
Request with Authorization: Negotiate (Base64 string 3), results in 401 with WWW-Authenticate NTLM+Negotiate
Apparently the client and the server (both running on the same machine) are trying to handshake, but in the end authorization fails.
What is strange is that if I disable Windows authentication of the site and enable Basic authentication and send user/pwd explicitly, it all works. It also works if I use NTLM authentication and try to access the site from the browser specifying my credentials.
Well, after several hours of struggling I figured what the problem was. In order to be able to inspect network traffic in Fiddler I defined a Fiddler rule:
if (oSession.HostnameIs("MYAPP")) { oSession.host = "127.0.0.1"; }
Then I used "MYAPP" instead of "localhost" in the Web app reference, and Fiddler happily displayed all session information.
But server security was far less happy, so this alias basically broke challenge-response authentication on the local server. Once I replaced the alias with "localhost", it all worked.