Could anyone explain to me why basic auth is working and the digest isn't working or not showing up in the http headers on the server anyway.
public String login(UserDTO user)
{
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
// client.addFilter(new HTTPBasicAuthFilter(user.getUsername(), user.getPassword()));
client.addFilter(new HTTPDigestAuthFilter(user.getUsername(), user.getPassword()));
ClientResponse response = client.resource(url + "user/login").accept("application*json").type("application/json").get(ClientResponse.class);
System.out.println(response.toString());
return null;
}
If I use:
client.addFilter(new HTTPBasicAuthFilter(user.getUsername(), user.getPassword()));
I get an authorization header on the server:
USER LOGIN REQUEST
request:uri: /StambomenWebAPI/rest/user/login
method: GET
QueryString: null
Parameters:
Headers:
Name: accept Value: application*json
Name: content-type Value: application/json
Name: authorization Value: Basic QXhsOkxvbA==
Name: user-agent Value: Java/1.7.0_51
Name: host Value: localhost:8084
Name: connection Value: keep-alive
USER AND PASS[XXXXX, XXXXX]
But when I use
client.addFilter(new HTTPDigestAuthFilter(user.getUsername(), user.getPassword()));
I do not get an authorization header field ... :s ?
Using jersey with tomcat v7
My regards and thx in advance for any help
You are not getting an authorization header field because of the digest authentication workflow. See here for more details, but basically:
Client makes a request with no Authorization header
Server responds with a 401 status and a WWW-Authenticate header that looks something like:
Digest realm="testrealm#host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
Client repeats the request with the correct Authorization header now that it has digest info from server
From the client side, this is all handled by the Jersey HTTPDigestAuthFilter. So, the filter makes the request without an Authorization header first, and your server should return a 401 status with a WWW-Authenticate header that has the necessary Digest info. Then the filter repeats the request with the correct Authorization header, and your server should authenticate and return the content.
After this initial handshake, the HTTPDigestAuthFilter remembers the necessary digest info, so for all requests after the very first request, the Authorization header will be included.
Related
I'm trying to send a simple GET to an HTTP endpoint with java.net.http.HttpClient. The endpoint requires basic authentication. Simple enough, I'm doing what everyone's doing:
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.authenticator(new Authenticator(){
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("guest","guest".toCharArray());
}
})
.build();
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("localhost:15672/api/overview")
.build();
HttpResponse<Void> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
However, this throws an IOException "WWW-Authenticate header missing for response code 401". It is not completely unreasonable to me that the server initially responds with 401 and the client then re-tries the request with the help of the Authenticator. The header is mandatory and if it is absent, that warrants an exception.
So far, so good. However, when I do the same request via curl, the header is present:
> curl -i http://localhost:15672/api/overview
HTTP/1.1 401 Unauthorized
content-length: 0
content-security-policy: script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'
date: Thu, 08 Jul 2021 11:06:45 GMT
server: Cowboy
vary: origin
www-authenticate: Basic realm="RabbitMQ Management"
What am I doing wrong here?
In the mean time I found out what the problem was: The server I'm contacting is buggy. The first GET returned exactly what is shown as the curl result. The Java HttpClient reacted correctly and sent a second GET with credentials. The credentials were wrong (for testing purposes) but the response was not a 403 as one would expect, but another 401 and this second 401 response is the one missing the header.
For basic authorization, you can do
String plainCreds = "myuser:mypassword";
byte[] base64Bytes = Base64.encodeBase64(plainCreds.getBytes());
HttpRequest request = HttpRequest.newBuilder()
.get()
.uri(URI.create("localhost:15672/api/overview"))
.header("Authorization", "Basic " + new String(base64Bytes))
.build();
I'm working on a project which requires to call GitHub APIs several times and I reached the limit of 60.
I read that with authentication you get 5000 as limit but I can't understand how I can authenticate my requests in my java program. I got my authentication token on Github and this is the way I'm building the request in java:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.build();
what should I add to the request to authenticate it?
I tried adding the header authToken:myToken but it didn't work.
Solved:
Once I got the token on my GitHub profile > Settings > Developer Settings > Personal Access Tokens, I added the header `"Authorization: Bearer "myToken" " to the http request so the request becomes:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder().header("Authorization","Bearer <myToken>")
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.build();
You need to add Http request header Authorization to your request and the header should contain your token. So if your code is written on Java 11 or higher as it appears to be than you need to change your code to:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.header("Authorization", "your-tocken")
.build();
Background
I have to send some info like cookie and csrf-token(fetched from web application) as header to third party rest client using resttemplate.The way I am sending is as below:
I have set them in my yml file.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("csrf_token", csrf_token);
headers.add("Cookie", cookie);
Snap of my postman req/res
csrf issue postman
I am stuck here because with same token i am able to hit the rest client directly with postman but i am facing above issue with my own API which isinternally calling client using resttemplate.
what is the way to send the csrf token if my approach is wrong.
So I used answer for this question as my tutorial for token based authentication. But I still have a problem with setting up authorization header.
In my authenticateUser method I tried to set up a bearer header, here's th code
#POST
#Path("/users/authentication")
#Produces("application/json")
#Consumes("application/x-www-form-urlencoded")
public Response getUsers(#FormParam("username") String username,
#FormParam("password") String password){
try{
if(userDao.existUser(username, password)){
User uUser = new User(userDao.getUser(username, password));
uUser.setToken(userDao.issueToken());
uUser.setTokenExpDate();
userDao.updateUser(uUser);
Response response = Response.ok(userDao.getUser(uUser.getId()).getToken())
.header(HttpHeaders.AUTHORIZATION, "Bearer "+userDao.getUser(uUser.getId()).getToken())
.build();
System.out.println(response.getHeaderString(HttpHeaders.AUTHORIZATION));
return response;
}
}catch(Exception e){
return Response.status(Response.Status.UNAUTHORIZED).build();
}
return null;
}
As you can see I'm setting it on response variable and it's there. But once I go to secured method and my AuthenticationFilter activates I find out that the header that i get from requestContext is null. How do I sent token to this header properly in this situation? Here's my full code
The header must be included by the client, not by the server. The general flow is this
1)the client authenticates in your Service with credentials, then the server builds a token and returns it to the client, which stores the token in a secure storage
2)the client performs a request and include the token in the header.
POST /yourservice
Authorization: Bearer thetoken
3)The server checks the header, extracts the token and validate it
nni have a problem calling a web service using jersey client.
I tried successfully as a test with : "http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%2248907%22&format=json"
using this code :
Client client = Client.create();
WebResource webResource = client.resource("http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%2248907%22&format=json");
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
String json = response.getEntity(String.class);
System.out.println(json);
but i can't do it when i call amazon webservice : http://ws.amazon.com/widgets/q?Operation=GetResults&Keywords=cool&SearchIndex=All&multipageStart=0&InstanceId=0&multipageCount=10&TemplateId=8002&ServiceVersion=20070822&MarketPlace=US
Is it because, I get a json file as response ?
Any help please ?
After experimenting with the Amazon web service with various form HTTP requests. I finally figured out that the problem is because of the User-Agent value sent in the HTTP Header.
For some reason, Amazon Rest Service is not able to handle the presence of period character . in the HTTP Header under User-Agent.
When sending a HTTP request with . as below
GET http://ws.amazon.com/widgets/q?Operation=GetResults&Keywords=cool&SearchIndex=All&multipageStart=0&InstanceId=0&multipageCount=10&TemplateId=8002&ServiceVersion=20070822&MarketPlace=US HTTP/1.1
User-Agent: Java.
Host: ws.amazon.com
Connection: keep-alive
Amazon WS sends a HTTP response without Body content
HTTP/1.1 200 OK
Date: Fri, 27 Sep 2013 19:29:54 GMT
Server: Server
Content-Length: 0
Vary: Accept-Encoding,User-Agent
Cneonction: close
Content-Type: text/plain
If the . is removed from the Content-Type, the response body does contain the detailed Json Content. This most likely looks like an issue on Amazon Rest Service implementation.
You can change the code as follows to see the Json content and get away with the problem
ClientResponse response = webResource.header("User-Agent", "SomeAgentNameWithoutPeriodChar").get(ClientResponse.class);