Spring Security OAuth2 MultipartRequest with android - java

I am using:
Spring 4.1.1.RELEASE
Spring Security 3.2.5.RELEASE
spring-security-oauth2 1.0.0.RELEASE
I have created a two multipart request:
One is at Non-secure controller Second at a Secure controller.
Both are same, there is no change.
Non secured request works very fine but secured Multipart request not working
#RequestMapping(value="/profileimage", method=RequestMethod.POST)
public #ResponseBody String createProfilePicture(#RequestParam MultipartFile
file, #RequestParam String profileId){
}
Please reply if you require more information.

Please specify what exactly you are trying to achieve by implementing an oauth2 authorization server.
Do you plan to support various authentication providers e.g Facebook, Linkedin, Google?
Please specify the error message you get when trying to consume the API.
Please share your Security configuration classes i.e the class that extends WebSecurityConfigurerAdapter and any other configuration that you have.
You can review this article which details how to implement an oauth2 authorization server to make sure you haven't missed any part.
In regards to the code above, it seems corrent but can be simplified:
#PostMapping("/profileimage")
public #ResponseBody String createProfilePicture(#RequestParam MultipartFile
file, #RequestParam String profileId){
}
You can even drop the #ResponseBody annotation in case a #RestController
annotation is specified on the class.
Good luck!

Related

Spring Security SAML: Extract Attributes from a saml2p:Response as user attributes

I have been digging into spring security yaml a little bit yesterday to make it work with Okta SAML. Logging in works, but the response XML contains user attributes that apparently cannot be extracted automatically into an attribute map. The response contains a fields like this
<saml2:Attribute Name="user.lastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
Surname
</saml2:AttributeValue>
</saml2:Attribute>
Once an authentication is successful, I would like to put those in the authentication information. When logging in via github/oauth, the OAuth2AuthenticatedPrincipal class has an attributes map, however the Saml2AuthenticatedPrincipal only features a name.
What would be the correct way to solve this?
Right now I am thinking of a custom AuthenticationSuccessHandler that populates a custom Saml2AuthenticatedPrincipalWithAttributes class which contains all the attributes by parsing the provided XML response (via .getDetails()) a second time (or put them into the session).
I have a hunch that this is probably not the spring way to do things and would love to get a second opinion. When googling around you mainly find examples of spring security saml, before it got merged into spring security, which seems to handle things a little bit different, as the mentioned classes do not exist anymore.
Thanks for helping everyone!
In the next release of Spring Security (5.4.0) you should be able to do something like this:
#GetMapping("/")
public String index(Model model,
#AuthenticationPrincipal Saml2AuthenticatedPrincipal principal) {
String emailAddress = principal.getFirstAttribute("emailAddress");
model.addAttribute("emailAddress", emailAddress);
model.addAttribute("userAttributes", principal.getAttributes());
return "index";
}
For now, I don't know a better workaround than yours.

How to add logging to a webflux endpoint in spring-mvc?

I have an existing spring-mvc application with different #RestController. Now I want to add a Mono<String> endpoint, and log the request timestamp with url path, as well as the response timestamp.
But how? I cannot simply #EnableWebFlux as I would have to disable spring-mvc therefor.
How could I register a filter explicit for the webflux endpoint that catches on invocation, and right before the response is written back async?
#RestController
public class FluxService {
#PostMapping
public Mono<String> post() {
return webClient.post().uri(uri).bodyValue(payload).retrieve().bodyToMono(String.class);
}
}
I want enhanced logging on the #PostMapping endpoint, not on the webClient!
MVC is a blocking/servlet based api, mixing it with webflux isn't going to work. They use different filters, security etc as MVC assumes a lot of ThreadLocal stuff. (Can I use SpringMvc and webflux together?)
If you really want to mix them like this you could use .doOnNext() once you get your mono and call your logger there.

How to prevent xss from java api side

