I am trying to implement the custom security rules with Micronaut 2.2.1, but it is not working.
public @interface RequiredPermission {
String resourceIdName();
String permission();
}
Security Rules
@Singleton
public class AdminRequirement implements SecurityRule {
@Override
public SecurityRuleResult check(HttpRequest<?> request, @Nullable RouteMatch<?> routeMatch, @Nullable Map<String, Object> claims) {
if (routeMatch instanceof MethodBasedRouteMatch) {
MethodBasedRouteMatch methodBasedRouteMatch = (MethodBasedRouteMatch) routeMatch;
if (methodBasedRouteMatch.hasAnnotation(RequiredPermission.class)) {
AnnotationValue<RequiredPermission> requiredPermissionAnnotation = methodBasedRouteMatch.getAnnotation(RequiredPermission.class);
// Get parameters from annotation on method
Optional<String> resourceIdName = requiredPermissionAnnotation.stringValue("resourceIdName");
Optional<String> permission = requiredPermissionAnnotation.stringValue("permission");
if (permission.isPresent() && resourceIdName.isPresent() && claims != null) {
// Use name of parameter to get the value passed in as an argument to the method
String resourceId = methodBasedRouteMatch.getVariableValues().get(resourceIdName.get()).toString();
// Get claim from jwt using the resource ID
Object permissionForResource = ((Map) claims.get("https://your-domain.com/claims")).get(resourceId);
if (permissionForResource != null && permissionForResource.equals(permission.get())) {
// if the permission exists and it's equal, allow access
return SecurityRuleResult.ALLOWED;
}
}
}
}
return SecurityRuleResult.UNKNOWN;
}
}
Controller
@Secured(SecurityRule.IS_AUTHENTICATED)
@Controller("/product")
public record ProductController(IProducer iProducer) {
@Get(uri = "/{text}")
@RequiredPermission(resourceIdName = "Admin", permission = "Admin")
public Single<String> get(String text){
return iProducer.sendText(text);
}
}
AdminRequirement implements SecurityRule
the override check() method is never executed, something I am missing.
Application.yml
micronaut:
application:
name: demo
security:
enabled: true
token:
jwt:
enabled: true
signatures:
jwks:
okta:
url: 'https://dev-6271510.okta.com/oauth2/default/v1/keys'
intercept-url-map:
- pattern: /swagger-ui/**
httpMethod: GET
access:
- isAnonymous()
- pattern: /swagger/**
access:
- isAnonymous()
If I update the code as below
@Controller("/product")
@RequiredPermission(resourceIdName = "Admin", permission = "Admin")
public record ProductController(IProducer iProducer) {}
The above code works, but it is not a suitable solution
@RequiredPermission(resourceIdName = "Admin", permission = "Admin")
Repo - https://github.com/anandjaisy/micronaut-customSecurityRule
Security rule implements the ordered interface. To achieve this you have to add below lines in your custom security rule class.