0

My objective is to access spring security protected API from a react js application after authentication.

  • Spring boot application hosted at http://myserver:8080
  • React JS application is hosted at http://myserver:3000

I am able to authenticate and access the APIs using curl as follows:

  1. Access login url with credentials . Extract jsessionid token from response header.
  2. Access end url with jsessionid token.
$ curl -i -X POST login_url --data 'username=myusername&password=mypassword'
$ curl end_url -H 'Cookie: JSESSIONID=session_token'

I am trying to replicate the same through React JS Application.

  • Even though JSESSIONID Cookie is present in response header (verified through curl , and browser dev tools) but axios response header is not able to capture it.

  • I understand that "Set-Cookie" header in JavaScript code will not work by default. As discussed in this question React Axios, Can't read the Set-Cookie header on axios response

  • Kindly help with modification required in code to achieve the same. OR suggest alternate way to achieve the objective. Thanks.

Client side code is as follows:

const onSubmitAuthenticateButton = (e) => {
 e.preventDefault();
 const loginUrl = 'http://myserver:8080/login';
 axios.defaults.withCredentials = true;
 axios.post(loginUrl, { username, password})
      .then(res => console.log(res.headers))
      .catch(err => console.log(err.message));
}

In Spring Secuirty configuration, csrf is disabled and cors allowed origin for "http://myserver:3000".

WebSecurityConfig class

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    private CustomAuthenticationProvider customAuthProvider;

    public WebSecurityConfig(CustomAuthenticationProvider customAuthProvider) {
        super();
        this.customAuthProvider = customAuthProvider;
    }
        
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
            .and()
            .csrf().disable()
            .authorizeRequests()
            .anyRequest().fullyAuthenticated()
            .and()
            .formLogin();           
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(customAuthProvider);
        }
}

WebMvcConfig class

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final long MAX_AGE_SECS = 3600;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://myserver:3000")
                .allowedMethods("GET", "POST")
                .exposedHeaders("Set-Cookie")
                .maxAge(MAX_AGE_SECS)
                .allowCredentials(true);       
      }
}
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Himanshu
  • 33
  • 7

1 Answers1

0

I have achieved the objective through alternate way. Instead of session based authentication, i am now using stateless authentication. Upon successful authentication a jwt token is returned as response. Subsequent API call, the jwt token is attached as payload. The application checks for the validity of token before processing the API call request.

Himanshu
  • 33
  • 7