Chapter 16. Jakarta Authentication 16.1. About Jakarta Authentication Security Jakarta Authentication is a pluggable interface for Java applications. For information about the specification, see the Jakarta Authentication specification . 16.2. Configure Jakarta Authentication You can authenticate a Jakarta Authentication provider by adding <authentication-jaspi> element to your security domain. The configuration is similar to that of a standard authentication module, but login module elements are enclosed in a <login-module-stack> element. The structure of the configuration is: Example: Structure of the authentication-jaspi Element <authentication-jaspi> <login-module-stack name="..."> <login-module code="..." flag="..."> <module-option name="..." value="..."/> </login-module> </login-module-stack> <auth-module code="..." login-module-stack-ref="..."> <module-option name="..." value="..."/> </auth-module> </authentication-jaspi> The login module itself is configured the same way as a standard authentication module. The web-based management console does not expose the configuration of JASPI authentication modules. You must stop the JBoss EAP running instance completely before adding the configuration directly to the EAP_HOME /domain/configuration/domain.xml file or the EAP_HOME /standalone/configuration/standalone.xml file. 16.3. Configure Jakarta Authentication Security Using Elytron Starting in JBoss EAP 7.3, the elytron subsystem provides an implementation of the Servlet profile from the Jakarta Authentication. This allows tighter integration with the security features provided by Elytron. Enabling Jakarta Authentication for a Web Application For the Jakarta Authentication integration to be enabled for a web application, the web application needs to be associated with either an Elytron http-authentication-factory or a security-domain . By doing this, the Elytron security handlers get installed for the deployment and the Elytron security framework gets activated for the deployment. When the Elytron security framework is activated for a deployment, the globally registered AuthConfigFactory is queried when requests are handled. It will identify if an AuthConfigProvider , which should be used for that deployment, has been registered. If an AuthConfigProvider is found, then JASPI authentication will be used instead of the deployment's authentication configuration. If no AuthConfigProvider is found, then the authentication configuration for the deployment will be used instead. This could result in one of the three possibilities: Use of authentication mechanisms from an http-authentication-factory . Use of mechanisms specified in the web.xml . No authentication is performed if the application does not have any mechanisms defined. Any updates made to the AuthConfigFactory are immediately available. This means if an AuthConfigProvider is registered and is a match for an existing application, it will start to be used immediately without requiring redeployment of the application. All web applications deployed to JBoss EAP have a security domain, which will be resolved in the following order: From the deployment descriptors or annotations of the deployment. The value defined on the default-security-domain attribute on the undertow subsystem. Default to other . Note It is assumed that this security domain is a reference to the PicketBox security domain, so the final step in activation is ensuring this is mapped to Elytron using an application-security-domain resource in the undertow subsystem. This mapping can do one of the following: Reference an elytron security domain directly, for example: Reference a http-authentication-factory resource to obtain instances of authentication mechanisms, for example: The minimal steps to enable the Jakarta Authentication integration are: Leave the default-security-domain attribute on the undertow subsystem undefined so that it defaults to other . Add an application-security-domain mapping from other to an Elytron security domain. The security domain associated with a deployment in these steps is the security domain that will be wrapped in a CallbackHandler to be passed into the ServerAuthModule instances used for authentication. Additional Options Two additional attributes have been added to the application-security-domain resource to allow some further control of the Jakarta Authentication behavior. Table 16.1. Attributes Added to the application-security-domain Resource Attribute Description enable-jaspi Can be set to false to disable Jakarta Authentication support for all deployments using this mapping. integrated-jaspi By default, all identities are loaded from the security domain. If set to false , ad-hoc identities will be created instead. Subsystem Configuration One way to register a configuration that will result in an AuthConfigProvider being returned for a deployment is to register a jaspi-configuration in the elytron subsystem. The following command demonstrates how to add a configuration containing two ServerAuthModule definitions. This results in the following configuration being persisted. <jaspi> <jaspi-configuration name="simple-configuration" layer="HttpServlet" application-context="default-host /webctx" description="Elytron Test Configuration"> <server-auth-modules> <server-auth-module class-name="org.wildfly.security.examples.jaspi.SimpleServerAuthModule" module="org.wildfly.security.examples.jaspi" flag="OPTIONAL"> <options> <property name="a" value="b"/> <property name="c" value="d"/> </options> </server-auth-module> <server-auth-module class-name="org.wildfly.security.examples.jaspi.SecondServerAuthModule" module="org.wildfly.security.examples.jaspi"/> </server-auth-modules> </jaspi-configuration> </jaspi> Note The name attribute is just a name that allows the resource to be referenced in the management model. The layer and application-context attributes are used when registering this configuration with the AuthConfigFactory . Both of these attributes can be omitted allowing wildcard matching. The description attribute is also optional and is used to provide a description to the AuthConfigFactory . Within the configuration, one or more server-auth-module instances can be defined with the following attributes. class-name - The fully qualified class name of the ServerAuthModule . module - The module to load the ServerAuthModule from. flag - The control flag to indicate how this module operates in relation to the other modules. options - Configuration options to be passed into the ServerAuthModule on initialization. Configuration defined in this way is immediately registered with the AuthConfigFactory . Any existing deployments using the Elytron security framework, that matches the layer and application-context , will immediately start making use of this configuration. Programmatic Configuration The APIs defined within the Jakarta Authentication specification allow for applications to dynamically register custom AuthConfigProvider instances. However, the specification does not provide the actual implementations to be used or any standard way to create instances of the implementations. The Elytron project contains a simple utility that deployments can use to help with this. The following code example demonstrates how to use this API to register a configuration similar to the one illustrated in the Subsystem Configuration above. String registrationId = org.wildfly.security.auth.jaspi.JaspiConfigurationBuilder.builder("HttpServlet", servletContext.getVirtualServerName() + " " + servletContext.getContextPath()) .addAuthModuleFactory(SimpleServerAuthModule::new, Flag.OPTIONAL, Collections.singletonMap("a", "b")) .addAuthModuleFactory(SecondServerAuthModule::new) .register(); As an example, this code could be executed within the init() method of a Servlet to register the AuthConfigProvider specific for that deployment. In this code example, the application context has also been assembled by consulting the ServletContext . The register() method returns the resulting registration ID that can also be used to subsequently remove this registration directly from the AuthConfigFactory . As with the Subsystem Configuration , this call also has an immediate effect and will be live for all web applications using the Elytron security framework. Authentication Process Based on the configuration of the application-security-domain resource in the undertow subsystem, the CallbackHandler passed to the ServerAuthModule can operate in either of the following modes: Integrated Mode Non-integrated Mode Integrated Mode When operating in the integrated mode, although the ServerAuthModule instances will be handling the actual authentication, the resulting identity will be loaded from the referenced SecurityDomain using the SecurityRealms referenced by that SecurityDomain . In this mode, it is still possible to override the roles that will be assigned within the servlet container. The advantage of this mode is that ServerAuthModules are able to take advantage of the Elytron configuration for the loading of identities, so that the identities stored in the usual locations, such as databases and LDAP, can be loaded without the ServerAuthModule needing to be aware of these locations. In addition, other Elytron configuration can be applied, such as role and permission mapping. The referenced SecurityDomain can also be referenced in other places, such as for SASL authentication or other non JASPI applications, all backed by a common repository of identities. Table 16.2. Operations of the CallbackHandlers method in the integrated mode. Operation Description PasswordValidationCallback The username and password will be used with the SecurityDomain to perform an authentication. If successful, there will be an authenticated identity. CallerPrincipalCallback This Callback is used to establish the authorized identity or the identity that will be available once the request reached the web application. Note If an authenticated identity has already been established via the PasswordValidationCallback , this Callback is interpreted as a run-as request. In this case, authorization checks are performed to ensure the authenticated identity is authorized to run as the identity specified in this Callback . If no authenticated identity has been established by a PasswordValidationCallback , it is assumed that the ServerAuthModule has handled the authentication step. If a Callback is received with a null Principal and name then: If an authenticated identity has already been established, authorization will be performed as that identity. If no identity has been established, authorization of the anonymous identity will be performed. Where authorization of the anonymous identity is performed, the SecurityDomain must have been configured to grant the anonymous identity the LoginPermission . GroupPrincipalCallback In this mode, the attribute loading, role decoding, and role mapping configured on the security domain are used to establish the identity. If this Callback is received, the groups specified are used to determine the roles that are assigned to the identity. The request will be in the servlet container and these roles are visible in the servlet container only. Non-Integrated Mode When operating in non-integrated mode, the ServerAuthModules are completely responsible for all authentication and identity management. The specified Callbacks can be used to establish an identity. The resulting identity will be created on the SecurityDomain but it will be independent of any identities stored in referenced SecurityRealms . The advantage of this mode is that JASPI configurations that are able to completely handle the identities can be deployed to the application server without requiring anything beyond a simple SecurityDomain definitions. There is no need for this SecurityDomain to actually contain the identities that will be used at runtime. The disadvantage of this mode is that the ServerAuthModule is now responsible for all identity handling, potentially making the implementation much more complex. Table 16.3. Operations of the CallbackHandlers method in the non-integrated mode. Operation Description PasswordValidationCallback The Callback is not supported in this mode. The purpose of this mode is for the ServerAuthModule to operate independently of the referenced SecurityDomain . Requesting a password to be validated would not be suitable. CallerPrincipalCallback This Callback is used to establish the Principal for the resulting identity. Because the ServerAuthModule is handling all of the identity checking requirements, no checks are performed to verify if the identity exists in the security domain and no authorization checks are performed. If a Callback is received with a null Principal and name, then the identity will be established as the anonymous identity. Because the ServerAuthModule is making the decisions, no authorization check will be performed with the SecurityDomain . GroupPrincipalCallback As the identity is created in this mode without loading from the SecurityDomain , it will by default have no roles assigned. If this Callback is received, the groups will be taken and assigned to the resulting identity while the request is in the servlet container. These roles will be visible in the servlet container only. validateRequest During the call to validateRequest on the ServerAuthContext , the individual ServerAuthModule instances will be called in the order in which they are defined. A control flag can also be specified for each module. This flag defines how the response should be interpreted and if processing should continue to the server authentication module or return immediately. Control Flags Whether the configuration is provided within the elytron subsystem or using the JaspiConfigurationBuilder API, it is possible to associate a control flag with each ServerAuthModule . If one is not specified, it defaults to REQUIRED . The flags have the following meanings depending on their result. Flag AuthStatus.SEND_SUCCESS AuthStatus.SEND_FAILURE, AuthStatus.SEND_CONTINUE Required Validation will continue to the remaining modules. Provided the requirements of the remaining modules are satisfied, the request will be allowed to proceed to authorization. Validation will continue to the remaining modules; however, regardless of their outcomes, the validation will not be successful and control will return to the client. Requisite Validation will continue to the remaining modules. Provided the requirements of the remaining modules are satisfied, the request will be allowed to proceed to authorization. The request will return immediately to the client. Sufficient Validation is deemed successful and complete, provided no Required or Requisite module has returned an AuthStatus other than AuthStatus.SUCCESS . The request will proceed to authorization of the secured resource. Validation will continue down the list of remaining modules. This status will only affect the decision if there are no REQUIRED or REQUISITE modules. Optional Validation will continue to the remaining modules, provided any Required or Requisite modules have not returned SUCCESS . This will be sufficient for validation to be deemed successful and for the request to proceed to the authorization stage and the secured resource. Validation will continue down the list of remaining modules. This status will only affect the decision if there are no REQUIRED or REQUISITE modules. Note For all ServerAuthModule instances, if they throw an AuthException , an error will be immediately reported to the client with no further module calls. secureResponse During the call to secureResponse , each ServerAuthModule is called, but this time in reverse order where a module only undertakes an action in secureResponse . If the module undertook an action in validateResponse , it is the responsibility of the module to track this. The control flag has no effect on secureResponse processing. Processing ends when one of the following is true: All of the ServerAuthModule instances have been called. A module returns AuthStatus.SEND_FAILURE . A module throws an AuthException . SecurityIdentity Creation Once the authentication process has completed, the org.wildfly.security.auth.server.SecurityIdentity for the deployment's SecurityDomain will have been created as a result of the Callbacks to the CallbackHandler . Depending on the Callbacks , this will either be an identity loaded directly from the SecurityDomain , or it will be an ad-hoc identity described by the callbacks. This SecurityIdentity will be associated with the request, in the same way it is done for other authentication mechanisms.

