micronaut-projects / micronaut-projects/micronaut-security

@Secured annotation unintuitive when using expressions

Open
#2,012 0 comments 0 reactions 1 assignee Claimed by @sdelamo View on GitHub
status: in progress status: under consideration type: bug
Dominant language
Java
Stars
179
Forks
146
Avg merge
1d 17h
Merged PRs (30d)
16

Description

### Expected Behavior

```java
@Secured({
SecurityRule.IS_ANONYMOUS,
"#{ true }"
})
```

I would expect the annotated endpoint to permit any request, since the first value is a token to allow unauthorized access and even the second value, an expression, evaluates to `true`.

I would also expect this configuration to be semantically equivalent:
```java
@Secured({
"#{ true }",
SecurityRule.IS_ANONYMOUS
})
```

### Actual Behaviour

The following `REJECTS` all requests:
```java
@Secured({
SecurityRule.IS_ANONYMOUS,
"#{ true }"
})
```

The following `PERMITS` all requests:
```java
@Secured({
"#{ true }",
SecurityRule.IS_ANONYMOUS
})
```

The following `REJECTS` all requests, even if the user has `some-role` in their roles:
```java
@Secured({
"some-role",
"#{ true }"
})
```

Reasons being:
1. When expressions are used, only the very first result is checked - effectively dropping the OR semantic
a. https://github.com/micronaut-projects/micronaut-security/blob/4.13.x/security/src/main/java/io/micronaut/security/rules/SecuredAnnotationRule.java#L75-L80
2. `EvaluatedAnnotationValue::booleanValues` returns `false` for anything that is not an expression - making it impossible to mix expressions and roles/tokens within the same `@Secured` annotation.

### Steps To Reproduce

```java
@Controller
public class MyController {

@Secured({"#{ true }", SecurityRule.IS_ANONYMOUS})
@Get("/permitted")
public void permitted() {}

@Secured({SecurityRule.IS_ANONYMOUS, "#{ true }"})
@Get("/rejected")
public void rejected() {}

@Secured({SecurityRule.IS_ANONYMOUS, "#{ false }"})
@Get("/also-rejected")
public void alsoRejected() {}
}
```

1. Request `GET /permitted`
2. Observe correct `HTTP 200`
3. Request `GET /rejected`
4. Observe faulty `HTTP 403`
5. Request `GET /also-rejected`
6. Observe faulty `HTTP 403`

### Environment Information

_No response_

### Example Application

_No response_

### Version

4.8.2

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.