使用 AAD 和 AWS Cognito 针对不同端点保护 Spring Boot REST API 的安全

问题描述 投票:0回答:1

希望有人可以在这里帮助我,因为我在任何地方都找不到有关此主题的任何资源。

我有一个 Spring Boot RestAPI,当前配置有两种路由:1. 未经授权 2. 通过 AAD/Entra 的 Bearer 授权

我的配置方法当前设置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable();
        http.authorizeRequests(requests -> requests
                .antMatchers(HttpMethod.OPTIONS, "/**/**").permitAll()
                .antMatchers("/api/protected/**").fullyAuthenticated()
                .anyRequest().permitAll()
        );
}

它被包装在一个扩展了

AadResourceServerWebSecurityConfigurerAdapter
的类中。

通过以这种方式配置我们的 API,我们能够按如下方式保护我们的路由:

@PreAuthorize("hasAuthority('APPROLE_AppName.RoleName')")
@GetMapping(value = "/some-method", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<String>> getStrings() {
    return ResponseEntity.ok(...);
}

我们的 API 现在应该进行扩展,以允许新型用户使用授权端点。这些用户由 AWS Cognito 管理。我如何设置我的

WebSecurityConfigurerAdapter
以允许某些路径未经授权,某些路径通过 AAD 进行保护,某些路径通过 AWS Cognito 进行保护?

我似乎遇到的主要问题是

AadResourceServerWebSecurityConfigurerAdapter
以这样的方式配置Jwt验证,它只适用于微软给出的承载。

理想情况下我想要这样的东西:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Configuration
    @Order(1)
    public static class AzureAdSecurityConfig extends AadResourceServerWebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests(requests -> requests
                    .antMatchers("/api/aad/**").fullyAuthenticated()
            );
            http.oauth2ResourceServer().jwt([UTILIZE AAD JWT VALIDATION]);
        }

    }

    @Configuration
    @Order(2)
    public static class AwsCognitoSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests(requests -> requests
                    .antMatchers("/api/cognito/**").fullyAuthenticated()
            );
            http.oauth2ResourceServer().jwt([UTILIZE AWS COGNITO JWT VALIDATION]);
        }
    }

    @Configuration
    @Order(3)
    public static class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {

            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.csrf().disable();
                http.authorizeRequests(requests -> requests
                        .antMatchers(HttpMethod.OPTIONS, "/**/**").permitAll()
                        .anyRequest().permitAll()
                );
            }
    }

}

我发现的另一个问题是

AadResourceServerWebSecurityConfigurerAdapter
自动将JwtClaimNames“roles”和“scp”的所有可能的前缀设置为“SCOPE_”和“APPROLE_”。理想情况下,我希望它们对于 AAD 和 AWS Cognito 来说是不同的,这样我就可以将“AAD_SCOPE_”、“AAD_APPROLE_”和“COGNITO_GROUP_”作为前缀。

我找到了一些资料解释如何为 Spring Boot 实现多租户 Jwt 验证,但它们都仅使用 SQL 数据库实现基于密码/用户的身份验证。

有没有办法基本上必须重新实现所有 AAD 逻辑,以便我可以混合对 AWS Cognito 给出的 Jwt 的验证,或者有没有办法根据路由进行决定?

我已经知道您可以使用

oauth2ResourceServer()
上的
HttpSecurity
功能来配置 Jwt 使用情况,但我只找到有关如何为单个租户实现该功能的信息。

如果有人已经成功实施了这个特定或类似的案例,或者可以将我推向正确的方向,我将非常感激。 或者也许我的想法是完全错误的,那么请告诉我。

java spring spring-security azure-active-directory amazon-cognito
1个回答
0
投票

我将在这里公开一个使用 my starter 的解决方案,因为它更容易。如果您更喜欢仅使用“官方”Spring Boot 启动器构建安全配置,请浏览我的教程官方文档(您应该通过

iss
声明映射身份验证管理器,每个身份验证管理器都有自己的身份验证转换器及其自己的权限转换器来处理源声明和您想要的前缀)。

此外,这使用最新的启动版本

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.c4-soft.demo</groupId>
    <artifactId>multi-tenant-resource-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>21</java.version>
        <spring-addons.version>7.3.5</spring-addons.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.c4-soft.springaddons</groupId>
            <artifactId>spring-addons-starter-oidc</artifactId>
            <version>${spring-addons.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
@Configuration
@EnableMethodSecurity
public class SecurityConf {
}

使用此 yaml 进行编辑以放置您自己的发行人:

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
        - iss: https://cognito-idp.us-west-2.amazonaws.com/us-west-2_RzhmgLwjl
          authorities:
          - path: $.cognito:groups
            prefix: COGNITO_GROUP_
        - iss: https://sts.windows.net/0a962d63-6b23-4416-81a6-29f88c553998/
          authorities:
          - path: $.appRoles.*.displayName
            prefix: AAD_APPROLE_
          - path: $.scp
            prefix: AAD_SCOPE_

上面

path
的值是 JSON 路径。您可以使用 jsonpath.com 等工具根据您自己的令牌有效负载测试路径表达式(使用 jwt.io 等工具提取)。

是的,就这么简单。不,我没有省略任何 YAML 属性或 Java 配置(如果您不相信我,只需在新项目中进行测试)。

© www.soinside.com 2019 - 2024. All rights reserved.