Commands:
<authentication-jaspi> <login-module-stack name="..."> <login-module code="..." flag="..."> <module-option name="..." value="..."/> </login-module> </login-module-stack> <auth-module code="..." login-module-stack-ref="..."> <module-option name="..." value="..."/> </auth-module> </authentication-jaspi>
/subsystem=undertow/application-security-domain=MyAppSecurity:add(security-domain=ApplicationDomain)
/subsystem=undertow/application-security-domain=MyAppSecurity:add(http-authentication-factory=application-http-authentication)
/subsystem=elytron/jaspi-configuration=simple-configuration:add(layer=HttpServlet, application-context="default-host /webctx", description="Elytron Test Configuration", server-auth-modules=[{class-name=org.wildfly.security.examples.jaspi.SimpleServerAuthModule, module=org.wildfly.security.examples.jaspi, flag=OPTIONAL, options={a=b, c=d}}, {class-name=org.wildfly.security.examples.jaspi.SecondServerAuthModule, module=org.wildfly.security.examples.jaspi}])
<jaspi> <jaspi-configuration name="simple-configuration" layer="HttpServlet" application-context="default-host /webctx" description="Elytron Test Configuration"> <server-auth-modules> <server-auth-module class-name="org.wildfly.security.examples.jaspi.SimpleServerAuthModule" module="org.wildfly.security.examples.jaspi" flag="OPTIONAL"> <options> <property name="a" value="b"/> <property name="c" value="d"/> </options> </server-auth-module> <server-auth-module class-name="org.wildfly.security.examples.jaspi.SecondServerAuthModule" module="org.wildfly.security.examples.jaspi"/> </server-auth-modules> </jaspi-configuration> </jaspi>
String registrationId = org.wildfly.security.auth.jaspi.JaspiConfigurationBuilder.builder("HttpServlet", servletContext.getVirtualServerName() + " " + servletContext.getContextPath()) .addAuthModuleFactory(SimpleServerAuthModule::new, Flag.OPTIONAL, Collections.singletonMap("a", "b")) .addAuthModuleFactory(SecondServerAuthModule::new) .register();