2

I am using the following to retrieve JSON via RestTemplate in Spring 4:

protected DocInfoResponse retrieveData(String urlWithAuth) {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + auth.getSig());
    HttpEntity<String> request = new HttpEntity<String>(headers);
    ResponseEntity<DocInfoResponse> response = restTemplate.exchange(urlWithAuth, HttpMethod.GET, request, DocInfoResponse.class);
    return response.getBody();
}

I used the same code (with different response class) to successfully get a JSON doc from the same site (with different parameters to get a different doc).

When I execute the above code I receive the following stack trace (in part):

Caused by: org.springframework.web.client.HttpClientErrorException: 401 Unauthorized 
at 
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]

Can anyone point me to why this might be receiving the exception?

Squigglylot
  • 41
  • 1
  • 1
  • 5
  • Have you tried to access the same from browser or postman? Is it working there with this authentication? – Coder Mar 14 '17 at 16:46
  • Yes, I have gotten the same URL to successfully return expected results in browsers. – Squigglylot Mar 16 '17 at 18:54
  • It surely is an authentication problem. Are you generating digital signatures for authentication? Is the signature URL specific? – Coder Mar 16 '17 at 19:16
  • Digital signature is being generated. That is in the 'auth.getSig()' call. There is nothing in the site documentation that specifies it is URL specific. The same signature/algorithm is used in both cases (the URL that works and the one that doesn't). – Squigglylot Mar 16 '17 at 20:30
  • Can you share the other method which is working? – Coder Mar 16 '17 at 20:42
  • It is exactly the same, with the following two exceptions: 1) the URL, 2) the response object (SyncResponse.class vs DocInfoResponse.class -- the former is working, the latter is the problem). – Squigglylot Mar 16 '17 at 20:53
  • Some digital signatures are URL specific. That being said resttemplate encodes the URL making it a bit difficult when you have a digital signature which most of the times is specifc to the URL. I am not sure how `auth.getSig()` generated a digital signature as in most of the cases it is validated against the client information provided in the URL – Coder Mar 16 '17 at 21:00
  • Hi I'm having the exact same problem. I am able to connect to the target URL using FireFox RESTClient in Basic Authentication. However, I'm getting a "401 Unauthorized" while usint Spring RestTemplate – avi.elkharrat Jul 21 '17 at 09:20

3 Answers3

2

I found that my issue originally posted above was due to double encryption happening on the auth params. I resolved it by using UriComponentsBuilder and explicitly calling encode() on the the exchange().

SyncResponse retrieveData(UriComponentsBuilder builder) {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<String> request = new HttpEntity<String>(headers);
    ResponseEntity<SyncResponse> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, request, SyncResponse.class);
    return response.getBody();
} 

My UriComponentsBuilder was built using:

UriComponentsBuilder buildUrl(String urlString) {
    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(urlString);

    return auth.appendAuth(builder);
}

(The auth.appendAuth() adds additional .queryParams() needed by the target service in urlString.)

The call to execute this was retrieveData(buildUrl(urlString));.

Squigglylot
  • 41
  • 1
  • 1
  • 5
  • I have a similar issue but I cannot fix it. Can you help me if you have any idea about it? Here is the link : https://stackoverflow.com/questions/74843944/spring-boot-microservices-rest-template-401-unauthorized-error – S.N Dec 18 '22 at 23:08
0

After investigating on my own problem, I realized that FireFox RESTClient was successful because I was connected to the target URL. The Basic Auth I thought I was using, was not so basic after all.

Eventually, I read the doc of the app i was trying to connect to and realized they propose a connection token mechanism. Now it works.

After reading your code, I say it looks quite OK, although I'm not sure what is your object auth on which you call getSig.

First things first: try to access your service from any client, like a web browser, a PostMan or RESTClient. Make sure you successfully retrieve your infos WITHOUT being connected to your app!!!

Depending on the result, I say you should, either try to encrypt manually your Authorization token (you'll easilly find posts on this site to show you how to) or try another connection mechanism.

avi.elkharrat
  • 6,100
  • 6
  • 41
  • 47
  • In my case, the authorization string was being double encrypted. I resolved this by doing something similar to your suggestion of manual encryption ... using 'UriComponentsBuilder'. – Squigglylot Jul 24 '17 at 19:43
  • glad this helped! your question was helpful too :) – avi.elkharrat Jul 26 '17 at 11:11
0

The process of creating the Authorization header is relatively straightforward for Basic Authentication, so it can pretty much be done manually with a few lines of code:

 HttpHeaders createHeaders(String username, String password){
   return new HttpHeaders() {{
         String auth = username + ":" + password;
         byte[] encodedAuth = Base64.encodeBase64( 
            auth.getBytes(Charset.forName("US-ASCII")) );
         String authHeader = "Basic " + new String( encodedAuth );
         set( "Authorization", authHeader );
      }};
}

Then, sending a request becomes just as simple:

RestTemplate restTemplate = new RestTemplate();    
restTemplate.exchange
     (uri, HttpMethod.POST, new HttpEntity<T>(createHeaders(username, password)), clazz);

https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring#manual_auth

Andrii
  • 67
  • 9