Cross origin request -401 with POSTMAN - spring

Currently am working on Spring boot back end API services.This API expecting two values one for path variables and others for request body.Using POSTMAN application for making request.
When i click into the send button it will show like this
{
"timestamp": "2020-07-31T05:57:15.178+0000",
"status": 401,
"error": "Unauthorized",
"message": "No message available",
"path": "/Service/api/ea/saveConfig/$%7Bhost%7D"
}
Controller class
I have added cross origin annotation like blow
Edit1
#CrossOrigin(origins = "http://localhost:8000")
#RestController
#RequestMapping("/api/ea")
public class ServiceConfigController
{
#PostMapping(value = "/saveConfig/{host}", produces = "application/json")
public ResponseEntity<JsonNode> saveConfig(#PathVariable String host,
#RequestBody JsonNode data) throws JsonProcessingException
{
try
{
ResponseEntity<JsonNode> result = configService.saveConfiguration(host, data);
return result;
}
catch (Exception e)
{
return new ResponseEntity<>(data, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
If we are making request from POSTMAN what will be the cross origin.I tried few things but not helpful.
Please suggest a valid solution.

The POSTMAN path variable should be {{host}} instead of ${host}. Please share your pom xml. Best guess is that you may use spring security to secure you API.
Please remove the dependency from your pom and retry again.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If spring security is a must, you may try to add Auth to your POSTMAN and retry. Username is user and password is generated and printed in your console.
For example,
2020-07-31 15:19:01.727 INFO 3296 --- [ main] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: ae4b7465-ab44-416d-96e3-8d122f755e04
2020-07-31 15:19:01.811 INFO 3296 --- [ main]

Related

How to display validation error messages and codes in a Spring WebFlux Rest API

I'm using Spring Web MVC in a Reactive SpringBoot Application, and wrote a custom validator. In case of a validation error, a 400 response code is used, which is fine, but then AbstractErrorWebExceptionHandler catches this and spits out
{
"timestamp": 1651678946524,
"path": "/signup",
"status": 400,
"error": "Bad Request",
"requestId": "0f61cb96-1"
}
which is not very useful to the client. How can I display the error messages and codes? I know they are available, because they are logged:
DEBUG 32475 --- [ parallel-1] a.w.r.e.AbstractErrorWebExceptionHandler : [0f61cb96-1] Resolved [WebExchangeBindException: Validation failed for argument at index 0 in method: public reactor.core.publisher.Mono<...with 1 error(s): [Field error in object 'userSignup' on field 'username': rejected value [matilda0]; codes [username.exists.userSignup.username,username.exists.username,username.exists.java.lang.String,username.exists]; arguments []; default message [null]] ] for HTTP POST /signup
Any help would be appreciated, thank you.
This is what I did:
private void validate(SomeEntity someEntity) {
Errors errors = new BeanPropertyBindingResult(someEntity, "SomeEntity");
validator.validate(someEntity, errors);
if (errors.hasErrors()) {
throw new ServerWebInputException(errors.toString());
}
}
Validator is injected:
private final Validator validator;
private final SomeEntityDao dao;
public SomeEntityHandler(
Validator validator,
SomeEntityDao dao
) {
this.validator = validator;
this.dao = dao;
}
Project: WebFluxR2dbc
Adding
server.error.include-binding-errors=ALWAYS
in application.properties seems to fix it, although it still doesn't look up the message code properly. To actually get the error message itself to appear in the response, I had to wire in a MessageSourceAccessor in my Validator and use that as the default message!
errors.rejectValue("username","username.exists",msgs.getMessage("username.exists"))
So I must still be missing something, but this will work for now.

How do I make Spring Security return a 500 instead of a 403 when a InternalAuthenticationServiceException is thrown

I am using Spring Security to handle auth on my RESTful-ish webservice.
The goal is to create a /login endpoint for which the user provides a username/password and which returns a JWT. I'm loosely following this guide: https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
I've got the happy-path working; when a user provides a valid user/pass, a valid JWT is returned to them.
The problem is my error case. If my UserService.loadUserByUsername method (which is called by Spring Security in order to validate the user/pass) throws an IOException, I want Spring to return a 500 error. Instead, Spring returns a 403. I stepped through the internal Spring classes a bit, and they clearly differentiate between a AuthenticationException (which is thrown when auth fails) and a InternalAuthenticationServiceException (which is thrown when auth is unable to be completed due to an internal error). I want a 500 error returned when an InternalAuthenticationServiceException is encountered. How to I configure Spring to do this? Will I need to implement my own AuthenticationFailureHandler?
As Thomas Andolf said, it might have been best for me to simply implement an OAuth2 flow instead of a custom authentication solution. However, if you want to implement a custom authentication solution, and if you want to return specific HTTP error codes for specific errors, then you can write a custom AuthenticationFailureHandler to accomplish this. I'm not sure if this is a good solution, but it is a solution. Something like this:
class CustomAuthenticationFilter(authManager: AuthenticationManager) : AbstractAuthenticationProcessingFilter(AntPathRequestMatcher("/login", "POST")) {
init{
this.authenticationManager = authManager;
this.setAuthenticationSuccessHandler(CustomAuthenticationSuccessHandler())
this.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler())
}
#Throws(AuthenticationException::class, PreAuthenticatedCredentialsNotFoundException::class)
override fun attemptAuthentication(req: HttpServletRequest, res: HttpServletResponse): Authentication {
// insert code to parse the request into a username and password
return authenticationManager.authenticate(
UsernamePasswordAuthenticationToken(
username,
password,
ArrayList())
)
}
}
class CustomAuthenticationSuccessHandler: AuthenticationSuccessHandler{
override fun onAuthenticationSuccess(request: HttpServletRequest?, response: HttpServletResponse?, authentication: Authentication?) {
// these next three lines simply verify that none of the inputs are null; this is Kotlin syntax.
request!!
response!!
authentication!!
val username = (authentication.principal as User).getUsername();
val expiration = Date(System.currentTimeMillis() + EXPIRATION_DURATION_MILLIS)
// insert code to create a JWT and write it to the response
// no need to return anything
}
}
class CustomAuthenticationFailureHandler : AuthenticationFailureHandler{
override fun onAuthenticationFailure(request: HttpServletRequest?, response: HttpServletResponse?, exception: AuthenticationException?) {
// these next two lines simply verify that none of the inputs are null; this is Kotlin syntax.
request!!
response!!
when (exception) {
is PreAuthenticatedCredentialsNotFoundException -> {
response.status = 400;
}
is AuthenticationServiceException -> {
response.status = 500;
}
else -> {
response.status = 401;
// consider adding a WWW-Authenticate header as well
}
}
}
}

How to handle Bad Request to return custom Response object for PostRequest in Spring Boot Rest Api

I am Trying to create Api which can accept POST Request.
But I want to handle Bad Request Also.
My Json object will be like
JSON Object
{
"name": "tom"
"description" : "he is scholar"
}
JSON object with incorrect parameter
{
"name": "tom"
"descr" : "he is scholar"
}
#PostMapping("/questions")
public question addQuestion(#RequestBody question theQuestion) {
theQuestion.setId(0);
try {
thequestionService.save(theQuestion);
}catch(Exception ex) {
throw new badRequestException("bad request");
}
return theQuestion;
}
For Bad Request it is throwing spring Boot internel error.
But I want to send custom JSON object to back to client.
Response in case of failure 400 Bad Request.
{
"status":"failed to query"
"description" : " can be any thing"
}
Help me out for this issue.
You can use #JsonAlias annotation.
public class Question {
#JsonAlias(value={"description", "descr"})
private String description;
}
This annotation was added in Jackson 2.9. You might have to upgrade/override Jackson version.
For Bad Request it is throwing spring Boot internel error.
You can also add #JsonIgnoreProperties(ignoreUnknown = true) annotation to Question class. Doing this will not throw error for descr key in JSON, but will initialize description field in Question object as null.

Request body is empty when no authentication is present for secure APIs

I am trying to log the request body on all requests in a spring boot reactive application secured with spring security. But I am running into an issue where the request body is logged only if the basic auth header is present (even if the username and password are invalid). But if no auth header is present the request body does not get logged. I am unsure what I am missing and would like to find out how I maybe able to get access to the request body for cases where there is no authentication header present.
The request body logging is done using an authentication entry point set on HttpBasicSpec. The security configuration looks as follows:
#Configuration
#EnableWebFluxSecurity
class SecurityConfiguration {
private val logger = LoggerFactory.getLogger(this::class.java)
#Bean
fun securityConfigurationBean(http: ServerHttpSecurity) =
http.csrf().disable()
.cors().disable()
.httpBasic()
.authenticationEntryPoint { exchange, _ ->
exchange.request.body
.subscribe { logger.info(CharsetUtil.UTF_8.decode(it.asByteBuffer()).toString()) }
.let { Mono.error(HttpServerErrorException(HttpStatus.UNAUTHORIZED)) }
}.and().authorizeExchange().anyExchange().authenticated().and().build()
}
There is a test router config that has a one route:
#Configuration
class TestRouterConfig {
#Bean
fun testRoutes() =
router {
POST("/test") {
ServerResponse.ok().bodyValue("This is a test route")
}
}
}
When I make a request to http:localhost:8080/test with a request body of
{"sample": "sample"}
with an invalid username and password in the basic auth header, I see the following in the console:
2019-12-06 11:51:18.175 INFO 11406 --- [ctor-http-nio-2] uration$$EnhancerBySpringCGLIB$$5b5f0067 : {"sample": "sample"}
But when I remove authentication all together I don't see the above logging statement for the same endpoint (I am using a rest client to make these calls).
The versions of tools/frameworks/languages:
Kotlin: 1.3.50
Spring boot: 2.2.1
Java: 12
Gradle: 5.6.4
Spring dependency management: 1.0.8.RELEASE
I would like to be able to log the request body for all requests that result in an authentication failure including the absence of an authentication header and would appreciate any help in this regard. My apologies if this has been discussed/posted elsewhere.
Thank you!

Using Jersey in Spring Boot for file upload getting 400 Bad Request [duplicate]

This question already has answers here:
Spring Boot + Jersey type filter - Bad request 400 for service Consumes MULTIPART_FORM_DATA
(2 answers)
Closed 4 years ago.
I have tried a large number of examples for doing file upload with jersey. I can get it to work with pure Spring using #RequestMapping, ResponseEntity instead of #Path etc. But I want to use jersey, as all of my other endpoints are handled by jersey.
UPDATE: I feel that I'm unable to pass an form data, file or text. Even a single FormDataParam of #FormDataParam("directory") String directory gives the bad request
I have the following class
#Component
#Path("/v1.0")
public class FileOperationsResource {
private ConfigurationReader mConfigReader;
#Autowired
public FileOperationsResource(ConfigurationReader configurationReader) {
mConfigReader = configurationReader;
}
#POST
#Path("/file/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(#QueryParam("dir") String directory,
#FormDataParam("file") InputStream file,
#FormDataParam("file") FormDataContentDisposition fileDisposition) {
I have added the following line to my ResourceConfig
register(MultiPartFeature.class);
I have added the following maven dependency, but have not added a version as my understanding is that it will automatically pull the version that works with my version of spring, and I have found newer versions no longer allow me to add register in ResourceConfig as MultiPartFeature is missing.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
When I make the following call, I get a 400 Bad Request. I feel like I must be making the call wrong, or have failed to wire something else in. Any help would be appreciated.
Response:
{
"timestamp": "2018-04-20T15:51:01.790+0000",
"status": 400,
"error": "Bad Request",
"message": "Bad Request",
"path": "/api/v1.0/file/upload"
}
I've made the call with Postman and using forms, as well as curl with the following call
curl --verbose --form file=#"settings.xml" http://localhost:8080/api/v1.0/file/upload?dir=MyDir
What is your spring.jersey.type set to in application.properties? I have file upload working with Jersey and Boot, I believe this is what you need:
# JERSEY
spring.jersey.type=servlet
spring.jersey.servlet.load-on-startup=1
For example purposes, here's my endpoint:
#POST
#Path("/file/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(#FormDataParam("file") InputStream fileInputStream,
#FormDataParam("file") FormDataContentDisposition fileDisposition) {
String fileName = fileDisposition.getFileName();
StringBuilder fileContents = new StringBuilder();
int read = 0;
int totalBytesRead = 0;
byte[] bytes = new byte[1024];
try {
while ((read = fileInputStream.read(bytes)) != -1) {
...save file...
}
} catch (IOException e) {
mLogger.error(e.getMessage(), e);
}
return Response.ok().build();
}

Resources