Search code examples
springspring-bootspring-securityspring-cloudspring-cloud-gateway

Calling resource server with JWT returns HTTP 403 by way of Spring Cloud Gateway


I have two projects. Both are reactive Spring. Project one is a combination of a Javascript application and Spring Cloud Gateway for reverse proxying. The second project is a Spring resource server.

Project one proxies requests from /api/artists to project two at http://localhost:8081/v1/artists.

If I call the resource server (project two) directly with a valid JWT, the response comes back HTTP 200. If I go by way of the reverse proxy in project one, and hit http://localhost:8080/api/artists with the same JWT, I receive an HTTP 403 from project two, which propagates back through project one.

Here is my Spring Cloud Gateway configuration:

spring:
  cloud:
    gateway:
      routes:
        - id: experience-api
          uri: http://localhost:8081/v1/artists
          predicates:
            - Path=/api/artists/**
          filters:
            - TokenRelay=

The HTTP 403 indicates that while the token was valid, it must be lacking some other permission to perform the action. Though, I'm not sure why it works when I call it directly versus calling it by way of the reverse proxy/Spring Cloud Gateway.


Solution

  • After stepping away for a couple days, I realized that my gateway configuration was incorrect. I realized that the original configuration was proxying requests to /v1/artists/api/artists, which doesn't exist on project two, but my security configuration was set up so that /v1/** required authentication. I suspect that is why I saw an HTTP 403 Forbidden before I saw an HTTP 404 Not Found.

    I ended up using the below configuration:

    spring:
      cloud:
        gateway:
          routes:
            - id: experience-api
              uri: http://localhost:8081
              predicates:
                - Path=/v1/artists/**
              filters:
                - TokenRelay=
    

    Note that I removed /v1/artists from the uri property. Now, requests to project one at http://localhost:8080/v1/artists are getting proxied to http://localhost:8081/v1/artists. I could have used the StripToken predicate filter but it wasn't as clean as this.