API Authentication in Spring Boot - spring

I am building a Spring Boot service that is supposed to call to an external API, and then send the fetched data to the client-side. To send any requests, I must first authenticate by sending a POST request with specific data in the request body, which then sends back a response with authentication key as a cookie. I've made it work in Postman but don't know how to do this in Spring Boot.

I would recommend to have something similar to this:
The main ideea is to use a rest template.
RestTemplate restTemplate = new RestTemplate();
HttpEntity entity = new HttpEntity<String>(headers);
try {
String result = restTemplate.postForEntity(externalAPIUrl, entity, String.class).getBody();
} catch (HttpClientErrorException ex) {
if (ex.getStatusCode() == HttpStatus.BAD_REQUEST) {
}
}

Related

REST API call from spring boot not working

I am trying to fetch live data from NSE options trading. Below code is not working and the request made is stuck without any response.
Any workaround on this?
public void getLiveBankNiftyData() {
String RESOURCE_PATH = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(RESOURCE_PATH, Object[].class);
Object[] objects = responseEntity.getBody();
}
i tried this
// request url
String url = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
// create an instance of RestTemplate
RestTemplate restTemplate = new RestTemplate();
// make an HTTP GET request
String json = restTemplate.getForObject(url, String.class);
// print json
System.out.println(json);
I found a way out. Instead of using RestTemplate I used WebClient and this solved the issue.

Asp.net web api IHttpActionResult springboot Java Equivalent

hi I am new in springboot and I want to develop rest api in springboot.
In .net web api IHttpActionresult type used to return entity and httpstatuscode in same time,is there any equivalent in spring boot
Use Spring's Class ResponseEntity<T>. It allows you to add an Object and a Response Status and send to the user.
Example from ResponseEntity docs:
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setLocation(location);
responseHeaders.set("MyResponseHeader", "MyValue");
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
You see how ResponseEntity accepts the body of the response as its first argument, the headers of the response as the second and the HTTP status as the third.

File upload, communication between two spring boot application

I have two spring boot application, one is 'AngularApp' (localhost:8870) supporting my front and the other one is 'batchApp'(localhost:8871) running some batches.
I would like to upload a file from my 'Front' to 'AngularApp', then to 'batchApp' as illustrated below.
Right now I did the upload from 'Front' to 'AngularApp', basically using REST API with one controller and service in 'AngularApp'.
#PostMapping("/post")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file)
It works well and upload the file into a specific folder 'upload-dir'.
Now I want 'AngularApp' and 'batchApp' to communicate so 'AngularApp' can give him the file uploaded, but I have no idea about how to do it. REST API ? Any ideas?
For the better approach to solve this problem using spring-framework libraries, please refer
https://piotrminkowski.wordpress.com/2017/02/05/part-1-creating-microservice-using-spring-cloud-eureka-and-zuul/
Below spring framework components make it easy.
Zuul – gateway service that provides dynamic routing, monitoring, resiliency, security, and more
Ribbon – client side load balancer
Feign – declarative REST client
Eureka – service registration and discovery
Sleuth – distributed tracing via logs
Zipkin – distributed tracing system with request visualization.
Here you'll find my working solution, with pvpkiran advice and following this method multipart upload with HttpClient4 :
In AngularApp, http post request :
public void batchAppUploadFile(String fileName) {
log.i("Creating HTTP POST Request to upload a file on batchApp server");
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(myFile_URL);
File file = new File(Paths.get("upload-dir").resolve(fileName).toString());
FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", fileBody);
HttpEntity entity = builder.build();
post.setEntity(entity);
log.i("Executing HTTP Request...");
try {
HttpResponse response = client.execute(post);
log.i("The request went well !");
ResponseEntity.status(HttpStatus.OK).body("SUCESS BS upload");
} catch (Exception e) {
log.i("The request failed !");
ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("FAIL BS upload");
}
}
My controller in batchApp :
#PostMapping("/uploadfile")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file) {
try {
Path uploadPath = Paths.get(getUploadDirectory(file));
Files.copy(file.getInputStream(), uploadPath.resolve(file.getOriginalFilename()));
log.i(file.getOriginalFilename() + " upload complete !");
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
return ResponseEntity.status(HttpStatus.OK).body("Uploaded on batchApp");
}

Get value from response body in RestClient

I am using Rest client of Firefox. I want to get value from response that is showing on Response body(Raw) in Rest-Client. I want to get this value in SpringBoot. Is it possible? If yes then How?
I have tried too many times but didn't get Satisfactory solution.
Using a Spring RestTemplate to make the calls will return a ResponseEntity. The simplest way to get the raw response would be this:
RestTemplate restTemplate = new RestTemplate();
try{
ResponseEntity<String> response = restTemplate.getForEntity(URI.create("http://example.org"),String.class);
System.out.println(response.getBody());
} catch (RestClientResponseException exception){
System.out.println(String.format("Error code %d : %s",e.getStatusCode().value(),e.getResponseBodyAsString()));
HttpHeaders errorHeaders = e.getResponseHeaders();
}
The ResponseEntity class will allow you to access the headers as well.
For more information on RestTemplate you can look at the docs here.

