简体   繁体   中英

How can I evaluate the HTTP POST payload in spring cloud gateway using spring security custom authorization

I am trying to secure some of my spring cloud gateway routes:

  1. Users must be authenticated using OAUTH2 to be able to use those routes (if not -> respond with http 401)
  2. The JWT access token must include a specific value in the "scp" claim ("2fa" in my case) (if not, respond with http 403)
  3. The JSON payload contains one property "user" that must have the same value as the "sub" claim in the JWT access token. (if not, respond with http 403)

Reading the documentation I found out how I can set up 1. and 2. Unfortunately, there seems to be very little information on how to achieve 3.

Where I could I find a working example?

Here's my spring security setup from application.yaml file:

...
spring:
  profiles: production

  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: ${AUTH_URL}/oidc
          jwk-set-uri: ${AUTH_URL}/oidc/jwks.json
...

Configuation of my SecurityWebFilterChain:

...
 @Bean
  @Order(Ordered.HIGHEST_PRECEDENCE - 3)
  public SecurityWebFilterChain secondFactorScopeApiHttpSecurity(ServerHttpSecurity http) {
    final ServerWebExchangeMatcher baseScopeEndpointsMatcher = new OrServerWebExchangeMatcher(
        new PathPatternParserServerWebExchangeMatcher("/api/fhir"),
        new PathPatternParserServerWebExchangeMatcher("/api/fhir/List**"),
        new PathPatternParserServerWebExchangeMatcher("/api/fhir/Observation**")
    );

    http.securityMatcher(baseScopeEndpointsMatcher)
        .authorizeExchange(exchanges -> exchanges.anyExchange().hasAuthority("SCOPE_2fa"))
        .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt);
    return http.build();
  }
...

I want the user to see a HTTP 403 in case the payloads "user" property does not match the sub claim from the JWT.

What you want to achieve is an easy task on resource-servers and, in my opinion, resources access-control is the responsability of resource-server, not gateway, specially if access decision involves the resource itself.

I would just let the gateway be transparent to OAuth2: leave requests authorization header as well as responses status code unchanged.

I have samples in that series of tutorials which incrementally builds to advanced role based access control. It should take you less than an hour to follow the first 3:

  • 1st demoes resource-server security conf with spring-boot-starter-oauth2-resource-server (what you've implemented on the gateway so far)
  • 2nd shows how to replace JwtAuthenticationToken with an implementation of your choice exposing strongly typed private-claims. It also greatly reduce Java conf with one of the thin wrappers I created around spring-boot one.
  • 3rd demoes security SpEL customization to write stuff like
@GetMapping("/on-behalf-of/{username}")
@PreAuthorize("is(#username) or isNice() or onBehalfOf(#username).can('greet')")
public String getGreetingFor(@PathVariable("username") String username) {
   ... 
} 

Of course, in your case, you would use a signature like myControllerMethod(@RequestBody MyDto dto, Authentication auth) and an expression like #dto.sub eq #auth.name , but you get the idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM