0

While using spring security custom login form, the parameters I passed from UI aren't accessible in HttpServletRequest.

class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {

    private final TokenAuthenticationService tokenAuthenticationService;
    private final CustomJDBCDaoImpl userDetailsService;

    protected StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
            CustomJDBCDaoImpl userDetailsService, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(urlMapping));
        this.userDetailsService = userDetailsService;
        this.tokenAuthenticationService = tokenAuthenticationService;
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

                final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(
                request.getAttribute("email").toString(), request.getAttribute("password").toString());
        return getAuthenticationManager().authenticate(loginToken);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain, Authentication authentication) throws IOException, ServletException {

        final UserDetails authenticatedUser = userDetailsService.loadUserByUsername(authentication.getName());
        final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser);

        tokenAuthenticationService.addAuthentication(response, userAuthentication);
        SecurityContextHolder.getContext().setAuthentication(userAuthentication);
    }
}

In AttemptAuthentication method request is not taking attributes I passed from the POST request using following code:

 var request = $http.post('/verifyUser', 
       {email: 'user', password: 'user',_csrf: $cookies['XSRF-TOKEN']})

I tried to track it using debugger console and found the payload populate with the elements I forwarded.

{"email":"user","password":"user","_csrf":"f1d88246-28a0-4e64-a988-def4cafa5004"}

My security configuration is:

http
                .exceptionHandling().and()
                .anonymous().and()
                .servletApi().and()
                .headers().cacheControl().and()
                .authorizeRequests()

                //allow anonymous resource requests
                .antMatchers("/").permitAll()               
                //allow anonymous POSTs to login
                .antMatchers(HttpMethod.POST, "/verifyUser").permitAll()
                .and()
                  .formLogin().loginPage("/signin")
                .permitAll()
                .and()

                .addFilterBefore(new StatelessLoginFilter("/verifyUser", new TokenAuthenticationService("456abc"), new CustomJDBCDaoImpl() , authenticationManager()), UsernamePasswordAuthenticationFilter.class)


                .addFilterBefore(new StatelessAuthenticationFilter(new TokenAuthenticationService("456abc")), UsernamePasswordAuthenticationFilter.class).httpBasic()
                         .and().csrf().disable().addFilterBefore(new CSRFFilter(), CsrfFilter.class);

EDIT # 1

I have also tried to use getParameter("email") instead of getAttribute("email") but, whole parameters map was empty at this point as well.

EDIT # 2: Adding request content

Remote Address:127.0.0.1:80
Request URL:http://localhost/api/verifyUser/
Request Method:POST
Status Code:502 Bad Gateway
Response Headers
view source
Connection:keep-alive
Content-Length:583
Content-Type:text/html
Date:Sun, 11 Oct 2015 17:23:24 GMT
Server:nginx/1.6.2 (Ubuntu)
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:81
Content-Type:application/x-www-form-urlencoded
Cookie:XSRF-TOKEN=f1d88246-28a0-4e64-a988-def4cafa5004
Host:localhost
Origin:http://localhost
Referer:http://localhost/ui/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
X-XSRF-TOKEN:f1d88246-28a0-4e64-a988-def4cafa5004
Form Data
view source
view URL encoded
{"email":"user","password":"user"}:
Wasif Kirmani
  • 1,277
  • 3
  • 22
  • 43

1 Answers1

0

The email and password data that you want are parameters, not attributes. Attributes in the ServletRequest are server-side only data that you can use in your application to pass data around between classes or to JSPs.

Note: You have to use the content type application/x-www-form-urlencoded and make sure that the request body is encoded in the correct format to use getParameter on the server side, e.g. email=user&password=user.

By default Angular will encode an object as JSON

Transforming Requests and Responses

Angular provides the following default transformations:

Request transformations ($httpProvider.defaults.transformRequest and $http.defaults.transformRequest):

If the data property of the request configuration object contains an object, serialize it into JSON format.

Also see How do I POST urlencoded form data with $http in AngularJS?

Difference between getAttribute() and getParameter()

Community
  • 1
  • 1
adashrod
  • 456
  • 2
  • 12
  • Hmm, what's the content type of the request? If it's not a "form" type like `application/x-www-form-urlencoded`, then you'll need to read the request body and parse it. See https://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getReader-- or https://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getInputStream-- – adashrod Oct 11 '15 at 16:29
  • I have set the form type explicitly before POST. And when I checked the request.getHeader("content-type") then it was returning me application/x-www-form-urlencoded. Or do I still need to parse the request inputstream? – Wasif Kirmani Oct 11 '15 at 16:51
  • You shouldn't have to. I haven't used `AbstractAuthenticationProcessingFilter`, but I know that `getParameter` works in this scenario in filters and endpoints. Can you post the content of the request body as the server sees it? Maybe angular is doing something weird and the server isn't getting the data in the correct format. – adashrod Oct 11 '15 at 17:21
  • Ah, I think I see the problem. Even though your request content type is `application/x-www-form-urlencoded`, your request body is actually in JSON format (the last line). The format should be `email=user&password=user`, similar to query strings. I'll edit my answer. – adashrod Oct 11 '15 at 17:44