I wanted to have digest authentication Authorization header added in very http request and hence added HTTP Authorization Manager under thread group. I added URL,username, password, domain, realm (both to same name) and selected BASIC_DIGEST as the option (I wanted only digest authentication).
I also uncommented http.authentication.preemptive$Boolean=true in httpclient.parameters and uncommented httpclient.parameters.file=C:\apache-jmeter-2.12\apache-jmeter2.12\bin\httpclient.parameters in jmeter.properties file.
After done, I closed my jmeter and started it again. When I gave a run and did a wireshark capture, I figured out that GET was sent with NO Authorization header, and server sends a 401 response and jmeter closes socket and fails the case.
I am not sure what I have done wrong. Awaiting for your comments.
JMeter Logs:
2014/11/20 13:19:35 INFO - jmeter.threads.JMeterThread: Thread started: Thread Group 1-1
2014/11/20 13:19:35 INFO - org.apache.commons.httpclient.auth.AuthChallengeProcessor: digest authentication scheme selected
2014/11/20 13:19:35 INFO - org.apache.commons.httpclient.HttpMethodDirector: No credentials available for DIGEST 'users#perf.tb.com'#192.168.100.30:80
Realm should not be required for digest authentication, domain is quite enough
Make sure that you're using either HttpClient3.1 or HttpClient4 implementation
See Windows Authentication with Apache JMeter guide for details on how to configure HTTP Authorization Manager for digest and kerberos authentication types
Related
I'm using Apache Shiro for my Rest service project and I have troubles getting it to work as intended.
For rest service,I use basic authentication and as first,when I send wrong username,It returns 401 as expected.
Then I send correct user name and password,It returns 200 as expected.
As 3th step,When I send again wrong username,It returns 200,should return 401.
I think after first successful login,It doesnt need any authentication process again.How can I force it to authenticate for every request?
I couldnt find any reason or any parameter I should add in my shiro.ini.
This is my shiro.ini:
What you are seeing may be the result of your client. Before a client will send credentials to a server typically has to ask for them (responding with a 401), the client will the add the auth header. A client can work around this using "preemptive" auth, which will send the Authorization header on the initial request.
Your server is likely also configured to use cookies, which the server will process first and then return a 200 (and the client would never send the new credentials).
If this is just a REST server/client setup, you could disable session creation, using the noSessionCreation filter.
https://shiro.apache.org/web.html#default_filters
If you are still stuck take a look at your HTTP logs and watch for the headers (specifically Authorization and an Cookie headers).
My Epson TM-T88V-i receipt printer tries to fetch XML data from a server URL which needs the printer to authenticate via HTTP digest. (this Epson feature is called "Server Direct Print")
From the printer's web console I'm able to send a test request to the server but HTTP digest authentication fails. Same happens if I let the printer try to authenticate at the server.
If I try to access the URL via browser the HTTP digest username+password box appears and if I enter the credentials the XML gets displayed in the browser as expected. This shows, that the HTTP digest mechanism on server side is set up correctly (I'm using the PHP framework Symfony 2.8).
On server side I see following log information:
Step 1
[2016-04-03 16:33:01] security.INFO: An AuthenticationException was
thrown; redirecting to authentication entry point.
{"exception":"[object]
(Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException(code:
0): A Token was not found in the TokenStorage. at /home/.../src/Symfony/Component/Security/Http/Firewall/AccessListener.php:53)"}
Step 2
[2016-04-03 16:33:01] security.DEBUG: Calling Authentication entry
point.
Step 3
[2016-04-03 16:33:01] security.DEBUG: Digest Authorization header
received from user agent. {"header":"username=\"printer\",
realm=\"example\",
nonce=\"MTQ1OTk5Mzk4MS40NjQ3OmI0OTVmN2ZkZTlhYmE1NmNjNDIxNmIxMWU0OGVmYjUz\", uri=\"/export\", cnonce=\"MDAxNjM0\", nc=00000001, qop=\"auth\",
response=\"c6ad88607624efd17f7de602f6ee9def\""}
Step 4
[2016-04-03 16:33:01] security.DEBUG: Unexpected response from the
DigestAuth received; is the header returning a clear text passwords?
{"expected":"741bff6abed513b6948c26eae529b6b6","received":"c6ad88607624efd17f7de602f6ee9def"}
Step 5
[2016-04-03 16:33:01] security.INFO: Digest authentication failed.
{"exception":"[object]
(Symfony\Component\Security\Core\Exception\BadCredentialsException(code:
0): Incorrect response at
/home/.../src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php:107)"}
The log file tells us what happens server side:
In Step 1+2 the Epson tries to access the server URL which is HTTP digest protected and the server sends a 401 "unauthorized" response with a nonce (we don't see this in this log file)
In Step 3 the Epson sends the HTTP digest client authorization request including all necessary data. The response parameter contains a hash which should be generated out of the other authorization parameters
In Step 4 my symfony 2.8 application says, that the hashed response parameter which was sent by the Epson in step 3 is not the one which was expected by the HTTP digest process.
Step 5 finally shows, that the HTTP digest authentication failed.
As far as I understand, the digest authentication process (as described on wikipedia) is correct, except that the Epson doesn't calculate the correct hash in his authentication request.
Does anyone know why the Epson sends a wrong response parameter or did someone make this scenario work?
I could resolve the problem after 2 days of debugging. The length of my digest auth password was 40 chars. I reduced it somewhat about 20 chars. Not it works, dohhh.
As described in RFC 4559, the Negotiate mechanism may take several requests to complete a GSSAPI context. I cannot understand from the RFC what mechanism is used to associate those requests with one another, however. To take the example described in section 5 of the the RFC:
1:
C: GET dir/index.html
2:
S: HTTP/1.1 401 Unauthorized
S: WWW-Authenticate: Negotiate
3:
C: GET dir/index.html
C: Authorization: Negotiate a87421000492aa874209af8bc028
4:
S: HTTP/1.1 401 Unauthorized
S: WWW-Authenticate: Negotiate 749efa7b23409c20b92356
5:
C: GET dir/index.html
C: Authorization: Negotiate 89a8742aa8729a8b028
This is clear to me up until step 5. Assuming there are potentially many clients doing authentication at the same time, how does server know that the Authorization header in step 5 is the response to the data from step 4? I can't see any mention of session cookies or anything, and while I'm not an expert on GSSAPI, I don't think there's anything inherent in the GSSAPI data that can be used to associate it with an authentication session.
So what's the deal? :)
State is maintained using the TCP connection. RFC-4559 doesn't spell this out directly, likely because it would make the author feel dirty. But they elude as much in section 6 when discussing "Session-Based-Authentication" when proxies are involved. This requirement is also "called-out" in the last paragraph of RFC-7230 section 2.3 when discussing how HTTP is supposed to be a stateless protocol:
Some non-standard HTTP extensions (e.g., [RFC4559]) have been known to violate this requirement, resulting in security and interoperability problems
There is even more ambiguity with another requirement in the last paragraph in Section 6:
When using the SPNEGO HTTP authentication facility with client-supplied data such as PUT and POST, the authentication should be complete between the client and server before sending the user data. The return status from the gss_init_security_context will indicate that the security context is complete. At this point, the data can be sent to the server.
So the server should remember the authentication state after the context is successfully completed (and sent the client the 200 with the last token), to let-in one last request containing the actual payload?
Your confusion is justified.
From RFC 7235
5.1.2. Considerations for New Authentication Schemes
There are certain aspects of the HTTP Authentication Framework that
put constraints on how new authentication schemes can work:
o HTTP authentication is presumed to be stateless: all of the
information necessary to authenticate a request MUST be provided
in the request, rather than be dependent on the server remembering
prior requests. Authentication based on, or bound to, the
underlying connection is outside the scope of this specification
and inherently flawed unless steps are taken to ensure that the
connection cannot be used by any party other than the
authenticated user (see Section 2.3 of [RFC7230]).
Which is how I remembered it, but I wanted to make sure. So each request that the user sends includes all the necessary credentials. The server itself knows nothing about what the authentication is. It just asks whether the credentials are valid, and if the answer is yes, go on with the request.
We have a secured WCF service with WsHttpBinding, Client & Server certificates & transport security with Claim Based Authorization.
Everything works fine 50 % of the time. When we do request to a secure endpoint, we get the correct response. But if we send the same request again immidiatly after the first we get the following response:
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
If we then send a request again, we get normal behaviour. So the odd requests work and the even not.
But after some more investigation in the problem. We noticed that if there is at least 1:40 minutes between the previous request, we don't get the error response.
What we can confirm from the debugger and logging. The client sends the credentials to the service. We don't enter System.ServiceModel if we have the Authentication response. In the IIS trace logs we get this on a good request:
Authentication: SSL/PCT
User from token: Domain\CertifacteUserName
and this on a bad request:
Authentication: NOT_AVAILABLE
User from token:
Also in the IIS Trace logging. If we send the second request, we see that the ConnId and RawConnId are the same on both requests. And if we make multiple successful request (By allowing some time between requests) they are different for each request.
It seems to me IIS is not getting the Credentials we send, when they are there. Is this due to caching? Or something else? Does anyone has a solution.
I'm implementing an R wrapper around PiCloud's REST API using the RCurl package to make HTTP(S) requests to the API server. The API uses Basic HTTP authentication to verify that users have sufficient permissions. The PiCloud documentation gives an example of using the api and authenticating with curl:
$ curl -u 'key:secret_key' https://api.picloud.com/job/?jids=12
This works perfectly. Translating this to an equivalent RCurl's command:
getURL("https://api.picloud.com/job/?jids=12", userpwd="key:secret")
Executing this function I receive the following error message:
[1] "{\"error\": {\"msg\": \"No HTTP Authorization information present\", \"code\": 995, \"retry\": false}}"
Exploring the issue in more depth I found that the HTTP requests made by the curl command included the Authorization field in the first GET command.
RCurl does not do this. Instead it first sends a GET request without the authorization field set. If it receives a 401 error code AND a response with a WWW-Authenticate field it sends another GET request with the Authorization field.
Although the HTTP spec requires messages that return with a 401 error code to include the WWW-Authenticate field PiCloud API messages do not. Thus when calling getURL even with the userpwd option set RCurl will never send a GET request with the authorization field set. As a result authentication will always fail.
Is there any way to force RCurl to set the Authorization field in the first GET message it sends? If not are there any other R packages that I could look into using?
I've resolved the problem with the help of the author of RCurl, Duncan Lang. The solution is to explicitly set the httpauth option which sets the authentication method to try initially. This works:
getURL("https://api.picloud.com/job/?jids=12", userpwd="key:secret", httpauth = 1L)
httpauth is a bitmask specifying which authentication methods to use. See the HTTP Authentication section of the libcurl tutorial for more details.
The equivalent code in httr is:
library(httr)
GET("https://api.picloud.com/job/?jids=12", authenticate("key", "secret"))