Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fallback for method based authorization #15257

Closed
Junhyunny opened this issue Jun 15, 2024 · 2 comments
Closed

fallback for method based authorization #15257

Junhyunny opened this issue Jun 15, 2024 · 2 comments
Assignees
Labels
in: docs An issue in Documentation or samples status: waiting-for-feedback We need additional information before we can continue type: bug A general bug

Comments

@Junhyunny
Copy link
Contributor

Junhyunny commented Jun 15, 2024

I am following an example in the spring security document to handle fallback for method based authorization.

In this example, @HandleAuthorizationDenied annotation is on the POJO User class's getEmail method like this.

public class User {
    // ...

    @PostAuthorize(value = "hasAuthority('user:read')")
    @HandleAuthorizationDenied(handlerClass = EmailMaskingMethodAuthorizationDeniedHandler.class)
    public String getEmail() {
        return this.email;
    }
}

This is not working in my test code. Here is my codes.

User class

package com.example.demo.domain;

import com.example.demo.handler.EmailMaskingMethodAuthorizationDeniedHandler;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.authorization.method.HandleAuthorizationDenied;

public class User {
    private final String email;

    public User(String email) {
        this.email = email;
    }

    @PostAuthorize(value = "hasAuthority('USER::READ')")
    @HandleAuthorizationDenied(handlerClass = EmailMaskingMethodAuthorizationDeniedHandler.class)
    public String getEmail() {
        return email;
    }
}

UserService class

package com.example.demo.service;

import com.example.demo.domain.User;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    public User getUser() {
        return new User("junhyunny@naver.com");
    }
}

UserServiceTests class

package com.example.demo;

import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserServiceTests {

    @Autowired
    UserService sut;

    @Test
    void test() {
        var result = sut.getUser();


        System.out.println(result.getEmail());
    }
}

Result is this.

junhyunny@naver.com

Is there a something what I miss? Please let me know. Is it working well? I tried this example with spring data jpa because I doubted that there are some mechanism working together with jpa repository. However the trial with jpa was also failed.

I think that @PostAuthorize annotation is working based on Spring AOP, so we need to this annotation should be on the UserService bean's getUser method.

Like this.

@Service
public class UserService {

    @PostAuthorize(value = "hasAuthority('USER::READ')")
    @HandleAuthorizationDenied(handlerClass = EmailMaskingMethodAuthorizationDeniedHandler.class)
    public User getUser() {
        return new User("junhyunny@naver.com");
    }
}

And MethodAuthorizationDeniedHandler instance is changed like this.

@Component
public class EmailMaskingMethodAuthorizationDeniedHandler implements MethodAuthorizationDeniedHandler {

    @Override
    public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
        return "***";
    }

    @Override
    public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult, AuthorizationResult authorizationResult) {
        User user = (User) methodInvocationResult.getResult(); // get user
        return new User(user.getEmail().replaceAll("(^[^@]{3}|(?!^)\\G)[^@]", "$1*")); // return new user instance
    }
}

When I changed the code like above. Test result is this.

jun******@naver.com

The example in the document is wrong or not? If sample code in the example is wrong, can I change like this?

@Junhyunny Junhyunny added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jun 15, 2024
@marcusdacoregio marcusdacoregio self-assigned this Jun 17, 2024
@marcusdacoregio marcusdacoregio added in: docs An issue in Documentation or samples and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 17, 2024
@marcusdacoregio
Copy link
Contributor

Hi @Junhyunny, thanks for the report. Yes, the feature relies on Spring AOP. The documentation says:

Let’s consider the example from the previous section

The previous section uses @AuthorizeReturnObject in the service class, effectively generating a proxy for the User class. Can you try adding the annotation and see if it works?

@marcusdacoregio marcusdacoregio added the status: waiting-for-feedback We need additional information before we can continue label Jun 17, 2024
@Junhyunny
Copy link
Contributor Author

Great! It is worked. Thanks, I am going to close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: docs An issue in Documentation or samples status: waiting-for-feedback We need additional information before we can continue type: bug A general bug
Projects
Status: No status
Development

No branches or pull requests

2 participants