I am trying to make a WISPr client. For this, I have read WISPr 1.0, 1.2 and 2.0 specifications.
Considering a 1.0 WISPr client, I have parsed the LoginURL from the hotspot login page, and try to make the authentication request (login = test, password = pass) :
POST : http://hotspot.server.com/login
Parameters : button=Login&UserName=test&Password=pass&FNAME=0&OriginatingServer=http://www.google.com
My credentials are good because I use them via the HTML form of the webpage.
With a http POST request, the authentication always failed with the response :
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>100</ResponseCode>
<ReplyMessage>Authentication Failure</ReplyMessage>
</AuthenticationReply>
I have tried with differents hotspots of other networks with other good credentials.
Do you have an idea where my error comes in my authentication request ?
You coul try using GET. this worked for me
I've done some WISPr client tools in the past and this seems quite weird, at least from the data provided. Best approach I would suggest is to use Wireshark to capture the traffic of a login session via browser and compare it to the session handled by your code. If the browser also uses POST check for missing headers, malformed data etc. If in fact browser does use GET then you should try to stick to that scenario as suggested. Maybe the hotspot supports only one kind of method, e.g. notification polling. Still, without Wireshark details it is hard to guess. Also remember that there are certain differences between WISPr 1.0 and WISPr 2.0 and you haven't state what is the version of the hotspot you are logging in to.
Related
I am attempting to use the REST api of Jenkins. Jenkins requires a POST request to a URL to delete a job. This results in the following:
I tell my chosen Client to send a POST to the appropriate URL.
The client sends a POST and authorizes itself with username and password.
Jenkins deletes the job.
Jenkins returns a "302 - Found" with the location of folder containing the deleted job.
Client automatically sends a POST to the location.
Jenkins answers with "200 - OK" and the full HTML of the folder page.
This works just fine with Postman (unless I disable "Automatically follow redirects" of course).
Jersey however keeps running into a "404" at step 5 because I blocked anonymous users from viewing the folder in question. (Or a "403" if I blocked anonymous users altogether.)
Note that the authentication works in step 1 because the job has been deleted successfully!
I was under the impression that Jersey should use the given authentication for all requests concerning the client.
Is there a way to actually make this true? I really don't want to forbid redirects just to do every single redirect myself.
To clarify: The problem is that while Jersey follows the redirect, but fails to authenticate itself again, leading to the server rejecting the second request.
Code in question:
HttpAuthenticationFeature auth = HttpAuthenticationFeature.basicBuilder()
.credentials(username, token)
.build();
Client client = ClientBuilder.newBuilder()
.register(auth)
.build();
WebTarget deleteTarget = client.target("http://[Jenkins-IP]/job/RestTestingArea/job/testJob/doDelete")
Response response = deleteTarget.request()
.post(null);
EDIT: The "302-Found" only has 5 headers according to Postman: Date, X-Content-Type-Options ("nosniff"), Location, Content-Length (0) and Server. So neither any cookies nor any tokens that Postman might use and Jersey disregard.
Question loosely related to this one - if I were able to log the second request I might be able to understand what's happening behind the scenes.
EDIT2: I have also determined that the problem is clearly with the authentication. If I allow anonymous users to view the folder in question, the error disappears and the server answers with a 200.
I found the answer with the help of Paul Samsotha and Gautham.
TL;DR: This is intended behavior and you have to set the System property http.strictPostRedirect=true to make it work or perform the second request yourself.
As also described here, HttpURLConnection decided to not implement a redirect as it is defined in the HTTP standard but instead as many browsers implemented it (so in laymans terms, "Do it like everyone else instead of how it is supposed to work"). This leads to the following behavior:
Send POST to URL_1.
Server answers with a "302 - Found" and includes URL_2.
Send GET to URL_2, dropping all the headers.
Server answers with a "404 - Not Found" as the second request does not included correct authentication headers.
The "404" response is the one received by the code, as steps 2 and 3 are "hidden" by the underlying code.
By dropping all headers, the authentication fails. As Jersey uses this class by default, this lead to the behavior I was experiencing.
A rails application can use the request object to access user agent and more data about the request.
How to detect browser type and its version
But with curl, a developer can set the header data and more. How to use curl to get a GET request exactly same as using Chrome?
Can a rails application accurately detect when a request is sent by a software like curl versus a browser?
No. cURL can simulate any HTTP request with the correct configuration. There is no way to tell the difference between Chrome and cURL from an HTTP request alone.
If you're trying to make it harder to scrape data from your server, you'll want to use other methods (rate-limiting, authentication, etc.). But there is no perfect solution to prevent a determined scraper.
In Postman, I am able to successfully request a new token using the GUI. I'm wondering how to do this programatically. Or at least see the HTTP request that Postman is making. I've tried viewing it by monitoring the network traffic in Chrome, and with Wireshark, but without success. Thank you
well, OAuth2 is quite a big subject and you are not really providing a lot of details.
Postman is just a client, it creates requests based on the data you gave it so you don't need to monitor anything, you should know how you set it up and then simply mirror that in whatever language you want. Look at headers and post data specifically.
All I can do is point you to an extensive article I wrote on OAuth2, it shows a complete implementation, how to use Postman to create the correct requests and then how to write code which makes it all work.
If you don't use dot net, you can still understand all the concepts and it should be trivial to do the same thing using a different language.
https://eidand.com/2015/03/28/authorization-system-with-owin-web-api-json-web-tokens/
If a website makes a GET request, from a HTTPS page to another HTTPS page, is that secure? Specifically, is the data in the URL / query params secure?
I'm asking because, hen I call Stripe.createToken, a connection is made to a URL with the credit card number in it. Even though the query parameter says _method=POST, it is being transmitted over a GET query param:
Request URL: https://api.stripe.com/v1/tokens?card[number]=4242424242424242&card[cvc]=123&card[exp_month]=4&card[exp_year]=2016&key=pk_test_1236&callback=sjsonp11234&_method=POST
Request Method: GET
Status Code: 200 OK
Now, I understand this is all over HTTPS, but isn't the URL part insecure? I thought that URLs get logged in various places along the way to their destination.
URLs usually do get logged in webserver logs. It is a very bad idea to sent that information as part of a GET request. The hops a request takes between the client and the destination are encrypted though. So assuming there is no web proxy or anything the only place it might be logged is on https://api.stripe.com/'s webserver.
See Are querystring parameters secure in HTTPS (HTTP + SSL)?
for more information.
From Stripe:
Because of the nature of how HTTPS works, the only information that's transmitted in plaintext to an HTTPS connection is the hostname you're connecting to (in this case, "api.stripe.com"). All other parts of the communication - including the full URL - are encrypted such that they're only decryptable by our servers. At the transport level, including cardholder details as GET parameters of the URL is no different from including them in the POST body. We only use JSONP for Stripe.js and not for any server-side bindings, in case you are worried about having those requests come up in your server logs.
Once the details get to our server, we've made changes to the configurations on our servers to ensure that the query strings are never logged, and we have routines in place that check all log files for accidental inclusion of card numbers. We've worked with our PCI auditors (who also audit Google, Apple and AWS) to ensure that this meets the standards of PCI, and are confident that we're handling cardholder data in a way that is secure.
Whenever a web request is made by Visual Studio to TFS, Fiddler will show a 401 Unauthorized error. Visual Studio will then try again with a proper Authorization Negotiate header in place with which TFS will respond with the proper data and a 200 status code.
How can I get the correct headers to be sent the first time to stop the 401?
This is how the process of Windows Integrated Authentication (NTLM) works. NTLM is a connection based authentication mechanism and actually involves 3 calls to establish the authenticated session.
The TFS API then goes to extra-ordinary lengths to make sure that this handshake is done in the most efficient way possible. It will keep the authenticated connection open for a period of time to avoid this hand-shake where possible. It will also do the initial authentication using a HTTP payload with minimal content and then send the real message if the message you were going to send is over a certain length. It does a bunch of other tricks as well to optimise the connection to TFS.
Basically, I would just leave it alone as it works well.
You will see that a web browser also does this when communicating with a web site. It will always try to give away the minimum amount of detail with the first call. If this fails, it will reveal a little more about you.
This is by design and for a very good reason.
This is how it's always done - request, get the 401 back, then send the authorization. It's part of the authentication protocol for http.