When using Basic Authentication for war deployed in WildFly, getUserPrincipal returns null - authentication

I have been attempting to get a simple Basic Authentication example working with WildFly 8.1.0, immutant, and friend. I'm willing to post any code desired, but I'm not sure what would be needed at this point. For now, I'll assume my standalone.xml, web.xml, and jboss-web.xml all contain the correct data -- that may not be the case, but for now I'll just dive in to the problem.
I have an application with a simple /test resource. I've deployed it on WildFly and use Basic Authentication to attempt to access it. Also, I've checked my application-roles.properties and application-users.properties files and they seem fine.
When I attempt to log in, I see the following trace from WildFly:
14:30:36,681 TRACE [org.jboss.security] (default task-1) PBOX000210:
defaultLogin, login context:
javax.security.auth.login.LoginContext#4c89fc2c, subject:
Subject(1313538088).principals=org.jboss.security.SimplePrincipal#99148614(tester-na)org.jboss.security.SimpleGroup#83654093(Roles(members:elm-nss-admin))org.jboss.security.SimpleGroup#83654093(CallerPrincipal(members:tester-na))
The user is tester-na and you can see that it is a member of elm-nss-admin.
When I use a bad password, WildFly catches it and my application never does any check. However, when I sent the correct password the above trace is logged and it calls my authentication handler.
The problem is that my authentication handler fails because a call to getUserPrincipal() returns NULL. The resource is protected, here are my security constraints:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Resources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
When I use LDAP, this isn't a problem. I think it's because LDAP supplied a certificate and WildFly passes up the cookie.
But with Basic Auth, I'm not getting a cookie, I won't barf the debug output unless requested, it's quite verbose, but the relevant bits are: :cookies {}, :context , :session nil
I'm guessing that getUserPrincipal() fails because I'm still in the act of authenticating?
So, any ideas on how I can get the user data/permissions from WildFly so friend can be passed the proper data to authenticate/authorize with?
#
Update: I was able to create a simple application with the same XML files I'm using for the production app and it isn't failing. For interest, and those who use stackoverflow for answers as much as I do, here are the relevant parts:
From standalone.xml in security-realms:
<security-realm name="ApplicationRealm">
<authentication>
<local default-user="$local" allowed-users="*"/>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
and in <subsystem xmlns="urn:jboss:domain:security:1.2"> I have:
<security-domain name="other" 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="password-stacking" value="useFirstPass"/>
</login-module>
</authentication>
</security-domain>
<security-domain name="jboss-web-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
<security-domain name="jboss-ejb-policy" cache-type="default">
<authorization>
<policy-module code="Delegating" flag="required"/>
</authorization>
</security-domain>
In my web.xml file (in the war-resources/WEB-INF folder):
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>ApplicationRealm</realm-name>
</login-config>
The jboss.xml file, in the same directory is:
<jboss-web>
<context-root></context-root>
<security-domain>other</security-domain>
</jboss-web>
Since these settings are working with my simple application, I'll start looking for something project specific as to why WildFly isn't giving me the user in my production code.
Any helpful suggestions would be greatly appreciated. Even just a suggestion as to where to start looking.
#
Problem solved. Turns out the user was being logged out before I was attempting to authorize access to a specific resource. :P

Steven solved the problem himself:
Problem solved. Turns out the user was being logged out before I was
attempting to authorize access to a specific resource. :P

Related

Wildfly 20 - Admin ManagementRealm (security-realm) on ldap SSL

I configure a wildfly 20 and i have a problem with the ManagementRealm (security-realm) on ldap SSL.
With LDAP, it's OK, but as soon as i switch to ldaps the authentication no longer works.
The login window opens and whatever account I indicate (even a true or false login) I turn back to the "Connect to Management Interface" screen (practically blank).
And I have no errors in any log.
I tried a WildFly 19 and 20, on centos 8.
The trustore does exist, I added it in the startup variable (as well as its password)
Here is an excerpt from my standalone.xml file
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<local default-user="$local" skip-group-loading="true"/>
<ldap connection="ldap_connection" base-dn="OU=Utilisateurs,DC=org">
<advanced-filter filter="(&(sAMAccountName={0})(memberOf=CN=APP-ADMIN,OU=Utilisateurs,DC=org))"/>
</ldap>
<truststore path="truststore.jks" relative-to="jboss.server.config.dir" keystore-password="XXX" />
</authentication>
<authorization map-groups-to-roles="false">
<properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
<security-realm name="LdapSSLRealm">
<authentication>
<truststore path="truststore.jks" relative-to="jboss.server.config.dir" keystore-password="XXX" />
</authentication>
</security-realm>
</security-realms>
<outbound-connections>
<ldap name="ldap_connection" url="ldaps://serveurad:636" search-dn="user" search-credential="XXX"/>
</outbound-connections>
If anyone has an idea I would appreciate it.
A little late but I believe you have to also reference the security realm (containing the ref to the trust store) in your <outbound-connection />:
<outbound-connections>
<ldap name="ldap_connection" url="ldaps://serveurad:636" search-dn="user" search-credential="XXX" security-realm="LdapSSLRealm"/>
</outbound-connections>

