I want to consume a post method which is secured using basicAuth. I am using springBoot, Spring RestTemplate to consume it.
I've tried like this:
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping(value = "/ValidateAnswers", method = RequestMethod.POST)
public ResponseEntity<String> ValidateAnswers(#RequestBody Object requestIbject,
HttpServletRequest request, HttpServletResponse response) {
final String uri = "foo:8080//validateAnswers";
// hiding full path here,
RestTemplate restTemplate = new RestTemplate();
String plainClientCredentials = "user:pass";
String base64ClientCredentials = new String(
Base64.encodeBase64(plainClientCredentials.getBytes()));
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64ClientCredentials);
HttpEntity<String> entity = new HttpEntity<String>("parameters",
headers);
ResponseEntity<String> respEntity = restTemplate.postForObject(uri, requestIbject, String.class);
// .exchange(uri,
// HttpMethod.POST, entity, String.class);
System.err.println("=------------Response--------------");
System.err.println("----" + respEntity);
return respEntity;
}
How do I pass the headers with basicAuth and post request body ?
if you using spring > 4.3.1
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));
From your code snippets I don't think you should use post method, try get first. And refer to my previous test:
public class Test {
private HttpHeaders getHeaders(){
String plainCredentials="admin:admin";
String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Credentials);
return headers;
}
#Test
public void testLogin() {
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<String>(getHeaders());
ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/login", HttpMethod.GET,
request, String.class);
System.out.println(response.getBody());
}
}
Related
I'm creating my first REST API using JAVA Spring and when I'm making a rest call to an external API, I get
401 Unauthorized: [no body]
I think my problem is here:
requestParams.add("Grant_type", "client_credentials");
I saw some questions related to this but none well able to solve my problem.
Spring REST template - 401 Unauthorized error
Spring Boot Callable - 401 Unauthorized: [no body]
JAVA code:
public String getAuth(String client_id, String app_secret) {
String auth = client_id + ":" + app_secret;
return Base64.getEncoder().encodeToString(auth.getBytes());
}
#GetMapping(value = "/token")
public Object generateAccessToken() {
String auth = this.getAuth(
"CLIENT_ID",
"APP_SECRET"
);
RestTemplate restTemplate = new RestTemplate();
String base = "https://external-api.com";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Basic " + auth);
MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
requestParams.add("Grant_type", "client_credentials");
ResponseEntity<Object> response = restTemplate.postForEntity(
base + "/v1/oauth2/token",
requestParams,
Object.class,
headers
);
return response.getBody();
}
Here's the solution to my own question.
This is what I had to change;
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "client_credentials");
HttpEntity<?> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(
base +"/v1/oauth2/token",
request,
String.class
);
Here's the final solution:
public String generateAccessToken() {
String base = "example-api.com";
String auth = this.getAuth(
"client id",
"app_id"
);
// create an instance of RestTemplate
RestTemplate restTemplate = new RestTemplate();
// create headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "Basic " + auth);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "client_credentials");
HttpEntity<?> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(
base +"/v1/oauth2/token",
request,
String.class
);
// check response
if (response.getStatusCode() == HttpStatus.OK) {
System.out.println("Request Successful");
System.out.println(response.getBody());
} else {
System.out.println("Request Failed");
System.out.println(response.getStatusCode());
}
JSONObject object = new JSONObject(response.getBody());
return object.getString("access_token");
}
I want to get the oath2 access token and using this I want to call an another service.
Below code does the same it gets the access token and call an another API using that. Using the below code I am able to do what ever I want with the below code.
But I am new to Spring Security I just want to know if there is a better way to do this. Like rather than making a separate call to get the token and then call the service can i do it in a single call? Or Using any other class provided by Spring can I write this in a better way ?
public class TestAPIToken{
#RequestMapping(value = "/showEmployees", method = RequestMethod.GET)
public ModelAndView showEmployees(#RequestParam("code") String code) throws JsonProcessingException, IOException {
String accessToken = getAccessToken();
System.out.println("API Token ---------" + accessToken);
HttpEntity<String> response = getResponseByCallingWithToken(accessToken);
System.out.println("API Response ---------" + response.getBody());
return null;
}
private HttpEntity<String> getResponseByCallingWithToken(String accessToken) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.add("Authorization", "Bearer " + accessToken);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("msisdn", msisdn)
.queryParam("email", email);
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class);
reponse.getBody();
return response;
}
private String getAccessToken() {
ResponseEntity<String> response = null;
System.out.println("Authorization Code------" + code);
RestTemplate restTemplate = new RestTemplate();
// According OAuth documentation we need to send the client id and secret key in the header for authentication
String encodedCredentials = new String(Base64.encodeBase64(credentials.getBytes()));
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.add("Authorization", "Basic " + encodedCredentials);
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("scope","scope,value");
body.add("grant_type","scope,value");
HttpEntity<String> request = new HttpEntity<String>(body, headers);
String access_token_url = "http://localhost:8080/oauth2/token";
ResponseEntity<TokenModel> response = restTemplate.exchange(access_token_url, HttpMethod.POST, request, TokenModel.class);
String accessToken = response.getBody().access_token;
return accessToken;
}
}
class TokenModel{
String access_token;
String scope;
String token_type;
String expires_in;
}
I am new to Spring security. Please help even if this seems simple to you
NB: This question does not have an exact duplicate
I a trying to mock restetmplate but don't why I am getting the below error. I am using doreturn to verify the invocation of the resttemplate.Is there by other way to mock the rest template and mock the HTTP request
class ToTest{
public ResponseEntity<String> getValue(){
if (StringUtils.isNotEmpty(token)) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
headers.setContentType(MediaType.APPLICATION_JSON);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(etsServiceResourceDetails.getAccessTokenUri())
.queryParam("test","tsetValue");
builder.queryParam("some","someValue");
HttpEntity<?> entity = new HttpEntity<>(headers);
try {
response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, String.class);
}
catch (RestClientResponseException ex ) {
log.error(ex);
if ( ex.getRawStatusCode() == HttpStatus.NOT_FOUND.value()) {
return ResponseEntity.notFound().build();
}
}
}
}
}
Unit Test for the rest Temaplate
#Test
public void testExchange() {
String token="abbjabxkcbkscksckbckbkcbksckckkcb";
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("query", "star");
queryParams.add("test", "star2");
UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("localhost:8080/some/add").path("/").queryParams(queryParams).buildAndExpand();
RestTemplate r = new RestTemplate();
RestTemplate r1 = spy(r);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> entity = new HttpEntity<>(headers);
// ResponseEntity responserm=
//r1.exchange(uriComponents.toUriString(),HttpMethod.GET,entity,String.class); //I am getting error org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8080
doReturn(new ResponseEntity("", HttpStatus.OK)).when(r1).exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class));
verify(r1, times(1)).exchange(eq(uriComponents.toUriString()), any(), any(), eq(String.class));
assertEquals("check", "http://localhost:8080/some/add/?query=s1&test=s2", uriComponents.toUriString());
}
Errors
-> at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:581)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
i'm using Spring Boot for making Rest Controllers.
my controller is :
#RestController
public class VersionRestController {
#Autowired
VersionService versionService;
#GetMapping(value = "/csv", produces = "text/csv")
#ResponseStatus(value = HttpStatus.OK)
public void exportCsv(HttpServletResponse response) throws Exception {
String fileName = "allVersions.csv";
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
StatefulBeanToCsv<Version> writer = new StatefulBeanToCsvBuilder<Version>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withOrderedResults(true).build();
writer.write(versionService.findAll());
}
}
im calling it like this
public void exportVersionAsCsv(){
final String uri = "http://localhost:8070/csv";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Version> response = restTemplate.getForEntity(uri, Version.class);
}
when i call the rest method direct in the browser it works fine, but when i call exportVersionAsCsv() in vaadin on click button it gives me org.springframework.web.client.HttpClientErrorException$NotAcceptable: 406 Not Acceptable
why is this happening ? any suggestion ?
thank you
Try this set setAccept to Media type to that is being produced by url you are consuming.
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
I'm trying to consume a rest service with authorization using the below code. I'm getting Status Code 200 with 404 result. The same params execute correctly via Postman. Can you please advise what to fix?
#Test
public void addEnterpriseTest() {
HttpHeaders headers1 = new HttpHeaders();
headers1.put("Authorization", Arrays.asList("Bearer 123"));
headers1.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String uri = PROVISIONING_END_POINT + "enterprises";
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> entity = new HttpEntity<>("Id=8888&Name=MyEnperprise", headers);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
System.out.println(result.getStatusCode()); //getting 200
System.out.println(result); //getting 404
}