k

Kikaha

blog source code

Kikaha has a very tiny and non-intrusive Security API written over Undertow's Security API. Basically it has a few components that together allow you to protect your resources. Let's checkout the main components you'll usually need to deal with:

  • Authentication Rules: will define how your web resources will be protected against unauthorized access.
  • Authentication Mechanisms: defines how to extract credentials from the request when trying to authenticate.
  • Identity Manager: defines how to check if found credentials are valid.
  • Session Store: defines how to sessions are managed on the server.
  • Password Encoder: defines how passwords are stored and matched.

Authentication Rules

TODO

Authentication Mechanisms

Authentication mechanisms is responsible for extract credentials from HTTP requests. Usually they does not check if the credentials are valid, but delegates the validation to the IdentityManager defined on the matched Authentication Rule. Out-of-box only a few Authentication Mechanisms are provided. They are very common and allow developers to get started very quickly. Bellow they are listed and identified by its own alias:

  • basic: The implementation of Http's Basic Authentication.
  • form: The Form-based authentication. It will enforce security by requiring user to provide their credentials through a HTML form.
  • json: Will receive the credentials through a HTTP POST of a JSON object. This mechanism requires kikaha-jackson module.

Now lets talk about its alias. All Authentication Mechanism should be defined on the configuration entry server.auth.authentication-mechanisms on a alias: class.Name form (see sample the configuration file bellow). The alias, as we discussed before, are used on the Authentication Rules and avoids you to repeat the Authentication Mechanism's Class Canonical Name every time you need to use it to protect a specific resource.

Here are a sample code with the default Authentication Mechanisms that comes out-of-box with Kikaha:

server:
  auth:
    auth-mechanisms:

      # available on kikaha-core's module
      basic: kikaha.core.modules.security.BasicAuthenticationMechanism
      form: kikaha.core.modules.security.FormAuthenticationMechanism

      # available on kikaha-jackson's module
      json: kikaha.urouting.serializers.jackson.JSONAuthenticationMechanism

If none of the above described mechanisms fits your needs you can easily create your own by implementing the interface kikaha.core.modules.security.AuthenticationMechanism and defining an alias for it. Please, keep in mind that cood Authentication Mechanisms usually delegates the Credential Validation to a proper IdentityManager.

Identity Managers

Identity Managers are responsible for ensure credentials are valid. Also, is its responsibility retrieve the Account and its Roles from the place you've stored your data. Out-of-box there a few Identity Managers available:

  • "fixed": Uses a fixed username and password, defined on the configuration file, as the only valid credential
  • "db-auth": Uses a Database connection to validate credentials.

, the only a Fixed User and Password identity manager is provided. It is a fast way to define a username and a password to authenticate a user while you are developing a software. A more sophisticated Identity Manager could be developed by implementing the kikaha.core.modules.security.IdentityManager interface. A much simpler approach is to extends kikaha.core.modules.security.AbstractPasswordBasedIdentityManager.

Custom Identity Manager

The code bellow illustrates how to create your own Identity Manager with fixed username and password. Developers are encouraged to follow this pattern to provide their own Identity Manager.

package sample;
import kikaha.core.modules.security.*;

public class CustomIdentityManager extends AbstractPasswordBasedIdentityManager {

    final String username = "admin";
    final String password = "password";
    final String defaultRole = "admin";

    @Override
    public Account retrieveAccountFor( String id, String password ) {
        if ( this.username.equals( id ) && this.password.equals( password ) )
            return new FixedUsernameAndRolesAccount( username, defaultRole );
        return null;
    }
}

Don't forget to register an alias to your custom Identity Manager.

server:
  auth:
    identity-manager:
      custom: sample.CustomIdentityManager

Session Store

Password Encoders

password-encoder: kikaha.core.modules.security.PlainTextPasswordEncoder

Note: In order to use the distributed SecurityContextFactory you have to include the kikaha-hazelcast module. See more details at Hazelcast documentation.

Note2: Both SecurityContextFactorys, AuthenticationMechanisms and IdentityManagers has to be a managed class in order to Kikaha load it correctly at the application startup. If you are not familiar with the managed class term, please take a look at the Dependency Injection for more details. [block:api-header] { "type": "basic", "title": "Protecting resources" } [/block] To define that some web resources will requires authentication, you could include an entry in server.auth.rules array on your configuration file. It will behaves like ACL where the first rule that matches the request will be applied. If no rule was matched, then the route will be executed as non-authenticated resource. Bellow we defined a rule the require authentication for any request made at "/protected/" resource and its sub-locations. [block:code] { "codes": [ { "code": "server: auth: rules: - pattern: \"/protected/*\" identity-manager: - \"custom\" auth-mechanisms: - \"basic\" expected-roles: exclude-patterns: ", "language": "yaml", "name": "application.yml" } ] } [/block] As you can note, there is some attributes we can define to the rule:

  • pattern: the unique mandatory attribute, it defines which resources will require authentication
  • identity-manager: defines which Identity Manager will be used to match the sent credentials.
  • mechanisms: defines which Authentication Mechanisms will used to extract credentials.
  • expected-roles: (optional) which roles should the Identity Manager retrieves to authorize the access to resources protected by this rule.
  • exclude-patterns: (optional) is an array of patters that should ignored during the authorization/authentication process. There is cases where is easier to map a more generalist pattern and define which URLs should be unconsidered on the authentication/authorization process. It may be also useful when you have more than one authentication rule.

Configuring the Fixed User and Password Identity Manager

If you opt to use the Fixed User and Password Identity Manager, you can set the expected username, password and role at server.auth.fixed-auth entry of your configuration file. You can find the default values here. [block:code] { "codes": [ { "code": "server: auth: fixed-auth: username: \"admin\" password: \"admin\" role: - \"admin\"", "language": "yaml", "name": "application.yml" } ] } [/block]

[block:api-header] { "type": "basic", "title": "Configuring the Form Authentication Mechanism" } [/block] Consider the bellow configuration. [block:code] { "codes": [ { "code": "server: auth: rules: - pattern: \"/protected/*\" auth-'mechanisms: - \"form\" identity-manager: - \"default\" fixed-auth: username: \"admin\" password: \"1q2w3e\" role: \"admin\" form-auth: login-page: \"/auth/login.html\" error-page: \"/auth/error.html\" permition-denied-page: \"/auth/forbiden.html\" ", "language": "json", "name": "application.yml" } ] } [/block] Here we've defined a set of configuration parameters related to Form Authentication. At the first block we which resources will be required authorization to access. Besides is impossible to set more than one Authentication Mechanism at once, we set only "form" to simplify our example.

As we defined the "default" identity-manager as our mechanism to validate the credentials sent by the HTTP client, we defined the username and password at the fixed-auth block. The last block, form-auth define which pages will be used during the authentication lifecycle:

  • login-page: the HTML page containing the form where users will be able to write its credentials
  • error-page: the HTML page that will notificaty that the logging have failed
  • permition-defined-page: the HTML page the will notify the user that the login was OK but he does not have permition (specific roles) to access the requested page. [block:code] { "codes": [ { "code": "
    Login to the Demo application:
    Name:
    Password:
    ", "language": "html", "name": "login.html" } ] } [/block] Above a sample login.html. Java developers will be at home here once it follows the same standard for form authentication defined by Servlet API:
  • The action must be placed inside the protected path and end with jsecuritycheck
  • The username field must be named j_username
  • The password field must be named j_password.