JBoss Wildfly - Authentication of Web App against LDAP

I have a security domain defined in jboss-web.xml as below
<jboss-web>
<security-domain>java:/jaas/my_ldap_security_domain</security-domain>
<disable-audit>true</disable-audit>
</jboss-web>
I also have defined inside my standalone.xml
<subsystem xmlns="urn:jboss:domain:security:1.2">
<security-domains>
<security-domain name="my_ldap_security_domain" cache-type="default">
<authentication>
<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="ldaps://xxx.xxx.xxx.xxx:yyyy"/>
<module-option name="java.naming.security.authentication" value="simple"/>
<module-option name="bindDN" value="temp#my.domain"/>
<module-option name="bindCredential" value="mypass"/>
<module-option name="baseCtxDN" value="DC=my,DC=domain"/>
<module-option name="baseFilter" value="(uid={0})"/>
<module-option name="rolesCtxDN" value="DC=my,DC=domain"/>
<module-option name="roleFilter" value="(uniquemember={1})"/>
<module-option name="roleAttributeID" value="cn"/>
<module-option name="searchScope" value="SUBTREE_SCOPE"/>
<module-option name="roleRecursion" value="0"/>
<module-option name="allowEmptyPasswords" value="true"/>
</login-module>
</authentication>
</security-domain>
</security-domains>
</subsystem>
My only realms present on my standalone.xml are
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<local default-user="$local" skip-group-loading="true"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization map-groups-to-roles="false">
<properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
<security-realm name="ApplicationRealm">
<authentication>
<local default-user="$local" allowed-users="*" skip-group-loading="true"/>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
</security-realms>
I did not mention it before because i presumed that this security realms were meant to authenticate the application server console access. Sorry for that.
My doubt is how to create a jsf2 login page to authenticate against what is defined above. I read a lot of articles about but still in the same place beacause most articles use a fake authentication as example (comparing with static strings instead of showing how to consult LDAP server).
Can anyone help me?
i presumed that this security realms were meant to authenticate the application server console access
You're partially correct there. The name="ManagementRealm" does indeed specify a realm config for accessing admin functions. name="ApplicationRealm" would be the attribute to specify for securing a web application
Your current realm config is missing some things necessary for LDAP authentication. I presume you're already familiar with the login-form configuration in web.xml. Your realm configuration should look something like the following, an excerpt from the Wildfly 8 Realm Configuration Manual:
<management>
  <security-realms>
    <security-realm name="ApplicationRealm">
      <authentication>
        <ldap connection="EC2" base-dn="CN=Users,DC=darranl,DC=jboss,DC=org">
          <username-filter attribute="sAMAccountName" />
        </ldap>
      </authentication>
    </security-realm>
 
  </security-realms>
</management>
Where the <ldap> tag specifies that your lookup is against an LDAP server. Beyond this, you only need follow the standard auth methods for a JavaEE application.
The takeaway from this should be that web application security within JavaEE generally takes the same approach of
Setting up a realm (App-server specific)
Setting up security constraints in web.xml (uniform across all JavaEE applications)
Implementing a login method (Configuration or Programmatic)
Related
Java EE 6 Programmatic security, glassfish and JDBC realm
How to properly logout of a Java EE 6 Web Application after logging in
Performing user authentication in Java EE / JSF using j_security_check

No authenticator available for programmatic login

