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.
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.
We have two jira installations at our company. One that we use for our projects and a second one for testing purposes.
I'm working in a project that needs to use the JIRA REST API. For this purpose I'm connecting to our testing instance.
The problem is that while trying out the REST API, I keep getting 400 errors without a single explanation of what went wrong. I just get an HTML with
Your browser sent a request that this server could not understand
I was a bit desperate and decided to try it into our real JIRA. To my surpirse the same request gave me a different response:
{"errorMessages":[],"errors":{"project":"project is required"}}
In this case, I do get a meaningful error!
I replicated this easily. I would never get a meaningful error from the test instance, but the real one will always give me one.
I cannot keep trying out stuff in our productive JIRA, but I cannot easily continue working without getting meaningful errors. So, what could be wrong in the testing instance? I could not find any configuration about the 'verbosity' of the API responses.
I believe that this error is returned not by JIRA but rather by proxy web server that is part of you production configuration.
I suggest you to compare HTTP headers that are sent with working requests from your browser with headers you pass via curl. Googling for the "Your browser sent a request that this server could not understand" helps too
I have a web application which i need to be load tested using LoadRunner. When I record the website using vugen it works good and there is no any application bug. But when I tried to replay the script, script failed after login and while navigating to next page, say, Transaction. At the end of log, I receive error:
Action.c(252): Error -26612: HTTP Status-Code=500 (Internal Server Error)
for "http://rob.com/common/transaction
Please help me to resolve this error.
LoadRunner generates HTTP request just as your browser does, this error is the same error you would get if you would go to that URL using your browser. Error code 500 is a generic server error that is returned when there is no better (more specific error to return).
Most likely the login process requires some form of authentication which is protected against a replay attack by using some form of token. It is up to you to capture this token using Correlations in LoadRunner and replay it as the server expects. The Correlation Studio in VuGen should detect and identify the token for you but since authentication methods vary it is sometimes impossible to do this automatically and you will have to create manual correlation. Please consult the product documentation for more details on how to do it. If your website is publicly available online then post its URL and I will try to record the script on my machine.
Thanks,
Boris.
Most common reasons
You are not checking each request for a valid result being returned and using a 200 HTTP status as an assumed correct step without examining the content of what is being returned. As a result when data being returned is incorrect you are not branching the code to handle the exception. Go one to two steps beyond where your business process has come off the rails with an assumptive success and you will have a 500 status message for an out of context action occurring 100% of the time.
Missed dynamic element. Record three times. Compare the code. Address the changing components.
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.
Whenever you request a web page, you send a message to a server, and the server responds. As far as I know, most interaction occurs this way: the client says one thing to the server, and the server says one thing back. The server can't "speak until spoken to".
Are there any technologies that let the server initiate a conversation? For instance, if you had a page that you wanted to always keep up to date, the way I'd do it now is periodically make an AJAX request to get updated info from the server. However, it would be nicer if the server could just let the client know at the moment when new info was available. Is there anything around that can do this?
The concept you are looking for is push technology.
All HTTP interactions are client request, server response. To get away from polling for updates as you described, you would have to look outside of HTTP; to do this in a webpage, you would have to use a plugin, Java applet, ActiveX control, etc.