Chapter 3. Additional Features 3.1. Adding a FORM Login as a Fallback JBoss EAP and applications deployed to it can also configure a FORM login authentication mechanism to use as a fallback. This allows applications to present a login page for authentication in cases where Kerberos/SPNEGO tokens are not present. This authentication happens independent of the Kerberos authentication. As a result, depending on how the FORM login fallback is configured, users may require separate credentials to authenticate by this method. Note The fallback to FORM login is available when no SPNEGO or NTLM tokens are present or, when a SPNEGO token is present, but from another KDC. 3.1.1. Update Your Application The following steps are required to configure your application for FORM login as a fallback: Configure JBoss EAP and the web application to use Kerberos and SPNEGO. See How to Set Up SSO for JBoss EAP with Kerberos for the steps required to configure JBoss EAP and web applications to use Kerberos and SPNEGO for authentication and authorization.  Add the login and error pages. To use FORM login, a login and error page are required. These files are added to web application and are used in the authentication process. Example: login.jsp File <html> <head></head> <body> <form id="login_form" name="login_form" method="post" action="j_security_check" enctype="application/x-www-form-urlencoded"> <center> <p>Please login to proceed.</p> </center> <div style="margin-left: 15px;"> <p> <label for="username">Username</label> <br /> <input id="username" type="text" name="j_username"/> </p> <p> <label for="password">Password</label> <br /> <input id="password" type="password" name="j_password" value=""/> </p> <center> <input id="submit" type="submit" name="submit" value="Login"/> </center> </div> </form> </body> </html> Example: error.jsp File <html> <head></head> <body> <p>Login failed, please go back and try again.</p> </body> </html> Modify the web.xml . After adding the login and error pages to the web application, the web.xml must be updated to use these files for FORM login. The exact value FORM must be added to the <auth-method> element. Since <auth-method> expects a comma-separated list and order is significant, the exact value for <auth-method> must be updated to SPNEGO,FORM . In addition, a <form-login-config> element must be added to <login-config> and the paths to the login and error pages specified as <form-login-page> and <form-error-page> elements. Example: Updated web.xml File <web-app> <display-name>App1</display-name> <description>App1</description> <!-- Define a security constraint that requires the Admin role to access resources --> <security-constraint> <display-name>Security Constraint on Conversation</display-name> <web-resource-collection> <web-resource-name>examplesWebApp</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Admin</role-name> </auth-constraint> </security-constraint> <!-- Define the Login Configuration for this Application --> <login-config> <auth-method>SPNEGO,FORM</auth-method> <realm-name>SPNEGO</realm-name> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/error.jsp</form-error-page> </form-login-config> </login-config> <!-- Security roles referenced by this web application --> <security-role> <description> role required to log in to the Application</description> <role-name>Admin</role-name> </security-role> </web-app> 3.1.2. Update the Elytron Subsystem Add a mechanism for FORM authentication in the http-authentication-factory . You can use the existing http-authentication-factory you configured for kerberos-based authentication and an additional mechanism for FORM authentication. Add additional fallback principals. The existing configuration for kerberos-based authentication should already have a security realm configured for mapping principals from kerberos token to roles for the application. You can add additional users for fallback authentication to that realm. For example if you used a filesystem-realm , you can simply create a new user with the appropriate roles: 3.1.3. Update the Legacy Security Subsystem If you are using the legacy security subsystem in JBoss EAP, you must update the security domain for fallback authentication. The web application security domain must be configured to support a fallback login mechanism. This requires the following steps: Add a new security domain to serve as a fallback authentication method. Add a usernamePasswordDomain module option to the web application security domain that points to the fallback domain. Example: Security Domain Configured with a Fallback Security Domain 3.2. Securing the Management Interfaces with Kerberos In addition to providing Kerberos authentication in security domains, JBoss EAP also provides the ability to secure the management interfaces using Kerberos. 3.2.1. Secure the Management Interfaces with Kerberos Using Elytron To configure Kerberos authentication for the HTTP management interface: Follow the same instructions for configuring Kerberos authentication for applications to create an http-authentication-factory that does Kerberos authentication. Important When configuring Kerberos authentication with the management interfaces, it is very important that you pay close attention to the service principal you configure for JBoss EAP to authenticate against the KDC. This service principal takes the form of service-name/hostname . JBoss EAP expects HTTP to be the service name, for example HTTP/localhost , when authenticating against the web-based management console and remote to be the service name, for example remote/localhost , for the management CLI. Update the management HTTP interface to use the http-authentication-factory . To configure Kerberos authentication for SASL authentication for the management CLI: Follow the same instructions for configuring Kerberos authentication for applications to create a security domain and kerberos-security-factory . Add GSSAPI to the configurable-sasl-server-factory . Create a sasl-authentication-factory that uses the security domain and kerberos-security-factory . Example: sasl-authentication-factory Update the management SASL interface to use the sasl-authentication-factory . Example: Update sasl-authentication-factory 3.2.2. Secure the Management Interfaces With Kerberos Using Legacy Core Management Authentication To enable Kerberos authentication on the management interfaces using legacy core management authentication, the following steps must be performed: Note The management CLI commands shown assume that you are running a JBoss EAP standalone server. For more details on using the management CLI for a JBoss EAP managed domain, see the JBoss EAP Management CLI Guide . Enable the relevant system properties. As discussed in a section , enable any needed JBoss EAP system properties for connecting to the Kerberos server. Add the Kerberos server identity to the security realm. Before Kerberos authentication can be used in a security realm, a connection to a Kerberos server must be added. The following example shows how to add a Kerberos server identity to the existing Management Realm. You will need to replace service-name , hostname , and MY-REALM with the appropriate values. Example CLI for Adding a Server Identity to a Security Realm Important When configuring Kerberos authentication with the management interfaces, it is very important that you pay close attention to the service principal you configure for JBoss EAP to authenticate against the KDC. This service principal takes the form of service-name/hostname . JBoss EAP expects HTTP to be the service name, for example HTTP/localhost , when authenticating against the web-based management console and remote to be the service name, for example remote/localhost , for the management CLI. Update the authentication method in the security realm. Once the Kerberos server identity has been properly configured, the authentication method in the security realm needs to be updated to use it. Example: Adding Kerberos Authentication to a Security Realm Important Based on the order in which you have the authentication mechanisms defined in the security realm, JBoss EAP will attempt to authenticate the user in that order when accessing the management interfaces. Secure both interfaces with Kerberos. In cases where you would like to secure both the web-based management console and management CLI with Kerberos, you need a Kerberos server identity configured for each. To add an additional identity, use the following command. 3.2.3. Connecting to the Management Interface Before attempting to connect to the management interfaces, you need to have a valid Kerberos ticket. If the security realm fails to authenticate a user via Kerberos, when using the legacy security solution, it will attempt to authenticate the user using any of the subsequent methods specified in the <authentication> element. The elytron subsystem behaves similar to the legacy security solution. If the Kerberos authentication mechanism fails, authentication falls back to any other mechanism that you have defined in the authentication factory that is protecting the management interface. Usually, DIGEST or BASIC is used as a fallback. When you connect to the web-based management console using a browser, the security realm will attempt to authenticate you based on that ticket. When connecting to the management CLI, you will need to use the -Djavax.security.auth.useSubjectCredsOnly=false parameter, as this allows the GSSAPI implementation to make use of the identity managed at the operating system level. You may also need to use the following parameters based on how your environment is set up: -Djava.security.krb5.realm= REALM_NAME Specifies the realm name. -Djava.security.krb5.kdc= KDC_HOSTNAME Specifies the location of the KDC. --no-local-auth Disables local authentication. This is useful if you are attempting to connect to a JBoss EAP instance running on the same machine you are running the script from. Example Command Warning If an HTTP proxy is used between the client and server, it must take care to not share authenticated connections between different authenticated clients to the same server. If this is not honored, then the server can easily lose track of security context associations. A proxy that correctly honors client to server authentication integrity will supply the Proxy-support: Session- Based-Authentication HTTP header to the client in HTTP responses from the proxy. The client must not utilize the SPNEGO HTTP authentication mechanism through a proxy unless the proxy supplies this header with the 401 Unauthorized response from the server. 3.3. Kerberos Authentication Integration for Remoting In addition to using Kerberos for securing the management interfaces and web applications, you can also configure Kerberos authentication for services accessed via remoting, such as Jakarta Enterprise Beans. System properties for Kerberos also need to be configured. For more information, see Configure the Elytron Subsystem . 3.3.1. Kerberos Authentication Integration Using Legacy Security Realms To configure Kerberos authentication, you will need to do the following: Configure a security domain with remoting and RealmDirect You need to configure a security domain for use by the service that is accessed by remoting. This security domain needs to make use of both the Remoting login module as well as a RealmDirect login module, such as RealmDirect or RealmUsersRoles . Essentially, it should look very similar to the other security domain provided by default. For more details on the specific configuration options of each login module, see the JBoss EAP Login Module Reference . Example: Security Domain with Remoting and RealmDirect Login Modules Configure a security realm for Kerberos authentication. Setting up a security realm with Kerberos authentication is covered in the Securing the Management Interfaces with Kerberos section. Example: Security Realm Configure the HTTP connector in the remoting subsystem. In addition, you will need to configure the HTTP connector in the remoting subsystem to use the newly created security realm. Example: Remoting Subsystem Configure security for the service. You must also set up the service that is accessed using the remoting interface to secured . This will vary depending on the service. For example, with a Jakarta Enterprise Beans, you can use the @SecurityDomain and @RolesAllowed annotations. 3.3.2. Kerberos Authentication Integration Using Elytron It is possible to define an Elytron security domain for Kerberos or GSSAPI SASL authentication for remoting authentication. Define the security realm to load the identity from. It is used for assigning roles. Define the Kerberos security factory for the server's identity. Define the security domain and along with it, a SASL authentication factory. Use the created sasl-authentication-factory , in the remoting subsystem, to enable it for remoting. Example CLI Command Configure security for the service. If you reference the security domain in a Jakarta Enterprise Beans, you must specify the application-security-domain that maps to the Elytron security domain. For example, with a Jakarta Enterprise Beans, you can use the @SecurityDomain annotation. Example CLI Command The use of a Jakarta Authentication Subject for identity association is no longer supported. Clients wishing to programmatically manage the Kerberos identity for a Jakarta Enterprise Beans call should migrate and use the AuthenticationConfiguration APIs directly, as follows: // create your authentication configuration AuthenticationConfiguration configuration = AuthenticationConfiguration.empty() .useProvidersFromClassLoader(SecuredGSSCredentialClient.class.getClassLoader()) .useGSSCredential(getGSSCredential()); // create your authentication context AuthenticationContext context = AuthenticationContext.empty().with(MatchRule.ALL, configuration); // create a callable that looks up an Jakarta Enterprise Bean and invokes a method on it Callable<Void> callable = () -> { ... }; // use your authentication context to run your callable context.runCallable(callable); The call to useGSSCredential(getGSSCredential()) happens when creating the AuthenticationConfiguration . Client code that already has access to a Jakarta Authentication Subject can easily be converted to obtain the GSSCredential as follows: private GSSCredential getGSSCredential() { return Subject.doAs(subject, new PrivilegedAction<GSSCredential>() { public GSSCredential run() { try { GSSManager gssManager = GSSManager.getInstance(); return gssManager.createCredential(GSSCredential.INITIATE_ONLY); } catch (Exception e) { e.printStackTrace(); } return null; } }); } Revised on 2024-01-17 05:25:11 UTC

