I would like to know if it is possible to make an additional query from the wildfly level after correct authentication and authorization. After logging in correctly to the database, I need to add an information record to the database (SQL) about the login date. Is it possible to do this from the xml level?
(I'm using wildfly 17, the configuration works below)
<authentication>
<login-module code="LdapExtended" flag="required">
<module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<module-option name="java.naming.security.protocol" value="ssl"/>
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="java.naming.security.authentication" value="simple"/>
<module-option name="java.naming.provider.url" value="ldaps://xxx.xxx.xxx:636"/>
<module-option name="bindDN" value="cn=xxx,dc=xxx,dc=xxx"/>
<module-option name="bindCredential" value="xxx"/>
<module-option name="baseCtxDN" value="ou=xxx,dc=xxx,dc=xxx"/>
<module-option name="baseFilter" value="(uid={0})"/>
<module-option name="roleAttributeID" value="cn"/>
<module-option name="searchScope" value="SUBTREE_SCOPE"/>
<module-option name="allowEmptyPasswords" value="true"/>
<module-option name="defaultRole" value="xxx"/>
</login-module>
<login-module code="Database" flag="required">
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="dsJndiName" value="java:/xxxJNDI"/>
<module-option name="rolesQuery" value="query for roles)"/>
</login-module>
</authentication>
You can't configure it from within the PicketBox (old security module of JBoss/Wildfly) Database LoginModule. You will have to write your own custom LoginModule (see e.g. here: http://www.mastertheboss.com/jboss-server/jboss-security/creating-a-custom-jboss-login-module)
Maybe it is also an opportunity to migrate to the new security module Elytron which no longer provides LoginModules but supports a jdbc-realm where you can directly query against a DB. (see here https://docs.jboss.org/author/display/WFLY/Database+Authentication+Migration)
Related
I have password encrypted by Argon2id in database.
How can I change my configuration to let JBoss know that it have to use Argon2 to verify password?
standalone.xml
<security-domain name="databaseDomain">
<authentication>
<login-module code="Database" flag="required">
<module-option name="dsJndiName" value="java:/datasources/hotel"/>
<module-option name="principalsQuery" value="select password from users where login=?"/>
<module-option name="rolesQuery" value="SELECT employee.position,'Roles' FROM users, employee WHERE employee.id=users.employeeId and login=?"/>
<module-option name="unauthenticatedIdentity" value="guest"/>
</login-module>
</authentication>
</security-domain>
web.xml
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
jboss-web.xml
<jboss-web>
<security-domain>databaseDomain</security-domain>
</jboss-web>
I added ARGON2 with
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>2.7</version>
</dependency>
I tried adding to standalone.xml
<module-option name="hashAlgorithm" value="ARGON2id"/>
but it didn't work and I wasn't that suprised about this. My form is calling to j_security_check
You need to implement your own login module, sounds scary, but actually it's not.
Find out which version of Picketbox you're Wildfly is bundled with - look in the modules/system/layers/base/org/picketbox/main directory. I.e. for WF 21 the version of Picketbox is 5.0.3.Final
Add the Picketbox library as a provided-scoped dependency to your project
Implement your custom login module by extending the org.jboss.security.auth.spi.DatabaseServerLoginModule class and overriding the convertRawPassword method - this is where you need to convert the user's input into the Argon2 form
Provide the full class name in the code parameter in your login module configuration in standalone.xml. Wildfly will pick it from your deployment and use your implementation instead of the default one.
This should work.
Perhaps I could ask you if you guys if you could help me out how to configure JBoss 6 with a custom auth-method?
We are moving from JBoss 5 to JBoss 6.
In 5 we got a web.xml with this login-tag
<login-config>
<auth-method>OURSSO</auth-method>
<realm-name>oursso</realm-name>
</login-config>
And a jboss-app.xml
<security-domain>oursso</security-domain>
And in login-config.xml
<application-policy name="oursso">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="sufficient">
<module-option name="usersProperties">props/mycomp-users.properties</module-option>
<module-option name="rolesProperties">props/mycomp-roles.properties</module-option>
<module-option name="unauthenticatedIdentity">anonymous</module-option>
</login-module>
<login-module code="rsa.ps.ct.jboss.jaas.OURSSOServerLoginModule" flag="required">
<module-option name="connectionProvider">rsa.access.manager:type=Service,name=RuntimeAPIClient</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.RoleMappingLoginModule" flag="optional">
<module-option name="rolesProperties">props/mycomp-rolemapping-roles.properties</module-option>
<module-option name="replaceRole">true</module-option>
</login-module>
</authentication>
</application-policy>
And in war-deployers-jboss-beans.xml
<property name="authenticators">
<map class="java.util.Properties" keyClass="java.lang.String" valueClass="java.lang.String">
<entry>
<key>BASIC</key>
<value>org.apache.catalina.authenticator.BasicAuthenticator</value>
</entry>
...
<entry>
<key>OURSSO</key>
<value>com.mycomp.OurssoAuthenticator</value>
</entry>
</map>
</property>
It seems like the auth-method in web.xml must match a key in war-deployers-jboss-beans.xml. How is the same accomplish in JBoss 6?
Best regards
Fredrik
I added these to my standalone-full.xml
<security-domain name="my-security-domain" cache-type="default">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
<module-option name="usersProperties" value="file://${jboss.server.config.dir}/users.properties"/>
<module-option name="rolesProperties" value="file://${jboss.server.config.dir}/roles.properties"/>
</login-module>
</authentication>
</security-domain>
In the file users.properties
123=qwe
456=asd
In the file roles.properties
123=role.A,role.B
456=role.B
In one of my beans in the server I annotate it with
#Stateless
#SecurityDomain("my-security-domain")
#RolesAllowed("role.A")
public class SecureStatelessBean extends SecureReturnAString implements SecureStatelessBeanLocal, SecureStatelessBeanRemote
{
...
In my web-application (running in the same server) I lookup the bean and login with this code
#EJB(lookup = "java:global/ejbtest-app/ejbtest-server-0.0.1-SNAPSHOT/SecureStatelessBean!se.albinoni.ejbtest.stateless.SecureStatelessBeanRemote")
private SecureStatelessBeanRemote secureStatelessBeanRemote;
...
private static SecurityClient getClientLogin() throws Exception
{
final SecurityClient client = SecurityClientFactory.getSecurityClient();
client.setSimple("123", "qwe");
return client;
}
...
SecurityClient client = getClientLogin();
client.login();
secureStatelessBeanRemote.someMethod();
Think that was it.
But I still have not found out how to do the same from a remote standalone app.
I have two groups of users - employees and members, employees are in LDAP server and members are in properties file. I need to configure both of them in a single security domain, which means I need to get authentication from different login modules - employees from LdapExtLoginModule, and, members from UsersRoles login module. Something like this:
<security-domain name="EmpMem" cache-type="default">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="usersProperties" value="app-users.properties"/>
<module-option name="rolesProperties" value="app-roles.properties"/>
</login-module>
<login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required">
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="java.naming.provider.url" value="ldap://ha-adds-global.xxx.com:3268"/>
<module-option name="bindDN" value="CN=prodjbsvc,OU=ServiceAccounts,OU=NOPOL,dc=eagle,dc=xxx,dc=com"/>
<module-option name="bindCredential" value="XQtU#1lc"/>
<module-option name="baseCtxDN" value="dc=eagle,dc=xxx,dc=com"/>
<module-option name="baseFilter" value="(sAMAccountName={0})"/>
<module-option name="rolesCtxDN" value="ou=COSAs,dc=eagle,dc=xxx,dc=com"/>
<module-option name="roleFilter" value="(sAMAccountName={0})"/>
<module-option name="roleAttributeID" value="memberOf"/>
<module-option name="roleAttributeIsDN" value="true"/>
<module-option name="roleNameAttributeID" value="cn"/>
<module-option name="roleRecursion" value="-1"/>
<module-option name="searchScope" value="SUBTREE_SCOPE"/>
<module-option name="allowEmptyPasswords" value="false"/>
<module-option name="java.naming.referral" value="follow"/>
</login-module>
</authentication>
</security-domain>
I know that there is a login module called Password Stacking which can chain multiple login modules together, but looks like LdapExtLoginModule doesn't support that? Please suggest a way to accomplish this.
My Requirement:
When the user is employee, he gets authenticated from LDAP server and should be able to to access employee resources (java packages/classes)only, and when the user is member, he gets authenticated from properties file and should be able to access member resources (java packages/classes) only.
If sufficient for your needs use LdapLoginModule instead of LdapExtLoginModule.
Password Stacking is supported by that LoginModule.
However, judging by your Requirement I don't think Password Stacking is what you're looking for ...
If a previous module configured for password stacking has authenticated the user, all the other stacking modules will consider the user authenticated and only attempt to provide a set of roles for the authorization step.
Seems like a User will either be a employee or a member? If so, use "sufficient" as the LoginModule "flag" attribute
sufficient : The login module is not required to succeed. If it does succeed, control immediately returns to the application. If it fails, authentication continues down the login stack.
I have some strange behaviour, and I am not sure why. I have two apps that work well in Tomcat 7, but do not behave correctly in Wildfly 8.2 and 9Beta2.
In Tomcat, I can log in on one app, go to the 2nd app and I can see my login state is correct, log out in the 2nd app, return to the 1st app, and I am logged out there. This is correct.
In Tomcat, I can log in on one app, go to the 2nd app and I can see my login state is correct, return to the 1st app, log out in the 1st app, return to the 2nd app, and I am logged out there. This is correct.
In Wildfly, I log in to the 1st app, go to the 2nd app and I can see my login state is correct, log out of the 2nd app, return to the 1st app, but I am still logged in. Incorrect.
In Wildfly, I log in to the 1st app, go to the 2nd app and I can see my login state is correct, return to the 1st app, log out of the 1st app, go to the 2nd app, and I am logged out there as well. Correct.
Why does Wildfly fail the first test (3. above)?
Any pointers would be greatly appreciated.
Here are some of the extracts from my files:
From standalone.xml
<security-realm name="DataSourceRealm">
<authentication>
<jaas name="app"/>
</authentication>
</security-realm>
<security-domain name="app" cache-type="default">
<authentication>
<login-module code="Database" flag="requisite">
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="dsJndiName" value="jdbc/icedb"/>
<module-option name="principalsQuery" value="select PASSWORD from WSV_USR_PRFL_DEF where USR_PRFL_DEF_ID=?"/>
<module-option name="rolesQuery" value="select USR_GRP_DEF_ID, 'Roles' from WSV_USR_GRP_MAP where USR_PRFL_DEF_ID = ?"/>
<module-option name="unauthenticatedIdentity" value="guest"/>
</login-module>
<login-module code="RoleMapping" flag="requisite">
<module-option name="rolesProperties" value="file:${jboss.server.config.dir}/app.properties"/>
<module-option name="replaceRole" value="false"/>
</login-module>
</authentication>
</security-domain>
<subsystem xmlns="urn:jboss:domain:undertow:2.0">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http"/>
<host name="default-host" alias="localhost">
<single-sign-on path="/"/>
.....
from the various applications (WAR) jboss-web.xml:
<jboss-web>
<context-root>/APPNAME</context-root>
<security-domain flushOnSessionInvalidation="true">app</security-domain>
</jboss-web>
From my logout.java:
#WebServlet(name="logout", urlPatterns={"/lo.xhtml"}, loadOnStartup=2)
public class Logout extends HttpServlet{
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if (request.getSession(false) != null) {
HttpSession ses = request.getSession(false);
ses.invalidate(); // remove session.
}
request.logout();
response.sendRedirect(request.getContextPath());
}
}
I've set up a login-module in my JBoss 7.1 server using LDAP like that:
<login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required">
<module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<module-option name="java.naming.provider.url" value="ldap://ldap.domain.com:port"/>
<module-option name="java.naming.security.authentication" value="simple"/>
<module-option name="principalDNPrefix" value="uid="/>
<module-option name="principalDNSuffix" value=",ou=peoples,dc=domain,dc=com"/>
<module-option name="searchTimeLimit" value="5000"/>
<module-option name="searchScope" value="ONELEVEL"/>
</login-module>
But, sometimes, this LDAP server maintained by my company crashes and I like to specify an alternative LDAP server (who exists) in my configuration.
Is that possible?
Thanks
You may be able to use a space separated list:
ie:
<module-option name="java.naming.provider.url" value="ldap://ldap.domain.com:port ldap://ldap2.domain.com:port"/>
See: JNDI LDAP & LDAPS URLs
Consider using an LDAP Directory Proxy Server to manage the high-availability of the LDAP service. This method removes the dependency of the application server requiring knowledge of more than one specific IP address or hostname - resulting in a simpler configuration that is easier to use, maintain, and operate.