Wildfly 8 not finding MyLoginModule - authentication

I realized my implementation of Loginmodule. Installed into WildFly 8.2.0.Final as module. Configure Security Domain.
add jboss-web.xml into my WebApplication in WEB-INF directory, with name of security-domain.
And when I initiate login at web form, I had this error in wildfly:
PBOX000206: Login failure: javax.security.auth.login.LoginException: unable to find LoginModule class: my.webapp.auth.WildLoginModule from [Module "deployment.MyWebApp.war:main" from Service Module Loader]
Why it cannot find my class? when this class resides in jar in wildfly modules.
What is more strange, it woks a couple weeks ago!

At last I've found my answer. I thought mistake should be in configuration of Wildfly, after long reserch and many ways of testing, I've found that my implementation of LoginModule works only if it resides in my WebApplication. But I wanted a separate module, I wanted my WebApp clean from Security realization.
So this is why 'it woks a couple weeks ago!', cause this loginModule was inside my webapp.
Steps to use you own JAAS loginModule:
By the way, this resource JBoss AS7 helped me a lot in my situation
Implement your own Principals, Login module (how to do this you may find in i-net)
Pack this to jar
Install like module into Wildfly (if you need to use it in many projects)
Using CLI install jar as module
hint from resource
Things to remember
When you create your own module, do not forget to add dependency on "org.picketbox" and "javax.api" in the module.xml of your custom module.
module add --name=my.security.module --resources=/path/to/MyLoginModule.jar --dependencies=javax.api,org.picketbox,my.dependencies
Add Security Domain in Wildfly (GUI, CLI or manual edition standalone.xml)
And my mistake was at this step. My sec.domain looks like this:
<security-domain name="mysecdomain" cache-type="default">
<authentication>
<login-module code="my.code.MyLoginModule" flag="required">
<module-option name="jndiDb" value="java:/datasources/myDataSource"/>
<module-option name="userQuery" value=""/>
<module-option name="roleQuery" value=""/>
</login-module>
</authentication>
</security-domain>
This is why it couldn't find my code, it doesn't know in what module to find my code. So this part of standalone.xml should look like this:
<security-domain name="mysecdomain" cache-type="default">
<authentication>
<login-module code="my.code.MyLoginModule" flag="required" ___module="my.security.module"___ >
<module-option name="jndiDb" value="java:/datasources/myDataSource"/>
<module-option name="userQuery" value=""/>
<module-option name="roleQuery" value=""/>
</login-module>
</authentication>
</security-domain>
I didn't configure, or I missed some params in CLI for this param, but this module="my.security.module" should be in your config.
After that my webapp could make login and use this security module.

Related

HTTP basic authentication for JAX-RS without web.xml

I'm implementing a REST service within an EJB-JAR within an EAR running on the JBoss EAP 7.1.
The unsecured version of the service works fine, but adding even basic HTTP-authentication turned out to be a challenge, since within an EJB-JAR I found no way to specify any required web.xml-entries, like <auth-method>BASIC</auth-method>
So my question is:
How can I configure JAX-RS to use HTTP authentication within an EJB-JAR?
Additional information:
To make things simpler I use default ManagementRealm like this
<security-domain name="my-security-domain" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="RealmDirect" flag="required">
<module-option name="realm" value="ManagementRealm"/>
</login-module>
</authentication>
</security-domain>
In EJB-jar:
#Stateless
#Path("/my-rest")
#SecurityDomain(value = "my-security-domain")
#DenyAll
public class MyRestStatelessBean {
#PUT
#RolesAllowed("admin")
#Path("/doAdminStuff")
public void doAdminStuff() {
// Implementation
}
}
The solution was to use the Proactive authentication feature of the Undertow, that is actually ON by default. Specifying HTTP-BASIC-Authentication header within the request, makes Undertow to try to login the user even through my REST service due to missing web.xml doesn't require any type of authentication.
My complete configuration (using Management JBoss users from mgmt-users.properties):
# Define my security domain
/subsystem=security/security-domain=MY-SECURITY-DOMAIN:add(cache-type=default)
# Link Untertow to Elytron for authentication
/subsystem=undertow/application-security-domain=MY-SECURITY-DOMAIN:add( \
http-authentication-factory="management-http-authentication" \
)
# Add BASIC-HTTP-Authentication support to Elytron
/subsystem=elytron/http-authentication-factory=management-http-authentication:list-add( \
name=mechanism-configurations, \
value={mechanism-name="BASIC", \
mechanism-realm-configurations=[{realm-name="ManagementRealm"}] \
} \
)
# Not sure, why is this required...
/subsystem=ejb3/application-security-domain=MY-SECURITY-DOMAIN:add( \
security-domain="ManagementDomain")

