Rama
Rama

Reputation: 1

Angular post-call submitted as OPTIONS to springboot

I am developing end to end application UI Angular, Backend Spring boot with JWT Token.

It reaches my method jwtFilter from Postman and angular.

After the jwtFilter my postman request reaches createJWTtoken method

From angular it doesn't reach create a token method, it returns 200 OK response.

Angular submitting my request as OPTIONS

Angular log

config.JwtRequestFilter    : JWT Token does not begin with Bearer String
DispatcherServlet        : ***OPTIONS*** "/myapp/authenticate", parameters={}
RequestMappingHandlerMapping : Mapped to com.myapp.controller.JwtAuthenticationController#createAuthenticationToken(JwtRequest)
DispatcherServlet        : Completed 200 OK

Request from postman log

config.JwtRequestFilter    : JWT Token does not begin with Bearer String
DispatcherServlet        : ***POST*** "/myapp/authenticate", parameters={}
RequestMappingHandlerMapping : Mapped to com.myapp.controller.JwtAuthenticationController#createAuthenticationToken(JwtRequest)
RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [com.myapp.model.security.JwtRequest@8d233a8]
JwtAuthenticationController      : Creating jwt token
StatisticsImpl         : HHH000117: HQL: select generatedAlias0 from Users as generatedAlias0 where generatedAlias0.userName=:param0, time: 297ms, rows: 1
HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json, application/x-jackson-smile, application/cbor]
HttpEntityMethodProcessor  : Writing [com.myapp.model.security.JwtResponse@2127c1d5]
DispatcherServlet        : Completed 200 OK

**@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {

    final String requestTokenHeader = request.getHeader("Authorization");

    String username = null;
    String jwtToken = null;
    if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
        jwtToken = requestTokenHeader.substring(7);
        try {
            username = jwtTokenUtil.getUsernameFromToken(jwtToken);
        } catch (IllegalArgumentException e) {
            System.out.println("Unable to get JWT Token");
        } catch (ExpiredJwtException e) {
            System.out.println("JWT Token has expired");
        }
    } else {
        logger.warn("JWT Token does not begin with Bearer String");
    }
    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
        UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
        if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
    }
    chain.doFilter(request, response);//Both postman and angular reach this point.
}**
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                .authorizeRequests().antMatchers("/authenticate", "/myapp/authenticate").permitAll().antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated().and().
                exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
    httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        }

Angular post-call

public baseUrl = 'http://localhost:8081/myapp/authenticate';

  public callService(userInfo:User){
    var username=userInfo.username;
    var password = userInfo.password;
    return this.http.post(this.baseUrl,
    {
      'username': username,
    'password': password
    },
    { headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Access-Control-Allow-Credentials': 'true',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST',
    'Access-Control-Allow-Headers': 'Origin, Content-Type, Accept, Access-Control-Allow-Origin',
    }), observe: 'response'}
    ).pipe(
      map(userData => {
        sessionStorage.setItem("username", username);
        let tokenStr = "Bearer " + '';
        console.log(tokenStr);
        sessionStorage.setItem("token", tokenStr);
        return userData;
      })
    );
  }

proxy.config.json

{
"/api": {
  "target": "http://localhost:8080/",
  "changeOrigin": true,
  "secure": false,
  "pathRewrite": {
  "^/api": ""
}
 }
}

Upvotes: 0

Views: 188

Answers (1)

jona303
jona303

Reputation: 1568

That's not angular that post a preflight OPTIONS request, it's your browser. Check this Angular $http is sending OPTIONS instead of PUT/POST

Conclusion you have to fix the CORS policy in the spring boot and how the spring boot handle the options request in your SecurityConfiguration. Can you please add this part of the code in your question.

Upvotes: 0

Related Questions