Skip to content
Advertisement

OAuth issue in API gateway

I am facing the OAuth issue, details are below: I am having two microservices: registration-service(https://github.com/choudharylakshyaveer/registration-service) student-service(https://github.com/choudharylakshyaveer/student-service)

For these two I have added : cloud-config-server(https://github.com/choudharylakshyaveer/cloud-config-server) naminig-server(https://github.com/choudharylakshyaveer/naming-server) gateway(https://github.com/choudharylakshyaveer/api-gateway)

FrontEnd: is at react js: https://github.com/choudharylakshyaveer/chargie

For first time use, a new user need to be register that can be done from curl:

curl --location --request GET 'http://localhost:8765/user/save' 
--header 'Content-Type: application/json' 
--data-raw '{
    "username": "user@chargie.com",
    "password": "chaudhary22",
    "enabled": true,
    "roles": [
        "ROLE_ADMIN",
        "ROLE_USER"
    ]
}'

To login using the above registered user, below can be run from cUrl:

curl --location --request POST 'http://localhost:8765/login' 
--header 'Content-Type: application/json' 
--data-raw '{
    "username": "user@chargie.com",
    "password": "chaudhary22"
}'

Once I log In and get the Bearer token, after that I am facing cors issue from the reactJs FE, bu same request is working fine from the Postman, below is request from postman:

curl --location --request GET 'http://localhost:8765/REGISTRATION-SERVICE/test' 
--header 'Access-Control-Allow-Credentials: true' 
--header 'Access-Control-Allow-Headers: content-type' 
--header 'Access-Control-Allow-Methods: PUT, POST, GET, DELETE, PATCH, OPTIONS' 
--header 'Access-Control-Allow-Origin: *' 
--header 'Access-Control-Max-Age: 1800' 
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJyb2xlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwic3ViIjoibHZzIiwiaWF0IjoxNjU4OTM0NzIxLCJleHAiOjE2NTg5NjM1MjF9.MN6lCrwLB2bBDBLp-HG4nlSRlyhoR2cQDSRGvJCD2WwDMojhei0wW7xVuDwVCtRUANK02aQMhqagafB2csDWWg'

Below is the code used to hit request from ReactJs FE:

var config = {
            method: 'get',
            url: 'http://localhost:8765/REGISTRATION-SERVICE/test',
            headers: { 
              Authorization: `Bearer ${token}`,
              'Content-Type': 'application/json',
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Credentials': 'true',
              'Access-Control-Max-Age': '1800',
              'Access-Control-Allow-Headers': 'content-type',
              'Access-Control-Allow-Methods': 'PUT, POST, GET, DELETE, PATCH, OPTIONS'
            },
            Authorization: `Bearer ${token}`
          };
          
          axios(config)
          .then(function (response) {
            console.log(JSON.stringify(response.data));
          })
          .catch(function (error) {
            console.log(error);
          });

And this request gives me CORS issue: enter image description here

Snippet of the ServerSecurityContextRepository’s overridden method used in SecurityContextRepository class of api-gateway:

@Override
    public Mono<SecurityContext> load(ServerWebExchange swe) {
        ServerHttpRequest request = swe.getRequest();
        HttpHeaders headers = request.getHeaders();
        String authHeader = headers.getFirst(HttpHeaders.AUTHORIZATION);

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.authenticationManager.authenticate(auth).map((authentication) -> {
                return new SecurityContextImpl(authentication);
            });
        } else {
            return Mono.empty();
        }
    }

Here when the request is coming from the Postman then below is receievd in the headers variable:

[access-control-allow-credentials:"true", access-control-allow-headers:"content-type", access-control-allow-methods:"PUT, POST, GET, DELETE, PATCH, OPTIONS", access-control-allow-origin:"*", access-control-max-age:"1800", authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJyb2xlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwic3ViIjoibHZzIiwiaWF0IjoxNjU4OTM0NzIxLCJleHAiOjE2NTg5NjM1MjF9.MN6lCrwLB2bBDBLp-HG4nlSRlyhoR2cQDSRGvJCD2WwDMojhei0wW7xVuDwVCtRUANK02aQMhqagafB2csDWWg", user-agent:"PostmanRuntime/7.29.0", accept:"*/*", postman-token:"6c0d7a9a-dcde-45d7-8422-1476682db9f4", host:"localhost:8765", accept-encoding:"gzip, deflate, br", connection:"keep-alive"]

But when same request comes from Front end then below is receievd in the headers variable and it seems to be malformed:

[host:"localhost:8765", connection:"keep-alive", pragma:"no-cache", cache-control:"no-cache", accept:"*/*", access-control-request-method:"GET", access-control-request-headers:"access-control-allow-credentials,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,access-control-max-age,authorization", origin:"http://localhost:3000", user-agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", sec-fetch-mode:"cors", sec-fetch-site:"same-site", sec-fetch-dest:"empty", referer:"http://localhost:3000/", accept-encoding:"gzip, deflate, br", accept-language:"en-US,en;q=0.9"]

So, Here I am not receiving proper Authorization header on backend’s headers variable so that I can take Bearer token to validate it.

Advertisement

Answer

Working after adding cors, complete code below for SecurityWebFilterChain’s method :

http
            .exceptionHandling()
            .authenticationEntryPoint((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                });
            }).accessDeniedHandler((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                });
            }).and()
            .cors().configurationSource(request -> {
                CorsConfiguration config = new CorsConfiguration();
                config.setAllowedOrigins(Collections.singletonList("*"));
                config.setAllowedMethods(Arrays.asList("GET","POST","PUT","PATCH", "DELETE","OPTIONS"));
                config.setAllowedHeaders(Collections.singletonList("*"));
                return config;
            })
            .and()
            .csrf().disable()
            .and()
            .formLogin().disable()
            .httpBasic().disable()
            .authenticationManager(authenticationManager)
            .securityContextRepository(securityContextRepository)
            .authorizeExchange()
            .pathMatchers("/login").permitAll()
            .pathMatchers("/user/save").permitAll() //line added
            .anyExchange()
            .authenticated()
            
            .and().build();
Advertisement