Wildfly 17 Elytron: server side authentication with classes from EAR

We plan to migrate from Picketbox to Elytron and face the following problem:
With Picketbox a custom login module can use functionality of (or even can reside in) a deployment module (e.g. an EAR in wildfly/standalone/deployments) to implement authentication on the server side:
<subsystem xmlns="urn:jboss:domain:security:2.0">
<security-domains>
...
<security-domain name="MyDomain" cache-type="default">
<authentication>
<login-module name="MyLoginModule" code="de.example.wildfly.MyLoginModule" flag="required" module="deployment.de.example.wildfly.login"/>
</authentication>
</security-domain>
My first try was to use a custom realm in Elytron. But as far as I understand, a custom realm needs to be a "static" module (meaning it is located under wildfly/modules/...) and thus cannot access "dynamically" deployed modules (see https://developer.jboss.org/message/984198#984198).
<subsystem xmlns="urn:wildfly:elytron:7.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
...
<security-domains>
<security-domain name="MyDomain" default-realm="MyRealm" permission-mapper="default-permission-mapper">
<realm name="MyRealm" role-decoder="from-roles-attribute" />
</security-domain>
</security-domains>
<security-realms>
...
<custom-realm name="MyRealm" module="de.example.wildfly.login" class-name="de.example.wildfly.MyCustomRealm" />
(I omitted some more of the security domain configuration)
When I try to load a Spring context (that is located in an EAR in order to access some custom classes from the EAR) in MyCustomRealm, I get the following error:
org.springframework.beans.factory.access.BootstrapException: Unable to initialize group definition. Group resource name [classpath:applicationContext-appServerBase.xml], factory key [applicationContextEjb]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext-appServerBase.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext-appServerBase.xml] cannot be opened because it does not exist
Which is no surprise, because my realm does not depend on the ear or any jar from therein, where the application context is located.
How can authentication (specifically for EJB calls) be customized on server side by using classes from a deployment module (EAR) in Elytron?
Maybe https://github.com/AntonYudin/wildfly-securityrealm-ejb is exactly what you are looking for.
It creates a SecurityRealm that can be configured with the address of an EJB that's deployed with your application.
The EJB has to be Stateless and must implement the method Map<String, Object> authenticate(String, String) which is called with a username and a password.
I guess you have to return a map that contains all roles and groups the user belongs to or null if the credentials are invalid.

How to avoid providing security credentials in Alfresco OpenLDAP authentication