I keep getting this error whenever I try to login with two different users in two different sessions.
13:27:28,444 ERROR [com.commit.steam.rest.RestLoginService] (http-localhost-127.0.0.1-8080-2) Error on login: javax.servlet.ServletException: No authenticator available for programmatic login
at org.apache.catalina.connector.Request.login(Request.java:3254) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.RequestFacade.login(RequestFacade.java:1082) [jbossweb-7.0.13.Final.jar:]
at com.commit.steam.rest.RestLoginService.login(RestLoginService.java:128) [steam-rest-api-0.1.6-SNAPSHOT.jar:]
from standalone.xml:
<security-domain name="steam" cache-type="default">
<authentication>
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
<module-option name="dsJndiName" value="java:jboss/datasources/STEAMDS"/>
<module-option name="principalsQuery" value="select U.PASSWORD from USERS U where U.EMAIL=?"/>
<module-option name="rolesQuery" value="select R.NAME, 'Roles' from USERS U join USER_ROLES UR on U.ID = UR.USER_ID join ROLES R on UR.ROLE_ID = R.ID where U.EMAIL=?"/>
<module-option name="hashAlgorithm" value="SHA-256"/>
<module-option name="hashEncoding" value="base64"/>
</login-module>
</authentication>
</security-domain>
jboss-web.xml:
<?xml version="1.0"?>
<jboss-web>
<security-domain>steam</security-domain>
</jboss-web>
I use JBoss-as 7.1.1.Final
While debugging I can see that the first request (HttpServletRequest.context.authenticator) has the NonLoginAuthenticator and the login with the second session doesn't have any authenticator attached to it (i.e. HttpServletRequest.context.authenticator is null).
Every following request in the first session has the same Authenticator on the request (when I test business flows for one user).
The HttpServletRequest is injected in the class level
#Context
private HttpServletRequest request;
protected HttpServletRequest request() {
return this.request;
}
(I tried to move the injection to method level and it didn't help). My rest class is annotated as #Stateless bean (to allow injections).
I tried switching the sessions (I use Chrome and FireFox to ensure different sessions) but it didn't change anything.
Does anyone have any idea or lead on where I need to look for this issue?
Thanks a lot
Avi
Add a <security-constraint> element to your web.xml. Something like this:
<security-constraint>
<web-resource-collection>
<web-resource-name>Permit all</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>

Login failure in jbpm-console jboss-as-7

I have a problem with the jbpm-console, generated to source , I installed jbpm-console-ng-jboss-as7.0.war in jboss, that deploy OK, config security-domain in the subsystem "urn:jboss:domain:security:1.1" and add users and roles properties , in the standalone, create the jboss user, but when login to jbpm-console, I have the following error Login failed: Not Authorized
The security-dommain is that in standalone.xml :
<subsystem xmlns="urn:jboss:domain:security:1.1">
<security-domains>
...
<security-domain name="jbpm-console-ng" cache-type="default">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="${jboss.server.config.dir}/users.properties"/>
<module-option name="rolesProperties" value="${jboss.server.config.dir}/roles.properties"/>
</login-module>
</authentication>
</security-domain>
</security-domains>
</subsystem>
The roles.properties you content is that :
root=jbpm-console-user,user,analyst,PM,IT,Reviewer
The users.properties you content is that :
root=root
The jboss user is "root".
Help me plis !!
Make sure your security-domain is being referenced in jboss-web.xml
<jboss-web>
<security-domain>jbpm-console-ng</security-domain>
</jboss-web>
this file is on jbpm-console.war/WEB-INF/jboss-web.xml

Login configuration in Vaadin/Spring application in JBoss AS 7

I am trying to configure authentication in my Vaadin/Spring application deployed in JBoss AS 7, but I cannot find any documentation on this. I've managed to configure the application so that only authenticated user can use it. Here is a part of my web.xml:
<security-constraint>
<display-name>SecureApplicationConstraint</display-name>
<web-resource-collection>
<web-resource-name>Vaadin application</web-resource-name>
<description>The entire Vaadin application is protected</description>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>Only valid users are allowed</description>
<role-name>ROLE_ADMIN</role-name>
<role-name>ROLE_DOCTOR</role-name>
<role-name>ROLE_PATIENT</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>file</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/loginError.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description/>
<role-name>ROLE_ADMIN</role-name>
</security-role>
<security-role>
<description/>
<role-name>ROLE_DOCTOR</role-name>
</security-role>
<security-role>
<description/>
<role-name>ROLE_PATIENT</role-name>
</security-role>
Now the application won't be displayed until the user is authenticated. What I expected was, that the user would be automatically redirected to the login form. I still have to configure the JBoss app server, but cannot find how. I used to work with JBoss 5, where this configuration was done in a login-config.xml file. Does anybody know hoe to configure the authentication REALM in JBoss 7 and make the Vaadin application redirect the user to the login form if he is not authenticated yet? Thanks for your help,
Bye,
Filip
First, a couple of questions -
(1)what is happening when you try to access a resource,
and (2)the security constraint covers/protects anything in the domain.
But your login page is there too.
Would you try limiting the url-pattern to something that wouldn't include the login page, like /myprotectedfolder/* instead?
I've found that FORM-based login is tricky in Vaadin, as Vaadin servlet is by default mapped to /*, which means that your login.jsp will also be handled by it. I implemented my login programmatically with the LoginForm, which seems like a nicer integration. However, it's not really what your question is about...
In JBoss AS 7 the configs moved to {jboss}/standalone/configuration/standalone.xml or {jboss}/standalone/configuration/domain.xml, depending on your setup. In most common cases it's standalone.xml. Here's the sample of my database-driven security domain:
<subsystem xmlns="urn:jboss:domain:security:1.0">
<security-domains>
<security-domain name="MySecurityDomain">
<authentication>
<login-module code="Database" flag="required">
<module-option name="dsJndiName" value="java:jboss/datasources/MyDS"/>
<module-option name="principalsQuery" value="SELECT PASSWORD FROM PRINCIPAL WHERE USERNAME=?"/>
<module-option name="rolesQuery" value="SELECT r.name, 'Roles' FROM role r, principal_role pr, principal p WHERE p.username=? AND p.user_id=pr.user_id AND pr.role_id=r.role_id"/>
<module-option name="hashAlgorithm" value="MD5"/>
<module-option name="hashEncoding" value="hex"/>
</login-module>
</authentication>
</security-domain>
</security-domains>
</subsystem>
I hope this helps.