I have REST API with Java Springboot 2.1.5.RELEASE and need to prevent every controller to check first the RequestBody contain XSS or not. if yes I want to return like BadRequest. The App only for API no HTML, JSP and etc
Here is sample my controller
#PostMapping("/test1")
public ResponseEntity<ResponseModel> process(#Valid #RequestBody Student request)
I've tried with some library to check Student to Json and clean the XSS like https://github.com/OWASP/json-sanitizer/ and etc
but still, doesn't work
and Already check https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
but still not found about implement in java api
I expect every request to API reject/return 400(BadRequest)
The validation can be on Controller, Filter, Interceptor or Spring Security

Angular 2 - no access control allow origin header [duplicate]

This question already has answers here:
How to create cross-domain request?
(7 answers)
Closed 5 years ago.
My project uses spring at the back-end and angular2 at the front-end. I have a json file under webapp folder of spring project. And I am trying to access it from angular.
I am able to access the file if I just type "http://localhost:8080/project1/test.json"
But if I use the same link from angular, I am getting an error message saying "no access control allow origin header"
My angular code :
1. Function getJson() defined in service.ts:
getJson(){
return this.http.get('http://localhost:8080/project1/test.json')
.map((response:Response) => response.json());
}
Calling getJson():
results=[];
this._manoService.getJson().subscribe(resJsonData => this.results =
resJsonData);
I created proxy.conf.json and added the following lines:
{
"/project1": {
"target": "http://localhost:8080",
"secure": false
}
}
And also added "start": "ng serve --proxy-config proxy.conf.json", to package.json
Still I am getting the same issue. Am I doing anything wrong?
For security reasons, browsers enforce a same origin policy. Your angular page is on an origin other than localhost:8080 (most likely localhost:3000). So the browser is disallowing access.
The SOP is a very important concept of the web. For example you may be logged in to your bank account and then open another website. The SOP prevents that website from accessing your bank account.
There are several ways to grant cross origin access.
By far the easiest way, is to put everything onto the same origin. That is provide the Angular application on the same domain and port as the service for production. For development, you can configure ng serve to act as a proxy server. Thus you will make your service request to http://localhost:3000/project1/test.json and let ng service forward it to localhost:8080. This is explained in detail in Angular proxy documentation.
If you need cross origin request even in production, Spring makes it relatively easy to allow that: You need toannotate your service methods with #CrossOrigin as explained in the Spring REST tutorial. In this case authentication via cookie will not work any longer. In case you need authentication, you should look into oauth. Adding the #CrossOrigin annotication to your service method, will make Spring-REST add the Access-Control-Allow-Origin http-header.
Another alternative to using proper CORS is to use jsonp, but this is a hack that should be avoided nowadays. JSONP exploits use of the fact, that you can include a <script> tag to any origin and the provided javascript is downloaded and execute. So the idea behind JSONP is that you define a callback function and the server will generate and return JavaScript code that invokes this function with the actual data as parameter.
Let's say that the service is implemented by a Spring #RestController and you need to consume it throught a web site that is outside of the server where the rest service is running. In that scenario just add a #CrossOrigin annotation to the handler method.
For example (in this example the #CrossOrigin is enable only to the addSite handler method.
#RestController
public class SiteController {
#Autowired
private SiteServiceImpl siteService;
#CrossOrigin(origins = "*")
#RequestMapping(method = RequestMethod.POST, value = "/api/sites")
public void addSite(#RequestBody Site site){
siteService.addSite(site);
}
But also you can enable #CrossOrigin to the whole controller enabling the #CrossOrigin at the #RestController level.
For example:
#RestController
#CrossOrigin(origins = "*")
public class SiteController {
#Autowired
private SiteServiceImpl siteService;
#RequestMapping(method = RequestMethod.POST, value = "/api/sites")
public void addSite(#RequestBody Site site){
siteService.addSite(site);
}
#CrossOrigin(origins = "*") annotation allows to all the resources that are outside of the rest service to consume it, in the case that the service is only enabled to be consumed for resources that comes from one specific origin then just change the origins value to the server name where the resources resides, for example #CrossOrigin(origins = "http://myothersite.com")
There is more related information at the Spring site: cors-support-in-spring-framework

Java Spring Restcontroller Post

I need help creating a POST request to my Java Spring Restcontroller.
This is my controller -
#RestController
#RequestMapping("hedgesimulator/")
public class HedgeSimulatorController {
#RequestMapping(value = "hedgesim/", method = RequestMethod.POST)
#ResponseBody
public HedgeSimulatorLog putHedgeSimulation(
#RequestBody HedgeSimulatorLog hedgeSimulatorLog) {
System.out.println(hedgeSimulatorLog.toJsonString());
return hedgeSimulatorLog;
}
}
I am using Chrome's "Advanced Rest Client" Plugin to POST my request to my URL (I am sure my localhost is running properly, etc.)
What do I need to add to my header?
I receive an error for "HTTP 400 - Status report: The request sent by the client was syntactically incorrect"
Please help!
To pass an object to controller you must configure HttpMessageConverter which helds serialization and deserealization of this object. For example, if you want to pass an object to controller as JSON, set a MappingJackson2HttpMessageConverter as parameter in your mvc declaration in spring config file.
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
If http message converter configured properly, maybe request was improperly formed.
#RequestMapping(value = "/hedgesim/", method = RequestMethod.POST)
Try with following, hope you might resolve the issue:
Since you are using #RestController annotation, so no need to use #ResponseBody annotation again, which is redundant.
If you are using spring boot, then make sure you have added the below dependency .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
If the project is not spring boot, then add dependency for jackson : com.fasterxml.jackson.databind.ObjectMapper
Just to make sure the request body is correct, what you can do is, execute request method first, get the JSON response, pass the same JSON for POST, so this might avoid some typo/human error while creating JSON data.
Hope, it helps.
You can do the following checks.
Validate the request body you are sending through some online tool like
JSonLint.
Check whether MappingJackson2HttpMessageConverter is registered or not. By default, Spring registers this converter if you have the jar in the classpath.
No need to use #ResponseBody if you are using #RestController. So remove it.
For a complete example on creating and consuming REST Service using Spring 4.0, you can visit Techno Spots.

Categories