We have to provide Alfresco and jBoss web application users authentication with openLDAP.
The OpenLDAP is configured so, that there is now need to provide any credentials to read openLDAP directory.
In case of jBoss configuration I am not providing these credentials with bindDN and bindCredential tags and authentication is working.
In case of Alfresco that is not the case, if I do not provide ldap.synchronization.java.naming.security.principal and ldap.synchronization.java.naming.security.credentials, I have synchronization error in log:
2019-02-15 10:58:04,466 ERROR [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] [localhost-startStop-1] Synchronization aborted due to error
org.alfresco.repo.security.authentication.AuthenticationException: 01150001 Failed to authenticate, username or password is wrong. User name:cn=Manager,dc=company,dc=com Reason [LDAP: error code 49 - Invalid Credentials]
So ldapsearch retreives the openLDAP directory without providing any credentials:
ldapsearch -x -h 10.0.1.15:389 -b "dc=some,dc=ua"
jBoss standalone-full.xml:
<login-module code="LdapExtended" flag="sufficient">
<module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<module-option name="java.naming.provider.url" value="ldap://10.0.1.15:389"/>
<module-option name="java.naming.security.authentication" value="simple"/>
<module-option name="baseCtxDN" value="ou=Users,dc=some,c=ua"/>
<module-option name="baseFilter" value="(uid={0})"/>
<module-option name="rolesCtxDN" value="ou=Users,dc=some,c=ua"/>
<module-option name="roleFilter" value="(member={1})"/>
<module-option name="roleAttributeID" value="cn"/>
<module-option name="roleAttributeIsDN" value="false"/>
<module-option name="roleRecursion" value="1"/>
<module-option name="allowEmptyPasswords" value="false"/>
<module-option name="throwValidateError" value="true"/>
</login-module>
Alfresco alfresco-global.properties
authentication.chain=alfinst:alfrescoNtlm,ldap1:ldap
ntlm.authentication.sso.enabled=false
alfresco.authentication.authenticateCIFS=false
ldap.authentication.active=true
ldap.synchronization.active=true
ldap.authentication.allowGuestLogin=false
ldap.authentication.userNameFormat=uid=%s,ou=Users,dc=some,dc=ua
ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
ldap.authentication.java.naming.provider.url=ldap://10.0.1.15:389
ldap.authentication.java.naming.security.authentication=simple
ldap.synchronization.java.naming.security.authentication=simple
ldap.authentication.defaultAdministratorUserNames=Admin
ldap.synchronization.java.naming.security.principal=uid\=someUser,ou\=users,dc\=some,dc\=ua
ldap.synchronization.java.naming.security.credentials=12356
ldap.synchronization.groupSearchBase=ou\=Users,dc\=some,dc\=ua
ldap.synchronization.userSearchBase=ou\=Users,dc\=some,dc\=ua
ldap.synchronization.groupQuery=(&(objectclass\=posixGroup)
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=posixGroup)(!(modifyTimestamp<\={0})))
ldap.synchronization.personQuery=(objectclass\=inetOrgPerson)
ldap.synchronization.personDifferentialQuery=(&(objectclass\=inetOrgPerson)(!(modifyTimestamp<\={0})))
ldap.synchronization.modifyTimestampAttributeName=modifyTimestamp
ldap.synchronization.timestampFormat=yyyyMMddHHmmss'Z'
ldap.synchronization.userIdAttributeName=uid
ldap.synchronization.userOrganizationalIdAttributeName=o
ldap.synchronization.groupDisplayNameAttributeName=displayName
ldap.synchronization.groupType=posixGroup
ldap.synchronization.personType=inetOrgPerson
ldap.authentication.java.naming.read.timeout=0
ldap.synchronization.userAccountStatusProperty=ds-pwp-account-disabled
ldap.synchronization.disabledAccountPropertyValue=true
ldap.synchronization.userFirstNameAttributeName=givenName
ldap.synchronization.userLastNameAttributeName=sn
ldap.synchronization.userEmailAttributeName=mail
ldap.synchronization.defaultHomeFolderProvider=userHomesHomeFolderProvider
ldap.synchronization.groupIdAttributeName=cn
ldap.synchronization.groupMemberAttributeName=member
ldap.synchronization.enableProgressEstimation=true
ldap.pooling.com.sun.jndi.ldap.connect.pool.debug=fine
synchronization.autoCreatePeopleOnLogin=true
synchronization.synchronizeChangesOnly=false
synchronization.syncOnStartup=true
synchronization.syncWhenMissingPeopleLogIn=true
synchronization.externalUserControl=true
synchronization.externalUserControlSubsystemName=ldap1
Is it possible to avoid providing OpenLDAP credentials in alfresco-global.properties?
Alfresco Community (Build: 201612)
jBoss EAP-6.4
There are two things going on with Alfresco: Authentication and Synchronization. Authentication against OpenLDAP can happen without a credential because it binds using the user's credential.
Synchronization, however, happens in batch in the background. The synchronization job that runs needs a credential to authenticate with OpenLDAP so it can query for users and groups created or modified since the last check. If you don't provide a credential it would mean your OpenLDAP directory would have to be wide open, which is surely not what you want.

