Skip to content

aserto-dev/aserto-spring

Repository files navigation

slack

aserto-spring

Aserto authorization filter for Spring Security. aserto-spring implements middleware for Spring Security that uses the Aserto authorizer.

The package adds a spring security filter that intercepts requests. Once a request is intercepted an authorization call is made to the Aserto Authorizer. Is the request is authorized it is allowed to continue, otherwise a 401 is returned.

Built on top of the Aserto Java SDK

Prerequisites

  • Java 17 or newer
  • Spring Boot 3.1.12 or newer
  • Spring Security 6.1.5 or newer

Building

mvn clean install

Add the middleware to your project

<dependency>
    <groupId>com.aserto</groupId>
    <artifactId>aserto-spring</artifactId>
</dependency>

Configuration

The following configuration settings are required for authorization:

Topaz

  • aserto.authorizer.serviceUrl
  • aserto.authorizer.insecure
  • aserto.authorizer.policyRoot
  • aserto.authorizer.grpc.caCertPath
  • aserto.authorizer.policyName
  • aserto.authorizer.policyLabel
  • aserto.authorizer.token
  • aserto.authorizer.decision

Aserto

  • aserto.authorizer.serviceUrl
  • aserto.authorizer.policyRoot
  • #aserto.authorizer.apiKey
  • aserto.authorizer.policyName
  • aserto.authorizer.policyLabel
  • aserto.authorizer.token
  • aserto.authorizer.decision

Usage

In order to use the middleware you just need to add the annotation for component scan to your main class.

@ComponentScan("com.aserto")

and configure the security filter chain to use the middleware.

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                    .anyRequest().access(new AsertoAuthorizationManager(authzCfg))
        );
        return http.build();
    }

Middleware defaults

By default, the middleware extracts

  • the policy path is extracted from the rest controller mappings e.g. @GetMapping("/users/{userID}") will generate the policy path <policy_path>.GET.users.__userID
  • the resource context is not included by default in the authorization call. The middleware does not extract the identity by default. You can easily configure an identity mapper by using one of the ones we provided or by creating your own. e.g.
    @Bean
    public IdentityMapper identityMapper() {
        Extractor hostNameExtractor = new HeaderExtractor("authorization");
        return new JwtIdentityMapper(hostNameExtractor);
    }

Customizing the middleware

You are able to change the identity mapper, policy path mapper or resource mapper. All you have to do is provide a bean that returns an instance that implement the IdentityMapper, PolicyMapper or ResourceMapper interface.

IdentityMapper

    @Bean
    public IdentityMapper identityMapper() {
        Extractor authzHeaderExtractor = new AuthzHeaderExtractor();
        return new SubjectIdentityMapper(hostNameExtractor);
    }

PolicyMapper

    @Bean
    public PolicyMapper policyMapper() {
        return new CustomPolicyMapper();
    }

ResourceMapper

    @Bean
    public ResourceMapper resourceMapper() {
        BodyExtractor bodyExtractor = new BodyExtractor();
        return new JsonResourceMapper(bodyExtractor, new String[]{"email", "name", "aud"});
    }

Configuring the middleware for check calls

The check call is a specialized is call. It allows us to specify an object type, an object id and a relation. e.g.

    @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authorize -> authorize
            .requestMatchers(HttpMethod.GET, "/todos")
            .access(new CheckConfig(authzCfg, "group", "viewer", "member").getAuthManager())
        );
    return http.build();
}

Method level authorization

The check call can be used at a method level as well. e.g.

    @GetMapping("/todos")
    @PreAuthorize("@aserto.check('group', 'viewer', 'member')")
    public String getTodo() {
        return "Hello from route GET /todos";
    }

The check call accept hard coded values or implementations of the ObjectTypeMapper.java, ObjectTypeMapper.java and RelationMapper.java interfaces

Example

An example can be found in the example directory.