Setting OAuth2 token for RestTemplate in an app that uses both #ResourceServer and #EnableOauth2Sso

On my current project I have an app that has a small graphical piece that users authenticate using SSO, and a portion that is purely API where users authenticate using an Authorization header.
For example:
/ping-other-service is accessed using SSO.
/api/ping-other-service is accessed using a bearer token
Being all cloud native our app communicates with other services that uses the same SSO provider using JWT tokens (UAA), so I figured we'd use OAuth2RestTemplate since according to the documentation it can magically insert the authentication credentials. It does do that for all endpoints that are authenticated using SSO. But when we use an endpoint that is authed through bearer token it doesn't populate the rest template.
My understanding from the documentation is that #EnableOAuth2Client will only extract the token from a SSO login, not auth header?
What I'm seeing
Failed request and what it does:
curl -H "Authorization: Bearer <token>" http://localhost/api/ping-other-service
Internally uses restTemplate to call http://some-other-service/ping which responds 401
Successful request and what it does:
Chrome http://localhost/ping-other-service
Internally uses restTemplate to call http://some-other-service/ping which responds 200
How we worked around it
To work around this I ended up creating the following monstrosity which will extract the token from the OAuth2ClientContext if it isn't available from an authorization header.
#PostMapping(path = "/ping-other-service")
public ResponseEntity ping(#PathVariable String caseId, HttpServletRequest request, RestTemplate restTemplate) {
try {
restTemplate.postForEntity(adapterUrl + "/webhook/ping", getRequest(request), Map.class);
} catch (HttpClientErrorException e) {
e.printStackTrace();
return new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);
}
return new ResponseEntity(HttpStatus.OK);
}
private HttpEntity<?> getRequest(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + getRequestToken(request));
return new HttpEntity<>(null, headers);
}
private String getRequestToken(HttpServletRequest request) {
Authentication token = new BearerTokenExtractor().extract(request);
if (token != null) {
return (String) token.getPrincipal();
} else {
OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken();
if (accessToken != null) {
return accessToken.getValue();
}
}
throw new ResourceNotFound("No valid access token found");
}
In the /api/** resources there is an incoming token, but because you are using JWT the resource server can authenticate without calling out to the auth server, so there is no OAuth2RestTemplate just sitting around waiting for you to re-use the context in the token relay (if you were using UserInfoTokenServices there would be one). You can create one though quite easily, and pull the incoming token out of the SecurityContext. Example:
#Autowired
private OAuth2ProtectedResourceDetails resource;
private OAuth2RestTemplate tokenRelayTemplate(Principal principal) {
OAuth2Authentication authentication = (OAuth2Authentication) principal;
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
details.getTokenValue();
OAuth2ClientContext context = new DefaultOAuth2ClientContext(new DefaultOAuth2AccessToken(details.getTokenValue()));
return new OAuth2RestTemplate(resource, context);
}
You could probably turn that method into #Bean (in #Scope("request")) and inject the template with a #Qualifier if you wanted.
There's some autoconfiguration and a utility class to help with this pattern in Spring Cloud Security, e.g: https://github.com/spring-cloud/spring-cloud-security/blob/master/spring-cloud-security/src/main/java/org/springframework/cloud/security/oauth2/client/AccessTokenContextRelay.java
I came across this problem when developing a Spring resource server, and I needed to pass the OAuth2 token from a request to the restTemplate for a call to a downstream resource server. Both resource servers use the same auth server, and I found Dave's link helpful but I had to dig a bit to find out how to implement this. I ended up finding the documentation here, and it turn's out the implemetation was very simple. I was using #EnableOAuth2Client, so I had to create the restTemplate bean with the injected OAuth2ClientContext and create the appropriate resource details. In my case it was ClientCredentialsResourceDetails. Thanks for all great work Dave!
#Bean
public OAuth2RestOperations restTemplate (OAuth2ClientContext context) {
ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
// Configure the details here
return new OAuth2RestTemplate(details, context)
}
#Dave Syer
My UAA service is also an oauth2 client, which needs to relay JWT tokens coming in from Zuul. When configuring the oauth2 client the following way
#Configuration
#EnableOAuth2Client
#RibbonClient(name = "downstream")
public class OAuthClientConfiguration {
#Bean
public OAuth2RestTemplate restTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
return new OAuth2RestTemplate(resource, context);
}
}
I do get a 401 response from the downstream service as my access token has a very short validity and the AccessTokenContextRelay does not update an incoming access token (Zuul does renew expired access tokens by the refresh token).
The OAuth2RestTemplate#getAccessToken will never acquire a new access token as the isExpired on the access token stored by the AccessTokenContextRelay drops the validity and refresh token information.
How can this by solved?

Resources