Commands:
<html> <head></head> <body> <form id="login_form" name="login_form" method="post" action="j_security_check" enctype="application/x-www-form-urlencoded"> <center> <p>Please login to proceed.</p> </center> <div style="margin-left: 15px;"> <p> <label for="username">Username</label> <br /> <input id="username" type="text" name="j_username"/> </p> <p> <label for="password">Password</label> <br /> <input id="password" type="password" name="j_password" value=""/> </p> <center> <input id="submit" type="submit" name="submit" value="Login"/> </center> </div> </form> </body> </html>
<html> <head></head> <body> <p>Login failed, please go back and try again.</p> </body> </html>
<web-app> <display-name>App1</display-name> <description>App1</description> <!-- Define a security constraint that requires the Admin role to access resources --> <security-constraint> <display-name>Security Constraint on Conversation</display-name> <web-resource-collection> <web-resource-name>examplesWebApp</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Admin</role-name> </auth-constraint> </security-constraint> <!-- Define the Login Configuration for this Application --> <login-config> <auth-method>SPNEGO,FORM</auth-method> <realm-name>SPNEGO</realm-name> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/error.jsp</form-error-page> </form-login-config> </login-config> <!-- Security roles referenced by this web application --> <security-role> <description> role required to log in to the Application</description> <role-name>Admin</role-name> </security-role> </web-app>
/subsystem=elytron/http-authentication-factory=example-krb-http-auth:list-add(name=mechanism-configurations, value={mechanism-name=FORM})
/subsystem=elytron/filesystem-realm=exampleFsRealm:add-identity(identity=fallbackUser1) /subsystem=elytron/filesystem-realm=exampleFsRealm:set-password(identity=fallbackUser1, clear={password="password123"}) /subsystem=elytron/filesystem-realm=exampleFsRealm:add-identity-attribute(identity=fallbackUser1, name=Roles, value=["Admin","Guest"])
/subsystem=security/security-domain=app-fallback:add(cache-type=default) /subsystem=security/security-domain=app-fallback/authentication=classic:add() /subsystem=security/security-domain=app-fallback/authentication=classic/login-module=UsersRoles:add(code=UsersRoles, flag=required, module-options=[usersProperties="file:USD{jboss.server.config.dir}/fallback-users.properties", rolesProperties="file:USD{jboss.server.config.dir}/fallback-roles.properties"]) /subsystem=security/security-domain=app-spnego/authentication=classic/login-module=SPNEGO:add(code=SPNEGO, flag=required, module-options=[serverSecurityDomain=host]) /subsystem=security/security-domain=app-spnego/authentication=classic/login-module=SPNEGO:map-put(name=module-options, key=usernamePasswordDomain, value=app-fallback) /subsystem=security/security-domain=app-spnego/authentication=classic/login-module=SPNEGO:map-put(name=module-options, key=password-stacking, value=useFirstPass) reload
/core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory, value=example-krb-http-auth)
/subsystem=elytron/configurable-sasl-server-factory=configured:list-add(name=filters, value={pattern-filter=GSSAPI})
/subsystem=elytron/sasl-authentication-factory=example-sasl-auth:add(sasl-server-factory=configured, security-domain=exampleFsSD, mechanism-configurations=[{mechanism-name=GSSAPI, mechanism-realm-configurations=[{realm-name=exampleFsSD}], credential-security-factory=krbSF}])
/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade.sasl-authentication-factory, value=example-sasl-auth) reload
/core-service=management/security-realm=ManagementRealm/server-identity=kerberos:add() /core-service=management/security-realm=ManagementRealm/server-identity=kerberos/keytab=service-name\/hostname@MY-REALM:add(path=/home\/username\/service.keytab, debug=true) reload
/core-service=management/security-realm=ManagementRealm/authentication=kerberos:add() reload
/core-service=management/security-realm=ManagementRealm/server-identity=kerberos/keytab=remote\/hostname@MY-REALM:add(path=/home\/username\/remote.keytab, debug=true) reload
EAP_HOME /bin/jboss-cli.sh -c -Djavax.security.auth.useSubjectCredsOnly=false --no-local-auth
/subsystem=security/security-domain=krb-remoting-domain:add() /subsystem=security/security-domain=krb-remoting-domain/authentication=classic:add() /subsystem=security/security-domain=krb-remoting-domain/authentication=classic/login-module=Remoting:add(code=Remoting, flag=optional, module-options=[password-stacking=useFirstPass]) /subsystem=security/security-domain=krb-remoting-domain/authentication=classic/login-module=RealmDirect:add(code=RealmDirect, flag=required, module-options=[password-stacking=useFirstPass, realm=krbRealm]) /subsystem=security/security-domain=krb-remoting-domain/mapping=classic:add() /subsystem=security/security-domain=krb-remoting-domain/mapping=classic/mapping-module=SimpleRoles:add(code=SimpleRoles, type=role, module-options=["testUser"="testRole"]) reload
/core-service=management/security-realm=krbRealm:add() /core-service=management/security-realm=krbRealm/server-identity=kerberos:add() /core-service=management/security-realm=krbRealm/server-identity=kerberos/keytab=remote\/localhost@JBOSS.ORG:add(path=\/path\/to\/remote.keytab, debug=true) /core-service=management/security-realm=krbRealm/authentication=kerberos:add(remove-realm=true) reload
/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=security-realm, value=krbRealm)
/path=kerberos:add(relative-to=user.home, path=src/kerberos) /subsystem=elytron/properties-realm=kerberos-properties:add(users-properties={path=kerberos-users.properties, relative-to=kerberos, digest-realm-name=ELYTRON.ORG}, groups-properties={path=kerberos-groups.properties, relative-to=kerberos})
/subsystem=elytron/kerberos-security-factory=test-server:add(relative-to=kerberos, path=remote-test-server.keytab, principal=remote/test-server.elytron.org@ELYTRON.ORG)
/subsystem=elytron/security-domain=KerberosDomain:add(default-realm=kerberos-properties, realms=[{realm=kerberos-properties, role-decoder=groups-to-roles}], permission-mapper=default-permission-mapper) /subsystem=elytron/sasl-authentication-factory=gssapi-authentication-factory:add(security-domain=KerberosDomain, sasl-server-factory=elytron, mechanism-configurations=[{mechanism-name=GSSAPI, credential-security-factory=test-server}])
/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory, value=gssapi-authentication-factory)
/subsystem=ejb3/application-security-domain=KerberosDomain:add(security-domain=KerberosDomain)
// create your authentication configuration AuthenticationConfiguration configuration = AuthenticationConfiguration.empty() .useProvidersFromClassLoader(SecuredGSSCredentialClient.class.getClassLoader()) .useGSSCredential(getGSSCredential()); // create your authentication context AuthenticationContext context = AuthenticationContext.empty().with(MatchRule.ALL, configuration); // create a callable that looks up an Jakarta Enterprise Bean and invokes a method on it Callable<Void> callable = () -> { }; // use your authentication context to run your callable context.runCallable(callable);
private GSSCredential getGSSCredential() { return Subject.doAs(subject, new PrivilegedAction<GSSCredential>() { public GSSCredential run() { try { GSSManager gssManager = GSSManager.getInstance(); return gssManager.createCredential(GSSCredential.INITIATE_ONLY); } catch (Exception e) { e.printStackTrace(); } return null; } }); }