> The idea of the UnauthorizedException is that they are unauthorized to
> execute that method and not to reflect the fact that authorization
> failed due to them being unauthenticated.

Which is why there is an UnauthenticatedException, although the fact
it extends AuthorizationException is a small fly in the ointment.

> But it should not fail if the user is not remembered or authenticated.
>  Authorization is orthogonal to authentication and either should work
> independently of the other.  For example, you can be remembered, at
> which point the system has enough identity information to perform
> authorization checks, and so those checks should generally be allowed
> to execute.

Fair enough, but it's is really a question of how this should be
modelled using annotations. You can't sensibly have a permission or
role check unless the principal is know. In other words, the user
needs to be remembered or authenticated.

You suggest adding @RequiresAuthentication or @RequiresUser, but that
does seem a bit verbose to me. Also, how do we combine class-level
annotations with method level ones? Do annotations on methods override
the ones on classes? Should overriding only happen if the method and
class annotations are of the same type (authentication or
authorization requirements)?

Maybe an example would help to define behaviour:

@RequiresAuthentication
class MyService {
    void methodOne() {}

    @RequiresRoles("Administrator")
    void methodTwo() {}

    @RequiresUser
    @RequiresPermissions("custom:read")
    void methodThree() {}

    @RequiresGuest
    void methodFour() {}
}

I suggest this behaviour:

1. methodOne() requires an authenticated user (from the class annotation)

2. methodTwo() requires an authenticated user with the role "Administrator"

3. methodThree() requires an authenticated or remembered user with the
permission "custom:read"

4. methodFour() can be accessed by anyone

What do people think? Perhaps there are other scenarios we need to think about?

Cheers,

Peter

Reply via email to