Hela, Hidden Extended Layer for Authentication is a Java library that implements the OpenID Connect (OIDC) / OAUth2 protocols at the client side. Built on top of Jakarta security, it targets applications hosted by servlet containers that are compliants with this framework. Primarily It targets Tomcat as a servlet container and Keycloak as the authentication server. But the best side It built with a strict implementation of the Jakarta Security Framework (a.k.a. JASPIC, formerly named) and the industry-standard OIDC and OAuth2 protocols. As such, it should also support any Jakarta EE 3.0 or later compatible application server and any OIDC/OAuth2 compliant authentication server.
Despite the complexity of the behaviors implemented to ensure security, Hela's code remains simple to approach and study its content. This insure total transparency about its operation, which is absolutely necessary for such critical feature. Its free source code is available to anonymous download on the Bitbucket platform. It is licensed under the GNU LGPL v3+ license.
Enjoy developing web applications & API REST containerized & well secured with Hela library, Tomcat and Keycloak.
The usual way to integrate Hela library with the target application is to insert a dependency to the construction of this application. This insertion varies according to the tool used. eg with Maven, just add the dependency to «pom.xml» project:
<groupId>net.meddeb.oauth</groupId>
<artifactId>hela</artifactId>
<!-- remember to adjust version if needed -->
<version>3.0.0</version>
</dependency>
You may prefer to build yourself the library before his intergration. This allows you to inspect code or make some modifications on it. The following commands let you achieve this goal.
cd hela
git checkout v3.0.0 # or whatever another tag
mvn clean install # At this time built library is ready to get used on your workstation
The demonstration application « Corporate intranet » made for Tomcat server may show you a concrete use case about integration.
Hela comes with a lot of settings parameters that allows to tuning his operation. It must get them at startup that happen at target application start time. Settings may come from configuration file or from environment variables. The special environement varibale HELA_CONFIG_PATH allows to switch between those 2 modes.
- Provide this variable with a valid path who contains the configuration file to use configuration file mode. The file name must be set to hela-auth.conf
- Do not provide this variable but other mandatory parameters as environment variables to use the second mode.
Environment variables mode is suitable for containerized deployment, and configuration file mode is easy to done with non containerized one. See below for the full parameters list.
Currently Hela library supports the Authorization code flow which is suitable for web applications. In the next release, it will support Bearer authentication which is suitable for API REST authentication. Then it will support other less used flows. The parameter authentication_type in the configuration file or the AUTHENTICATION_TYPE environment variable allows to define which operation mode the library perform.
authentication_type = authorization_code_grant or AUTHENTICATION_TYPE = authorization_code_grant. It is the default mode if this parameter value is not provided.
If user attempts to access protected resources of the application (step 1):
- If it is not already authenticated with the authentication server: it will be redirected to this server to sign-in (step 2).
- If it is already authenticated with the authentication server (SSO): it will be recognized as connected.
In both cases, the exchanges between Hela and the authentication server (step 3) allow the user's identity to be confirmed, information about them to be retrieved and made available to the application through the underlying container
authentication_type = bearer_token or AUTHENTICATION_TYPE = bearer_token
Request is coming from an application, no web browser (User-agent), nor human user involved. Client application make the request on behalf a user (e.g. web application) or on behalf himself (e.g. batch job). If it attempts to access protected resources of the target application (step 1):
- If it is not contains the HTTP regular authentication header with a Bearer token, it is rejected
- Otherwise, the library make token verification with the authentication server (step 2) and allows the request if it is valid one.
There are three security levels supported. The parameter security_level in configuration file or SECURITY_LEVEL environment variable allows to set it. The level mainly define how deeply the token validity check should be done.
security_level = minimal or SECURITY_LEVEL = minimal.
This level is intended to use in development or test environment where strict configuration to address security concern could be painful. It is strongly recommended to not use it in production even within full controlled infrastructure (whole on premise). Only the token's own fields values are verified like expiry time, issuer or audience. The integrity of the token is not checked and communication through insecure, without TLS connection is allowed.
security_level = enforced or SECURITY_LEVEL = enforced. It is the default level if this parameter value is not provided.
This level is intended to use within full controlled infrastructure that is whole self managed. It is recommended to not use it in production when communication pass through public network or within infrastructure paired to third-party one. The token's intergrity is checked against issuer signature in addition to own fields values verification. Only secure communication over TLS is allowed.
security_level = rugged or SECURITY_LEVEL = rugged.
In addition to support all features of enforced level, the Demonstrating Proof of Possession (DPoP) mechanism is implemented. DPoP significantly increases capability to fight against token theft and replay attacks.
Information about authentication success comes to target application at the servlet level. Call to HttpServletRequest#getUserPrincipal() method returns:
- null if authentication fail for any reason
- Non null Principal object if authentication success, Principal#getName() to get authenticated username
When the authentication success, target application may get informed about authorization aspect. HttpServletRequest#isUserInRole(String) call get response about authenticated user'membership of a particular role.
Default, all target application or API REST is protected and access to any part of them requires authentication. This behavior may be tuned with protected_path configuration file parameter or PROTECTED_PATH environment variable. This parameter must contains a Java regular expression that reduce protected area to only a perticular part. eg /private/* allows to restrict protected area to locations bellow /private/ path of the URI call. Other locations become public and does not require authentication.
Authentication with OIDC protocol requires a lot of data exchange between Hela code and the authentication server. Several types of issues may occur during these exchanges. The server may become unavailable, network communication break happens or identity theft attempt may occurs. When such issue happen the authentication fails. In addition, in case of Authentication code flow with a target web application, a default localized (6 languages) error message is shown.
Target application developers may override this behavior with error_path configuration file parameter or ERROR_PATH environment variable. The value of this parameter must be a path to resource that manage a custom web page. eg /failauth.jsp. Obviously, in this case developers should add this JSP resource to the target application root path.
Config file | Environment | Value | Default | Required | Value meaning |
---|---|---|---|---|---|
HELA_CONFIG_PATH | Only when config file | Path to configuration file, file name must be hela-auth.conf | |||
authentication_type | AUTHENTICATION_TYPE | authorization_code_grant | ✓ | ✗ | OAuth2 Authentication code flow |
- | - | bearer_grant | ✓ | Bearer authentication | |
security_level | SECURITY_LEVEL | minimal | ✓ | Insecure communication allowed, token integrity not checked, not suitable for production | |
enforced | ✓ | ✗ | Secure communication over TLS is mandatory, token integrity checked, suitable for production within full controlled infrastructure | ||
root_endpoint | ROOT_ENDPOINT | provide URL | ✗1 | Authentication server root URL that must be completed with suffix to reach different end points | |
authorization_endpoint | AUTHORIZATION_ENDPOINT | provide URL | ✗2 | Authentication server's authorization endpoint, full URL | |
token_endpoint | TOKEN_ENDPOINT | provide URL | ✗2 | Authentication server's token request endpoint, full URL | |
userinfo_endpoint | USERINFO_ENDPOINT | provide URL | ✗3 | Authentication server's user info endpoint, full URL | |
introspection_endpoint | INTROSPECTION_ENDPOINT | provide URL | ✗4 | Authentication server's introspection request endpoint, full URL | |
certs_endpoint | CERTS_ENDPOINT | provide URL | ✗5 | Authentication server's public key certificates request endpoint, full URL | |
client_id | CLIENT_ID | provide ID | ✓ | Target application client ID registration on authentication server | |
client_secret | CLIENT_SECRET | provide secret | ✓6 | Target application client secret registration on authentication server | |
userinfo_scope | USERINFO_SCOPE | provide scope | openid | ✗7 | list of scopes claimed to authentication server to include them in the token |
protected_path | PROTECTED_PATH | provide path | /* | ✗ | Java regular expression that define protected area within application URL |
error_path | ERROR_PATH | provide path | ✗ | Path to custom error page within application URL | |
server_context | SERVER_CONTEXT | provide context | ✗8 | Some application servers like Wildfly and Geronimo still require custom tag in their internal server context |
- 1 If provided all other endpoint parameters value will be set to this value concatened with suffixes: auth, token, userinfo, introspect and certs. Unless you which to override this behaviore for one or more parameter no need to provide them.
- 2 Value required only for Authorization code flow.
- 3 Provide only when access token is opaque and there is a need to have extended scope or authorization information. See authentication server documents to make decision. Some authentication servers do not include informations in the access token
- 4 Provide only when strong validation of token is necessary and there is no other way to do it (eg opaque token with no signature). Huge resources consumption. Avoid as much as possible.
- 5 Not necessary and not used when security level is set to minimal
- 6 Do not provide when "Bearer authentication" nor when "Authorization code fow" with mutual TLS authentication (mTLS). mTLS is possible only with rugged security level.
- 7 Be careful with this list, claimed data may be subject to user consent on the authentication server. When consent not granted authentication fails
- 8 Do not provide for Tomcat, set server for geronimo and default-server for Jboss/Wildfly
The demonstration application « Corporate intranet » aims to show you a concrete use case of Hela's integration within a web application. Its source code is available on the Bitbucket plateform. Especially PrivateAccess.java servlet who handle authentication and authorization informations coming from Hela library let you know how to use them. The default log level set to « trac » shows a lot of informations about « Authorization code flow » exchange performed in this use case.