The Inverno framework security module provides general support to secure access to protected service or resources in an application.

An Inverno application divides the security process into three parts:

which is the process of authenticating a request or the entity behind it by validating credentials.
which is the process of identifying the authenticated entity.
Access control
which is the process of controling the access to protected services or resources for the authenticated entity.

The entity represents the originator of an access to the application, it can be external or internal. An application can secure the access to protected services or resources by authenticating the entity which must provide valid credentials. An AccessController can then be obtained from the resulting Authentication to fine-grained control the access to services and resources. The Identity of the authenticated entity might also be resolved from the authentication and used whenever strong identification is required.

It is important to understand that Authentication, Identity and AccessController are decorrelated even though they are all related to the authenticated entity. We can have an authentication without identification (e.g. OAuth2) and/or without access controller.

The SecurityContext is the central security component in an application, it is composed of above components and it should be created and used whenever there is a need to protect services or resources. It allows to verify whether an authenticated entity is accessing a protected service or resource and control whether the access should be granted based on its roles, permissions or any other access control method.

A SecurityManager can be used to authenticate credentials and create a security context for an entity, it is built from an Authenticator, an IdentityResolver and an AccessControllerResolver.

The following is a complete example of how to authenticate an entity and obtain a security context to secure an application:

     SecurityManager<LoginCredentials, PersonIdentity, RoleBasedAccessController> securityManager = SecurityManager.of(
         // The authenticator used to authenticate login credentials
         new UserAuthenticator<>(
             // The in-memory user repository initialized with one user (password is encoded before it is stored in the repository)
                         .identity(new PersonIdentity("jsmith", "John", "Smith", ""))
                         .password(new RawPassword("password"))
               // The login matcher used to match the credentials to authenticate with the stored credentials
               new LoginCredentialsMatcher<>()
         // The identity resolver used to resolve the identity from the authentication
         new UserIdentityResolver<>(),
         // The access controller resolver used to resolve the access controller from the authentication
         new GroupsRoleBasedAccessControllerResolver()
     // Authenticating credentials and create the security context
     SecurityContext<PersonIdentity, RoleBasedAccessController> securityContext = securityManager.authenticate(LoginCredentials.of("jsmith", new RawPassword("password"))).block();
     // Secure the application
     if(securityContext.isAuthenticated()) {
         // Do something usefull with identity...
         securityContext.getIdentity().ifPresent(identity -> System.out.println("Hello " + identity.getFirstName() + " " + identity.getLastName()));
         // Access control
         if(securityContext.getAccessController().orElseThrow().hasRole("readers").block()) {
             // Authenticated user has 'readers' role...
         else {
             // unauthorized access...
             throw new AccessControlException("Unauthorized access");
Jeremy Kuhn