Jackson MismatchedInputException: No content to map due to end-of-input

19,413

I had the same error, had to remove ApplicationUser user = new ObjectMapper().readValue(request.getInputStream(),ApplicationUser.class);

and use request.getParameter directly:

                new UsernamePasswordAuthenticationToken(
                    request.getParameter("username"),
                    request.getParameter("password"),
                    Collections.emptyList()
            )
Share:
19,413
theanilpaudel
Author by

theanilpaudel

Computer Fanatic, studying JAVA and so android

Updated on June 04, 2022

Comments

  • theanilpaudel
    theanilpaudel over 1 year

    I am trying to implement JWTAuthentication in my project. I have set up my entity like this:

    @Entity
    public class ApplicationUser {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        Long id;
        String username,password;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    Then I have setup the AuthenticationFilter like this:

        public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
            private AuthenticationManager authenticationManager;
    
            public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
                this.authenticationManager = authenticationManager;
            }
    
            @Override
            public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
                try {
                    System.out.println("request "+request.getPathInfo());
                    ApplicationUser user = new ObjectMapper().readValue(request.getInputStream(),ApplicationUser.class);
    //this is where the exception is    
                    return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword(),new ArrayList<>()));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
    
            @Override
            protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
                String token = Jwts.builder()
                        .setSubject(((ApplicationUser) authResult.getPrincipal()).getUsername())
                        .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                        .signWith(SignatureAlgorithm.HS512, SECRET.getBytes())
                        .compact();
                response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
            }
        }
    

    And this is my SecurityConfiguration as:

    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        private BCryptPasswordEncoder bCryptPasswordEncoder;
        private UserDetailsService userDetailsService;
    
        public SecurityConfig(AppUserDetailService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder){
            this.bCryptPasswordEncoder=bCryptPasswordEncoder;
            this.userDetailsService=userDetailsService;
        }
    
    
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable().authorizeRequests()
                    .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
    //                .antMatchers(HttpMethod.POST,LOGIN_URL).permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                    .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                    // this disables session creation on Spring Security
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
        }
        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
            return source;
        }
    }
    

    Sign up is working fine, but when I try to login using the same credentials I get the following exception:

    Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 0] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.9.6.jar:2.9.6] at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4145) ~[jackson-databind-2.9.6.jar:2.9.6] at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4000) ~[jackson-databind-2.9.6.jar:2.9.6] at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070) ~[jackson-databind-2.9.6.jar:2.9.6] at com.project.pq.security.JWTAuthenticationFilter.attemptAuthentication(JWTAuthenticationFilter.java:35) ~[classes/:na] ... 53 common frames omitted

    I am using Postman to hit the API and there I have set application/json as the content-type and sent the username and password as post parameters. I am following this tutorial. What am I doing wrong? Any help would be appreciated.

    Thanks

    • Andreas
      Andreas over 5 years
      Do not consume the POST content in a filter, especially not a filter that applies to all URLs. If logging in requires a POST to a specify URL with JSON content, then it should be handled by a Servlet, not a Filter. Authentication filters are for processing header values (e.g. Authentication), so authentication can happen on-the-fly, during the processing of any arbitrary request.
  • Katharina
    Katharina about 4 years
    Have you found out the reason for this behaviour? I'm having the same issue.
  • sanjeevRm
    sanjeevRm over 2 years
    replacing objectMapper line with request.getParameter("") worked like charm