JBoss EAP 7: xa transaction warning “No security domain defined for crash recovery” even with a security domain

I have a JBoss EAP 7.1 with some XA datasource.
The datasource has a security domain:
<security>
<security-domain>encrypted-ds</security-domain>
</security>
which makes use of the encrypted-password login module (for various political reasons):
<security-domain name="encrypted-ds" cache-type="default">
<authentication>
<login-module code="org.picketbox.datasource.security.SecureIdentityLoginModule" flag="required">
<module-option name="username" value="user_name_here"/>
<module-option name="password" value="some_hash_here"/>
</login-module>
</authentication>
</security-domain>
Yet, I get those cyclic warning messages when the server has started:
11:25:15,506 WARN [org.jboss.jca.core.tx.jbossts.XAResourceRecoveryImpl] (Periodic Recovery) IJ000904: No security domain defined for crash recovery: java:/jdbc/myDataSource
11:25:15,511 WARN [org.jboss.jca.core.tx.jbossts.XAResourceRecoveryImpl] (Periodic Recovery) IJ000905: Subject for crash recovery was null: java:/jdbc/myDataSource
This is similar, but not the same as question Wildfly xa transaction warning "No security domain defined for crash recovery" , as here, I have a username and an encrypted password, and a security domain. I can fathom why the system would consider there is no security domain nor subject/username.
You can add the same security domain for recovery
<recovery>
<recover-credential>
<security-domain>your sec domain here</security-domain>
</recover-credential>
</recovery>
I ended up using the JBoss Vault to manage the encrypted password.
https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.0/html-single/how_to_configure_server_security/index#secure_passwords

unable to set security domain via jboss-web.xml

We have an app that is being deployed as an ear. Within this ear, there is a war that needs to use a specific security domain.
To achieve this, we have configured the standalone-full-ha.xml with the following security section
<security-domain name="ourDomain" cache-type="default">
<authentication>
<login-module code="blah.blah.OurDomain" flag="required" />
</authentication>
</security-domain>
ear/war/WEB-INF/jboss-web.xml is configured as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>Quark</security-domain>
<disable-audit>true</disable-audit>
</jboss-web>
With this configuration, the app tries to authenticate against the "other" domain which is there in JBoss by default.
log entries as follows:
TRACE [org.jboss.security] (http-/127.0.0.1:8080-6) PBOX000224: End getAppConfigurationEntry(other), AuthInfo: AppConfigurationEntry[]:
[0]
LoginModule Class: org.jboss.as.security.remoting.RemotingLoginModule
ControlFlag: LoginModuleControlFlag: optional
Options:
name=password-stacking, value=useFirstPass
[1]
LoginModule Class: org.jboss.as.security.RealmDirectLoginModule
ControlFlag: LoginModuleControlFlag: required
Options:
name=password-stacking, value=useFirstPass
When trying to define this as part of the ear in ear/META-INF/jboss-app.xml, that made the whole thing blow up pretty spectacularly - so figured that was less likely to be the way to resolve this.
If the default security domain is changed to ourDomain however, it all works as expected.
This doesn't seem to be a big deal - however, it feels better to be able to leave as much of the configuration in the app as possible.
Any pointers to resolve this appreciated.
Your security domain name specified in jboss-web.xml needs to match the name of some security domain in your JBoss config, in your case the web descriptor specifies Quark while the security subsystem defined domain named ourDomain.
Whenever JBoss can not find the security domain you request in your jboss-web.xml, it will fallback to the default security domain, which in case of 7.x is named other.