The security module comes up with a couple of pre-defined authenticators and also allows you to extend and create custom authenticators. The authenticator takes in a credential
, validates it and returns back a principal
. The credential can be username/password or an auth token and the principal will be the user object.
This module uses a session store for storing the auth tokens. Once an user is authenticated, minnal creates a session for the user and a session token will be returned back to the caller as a cookie. The subsequent calls should send the session token in the request cookie for authenticity.
The security is configured at application level. Below is a sample security configuration of an application.
1 2 3 4 5 6 7 8 9 | security:
casConfiguration:
casServerUrl: https://localhost:8443
casProxyCallbackUrl: https://localhost:8083/facilities/casCallbackProxy
ticketStorage:
class: org.minnal.security.auth.cas.JpaPgtStorage
sessionStore:
class: org.minnal.security.session.JpaSessionStore
sessionExpiryTimeInSecs: 300
|
The session store stores the user sessions. A session is a bunch of key-value attributes and maps the session token with an auth token. The security module comes with an inbuilt org.minnal.security.session.JpaSessionStore
that stores the sessions in a database table.
You can change the sesison store from the security configuration of the application.
1 2 3 | security:
sessionStore:
class: org.minnal.security.session.JpaSessionStore
|
Authenticators are the one that actually authenticate the incoming requests based on a strategy. Minnal comes with a CAS authenticator and allows you to build custom ones.
The CAS authenticator uses Jasig client library <https://github.com/Jasig/cas> to talk to the CAS server. It takes in a session/proxy ticket
as credential and validates it against the request path. If they match, returns the CAS user that was originally authenticated. You can configure the authenticator in the security configuration of your application.
1 2 3 4 5 6 7 8 9 | security:
casConfiguration:
casServerUrl: https://localhost:8443
casProxyCallbackUrl: https://localhost:8083/facilities/casCallbackProxy
ticketStorage:
class: org.minnal.security.auth.cas.JpaPgtStorage
sessionStore:
class: org.minnal.security.session.JpaSessionStore
sessionExpiryTimeInSecs: 300
|
To enable CAS authentication for your application, you will have to register CasPlugin in your application.
1 2 3 4 5 6 7 | @Override
protected void registerPlugins() {
if (getConfiguration().getSecurityConfiguration() != null) {
registerPlugin(new CasPlugin(getConfiguration().getSecurityConfiguration()));
}
registerPlugin(new JPAPlugin());
}
|
Minnal comes with a database store org.minnal.security.auth.cas.JpaPgtStorage
for storing the proxy granting tickets. You can also provide a custom storage via the configuration by extending org.jasig.cas.client.proxy.ProxyGrantingTicketStorage
Creating authenticators is simple. You will have to implement the interface org.minnal.security.auth.Authenticator
and configure it in the security configuration of your application.
1 2 3 4 | public interface Authenticator<C extends Credential, P extends Principal> {
P authenticate(C credential);
}
|
Authorizers authorize the incoming requests against the permissions defined over the route. Minnal comes with a simple authorizer org.minnal.security.auth.SimpleAuthorizer
that reads the roles and permission of the user from property files. You can always extend it to provide your own authorizer.
The security configuration defaults to SimpleAuthorizer. In case you want to provide a custom authorizer implementation, you can override it in the application cofiguration.
1 2 3 4 5 | security:
sessionStore:
class: org.minnal.security.session.JpaSessionStore
authorizer:
class: your.custom.authorizer.CustomAuthorizer
|
Minnal takes the permission configuration for the routes via the route definition. Below code shows a sample usage,
1 2 3 4 5 6 7 | public class OrderApplication extends Application<OrderConfiguration> {
@Override
protected void defineRoutes() {
resource(OrderResource.class).builder("/hello").action(HttpMethod.GET, "helloWorld")
.attribute(Authorizer.PERMISSIONS, "permission1,permission2");
}
}
|
This instructs minnal to allow only the users with permissions permission1 and permission2 for the route GET /hello
The simple authorizer uses the roles and permissions of the principal org.minnal.security.auth.Principal
to authorize the route. If the roles and permissions are not populated in the principal, it looks for the property files user_roles.properties and role_permissions.properties in the classpath and validates against them.
The location of the property files can be customized by overriding them in the configuration,
1 2 3 4 5 6 7 8 9 | security:
authorizer:
class: org.minnal.security.auth.SimpleAuthorizer
roleMapper:
class: org.minnal.security.auth.SimpleUserRoleMapper
mappingFile: <location-to-property-file>
permissionMapper:
class: org.minnal.security.auth.SimpleRolePermissionMapper
mappingFile: <location-to-property-file>
|
You can customize the simple authorizer to fetch the roles and permissions of the user from a data store instead of from a property file. All you have to do is to implement the interfaces org.minnal.security.auth.UserRoleMapper
and org.minnal.security.auth.RolePermissionMapper
and override them in the authorizer configuration.
1 2 3 4 5 6 7 | security:
authorizer:
class: org.minnal.security.auth.SimpleAuthorizer
roleMapper:
class: <your-custom-role-mapper-implementation>
permissionMapper:
class: <your-custom-permission-mapper-implementation>
|
You can whitelist the urls that you don’t want to be autneticated by adding them to whiteListedUrls
in configuration. Typical use cases are publicly visible files, health check urls etc.
1 2 3 | security:
whiteListedUrls:
- /appstatus
|