JBOSS EAP 7 - EJB Client user data - jboss

I have migrated my EJB application from jboss 5.0.1 to JBOSS EAP 7.
I want to pass user data from EJB client to my EJB.
I'm using this code to pass custom attribute to ejb server but it does not work anymore.
Client:
public class CustomData extends SimplePrincipal{
String userData1;
public CustomData(String userData1){
this.userData1 = userData1;
}
SecurityClient client = SecurityClientFactory.getSecurityClient();
client.setSimple(new CustomData("MyData"), credentials.getPass());
client.login();
Server:
#Resource
SessionContext ejbCtx;
Principal data= ejbCtx.getCallerPrincipal();
data.getName() --- anonymous
How to fix it on new JBOSS ?

1.Create the client side interceptor
This interceptor must implement the org.jboss.ejb.client.EJBClientInterceptor. The interceptor is expected to pass the additional security token through the context data map, which can be obtained via a call to EJBClientInvocationContext.getContextData().
2.Create and configure the server side container interceptor
Container interceptor classes are simple Plain Old Java Objects (POJOs). They use the #javax.annotation.AroundInvoke to mark the method that is invoked during the invocation on the bean.
a.Create the container interceptor
This interceptor retrieves the security authentication token from the context and passes it to the JAAS (Java Authentication and Authorization Service) domain for verification
b. Configure the container interceptor
3.Create the JAAS LoginModule
This custom module performs the authentication using the existing authenticated connection information plus any additional security token.
Add the Custom LoginModule to the Chain
You must add the new custom LoginModule to the correct location the chain so that it is invoked in the correct order. In this example, the SaslPlusLoginModule must be chained before the LoginModule that loads the roles with the password-stacking option set.
a.Configure the LoginModule Order using the Management CLI
The following is an example of Management CLI commands that chain the custom SaslPlusLoginModule before the RealmDirect LoginModule that sets the password-stacking option.
b. Configure the LoginModule Order Manually
The following is an example of XML that configures the LoginModule order in the security subsystem of the server configuration file. The custom SaslPlusLoginModule must precede the RealmDirect LoginModule so that it can verify the remote user before the user roles are loaded and the password-stacking option is set.
Create the Remote Client
In the following code example, assume the additional-secret.properties file accessed by the JAAS LoginModule
See the link:
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.2/html/Development_Guide/Pass_Additional_Security_For_EJB_Authentication.html

I have done with this way:
Client:
Properties properties = new Properties();
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
properties.put("org.jboss.ejb.client.scoped.context", "true");
properties.put("remote.connection.default.username", "MyData");
Server:
public class MyContainerInterceptor{
#AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Connection connection = RemotingContext.getConnection();
if (connection != null) {
for (Principal p : connection.getPrincipals()) {
if (p instanceof UserPrincipal) {
if (p.getName() != null && !p.getName().startsWith("$"))
System.out.println(p.getName()); //MyData will be printed
}
}
}
return ctx.proceed();
}
}
Don't forget to configure container interceptor in jboss-ejb3.xml (not in ejb-jar.xml)
<?xml version="1.0" encoding="UTF-8"?>
<jee:assembly-descriptor>
<ci:container-interceptors>
<jee:interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>package...MyContainerInterceptor</interceptor-class>
</jee:interceptor-binding>
</ci:container-interceptors>
</jee:assembly-descriptor>

Related

Enable REST service for CAS Apereo version cas-overlay-template-6.0

I want to enable REST service for CAS Apereo version cas-overlay-template-6.0 (on Ubuntu 16.04)
I have done following this step:
Step 1: Add compile for REST API to build.gradle file
root#ubuntu16:~/cas-overlay-template-6.0# nano build.gradle
And add two line below under dependencies clock
compile "org.apereo.cas:cas-server-support-rest:6.0.0"
compile "org.apereo.cas:cas-server-support-rest-services:6.0.0"
Step 2: clean build
root#ubuntu16:~/cas-overlay-template-6.0# ./build.sh clean
Step 3: Build source code again
root#ubuntu16:~/cas-overlay-template-6.0# ./build.sh run
But in step 3, I got error like this.
CAS is configured to accept a static list of credentials for authentication. While this is generally useful for demo purposes, it is STRONGLY recommended that you DISABLE this authentication method (by setting 'cas.authn.accept.users' to a blank value) and switch to a mode that is more suitable for production.>
2019-12-30 01:17:55,465 WARN [org.apereo.cas.config.support.authentication.AcceptUsersAuthenticationEventExecutionPlanConfiguration] - <>
2019-12-30 01:17:55,806 INFO [org.apereo.cas.config.CasPersonDirectoryConfiguration] - <Found and added static attributes [[email]] to the list of candidate attribute repositories>
2019-12-30 01:17:59,004 WARN [org.apereo.cas.web.CasWebApplicationContext] - <Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registeredServiceResourceRestController' defined in class path resource [org/apereo/cas/support/rest/config/RestServicesConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apereo.cas.support.rest.RegisteredServiceResource]: Factory method 'registeredServiceResourceRestController' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: No attribute name is defined to enforce authorization when adding services via CAS REST APIs. This is likely due to misconfiguration in CAS settings where the attribute name definition is absent>
Where have I gone wrong?
Remove this:
compile "org.apereo.cas:cas-server-support-rest-services:6.0.0"
This module does this:
Invoke CAS to register applications into its own service registry. The REST call must be authenticated using basic authentication where credentials are authenticated and accepted by the existing CAS authentication strategy, and furthermore the authenticated principal must be authorized with a pre-configured role/attribute name and value that is designated in the CAS configuration via the CAS properties. The body of the request must be the service definition that shall be registered in JSON format and of course, CAS must be configured to accept the particular service type defined in the body. The accepted media type for this request is application/json.
So you can remove it, if you don't need the functionality.
If you do need it, you will need to define attribute names/values that can enforce authorization as the error message is telling you.
No attribute name is defined to enforce authorization when adding services via CAS REST APIs. This is likely due to misconfiguration in CAS settings where the attribute name definition is absent.
So, define:
# cas.rest.attributeName=
# cas.rest.attributeValue=
PS Don't add things you do not need.

Permission issue in calling EJB from MDB

We have recently switched from JAAS to Keycloak. Application is JavaEE application with EJBs & MDBs.
Set keycloak login module in WildFly to propagate user from wen to EJB & it worked.
But facing issue when an EJB is called from MDB. There is anonymoius user in MDB when message received. So that user don't have permission to invoke EJB protected by:
<s:security>
<ejb-name>*</ejb-name>
<s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
<s:security-domain>keycloak</s:security-domain>
</s:security>
In JAAS version, we have programmatic login using dedicated mdb user.
loginContext = new LoginContext("ldap", new CallbackHandler() {
#Override
public void handle(Callback[] callbacks) {
...
}
});
loginContext.login();
//Invoke EJB now as logged in user
This have user with required permission. Since now moved to Keycloak, this JAAS login code will not work. What is the option to prevent permission issue in calling EJB from MDB?

Trouble with Authenticating with remote EJB calls to Wildfly 10

I'm trying to do Remote EJB calls to my Wildfly 10/JBoss 7 EAP server, but keep getting Invalid User error messages on my Wildfly server (my EJB is called LoginManager):
23:04:02,872 ERROR [org.jboss.as.ejb3.invocation] (default task-6) WFLYEJB0034: EJB Invocation failed on component LoginManager for method public abstract java.lang.String ejbs.LoginManagerRemote.echo(java.lang.String): javax.ejb.EJBAccessException: WFLYSEC0027: Invalid User
at org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:69)
at org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:49)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:97)
I've added my user to the application-users.properties file using the add-user.sh/bat scripts.
I've tried putting in breakpoints in the Wildfly server itself in the SecurityContextInterceptor class on line 54 and see that the principal is null:
if (holder.skipAuthentication == false) {
holder.securityManager.authenticate(holder.runAs, holder.runAsPrincipal, holder.extraRoles);
I'm not entirely sure if this runAs or runAsPrincipal is the principal/credentials passed by the remote EJB invocation, but I suspect it might be responsible for my problem.
I'm calling the remote ejb as:
Properties p = new Properties();
p.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(p);
LoginManagerRemote ejb = (LoginManagerRemote) context.lookup("ejb:ear-1.0/ejbs-1.0//LoginManager!ejbs.LoginManagerRemote");
return ejb.echo("test");
with my jboss-ejb-client.properties as:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.conncetion.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
remote.connection.default.username=test
remote.connection.default.password=test
Am I doing something wrong? Am I missing something obvious somewhere? What do I need to do to successfully call a remote EJB?
There's a typo in your jboss-ejb-client.properties
remote.conncetion.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
Should be remote.connection.default.connect.options etc etc

Resteasy Bean Validation Not Working on Remote Server

I have a problem similar to the one described here.
I am using RESTEasy within a standalone Jetty application. When I start the application locally and call a service (e.g. localhost:16880/rest/user/login) bean validation works fine, i.e. I get validation errors like this:
[PARAMETER]
[UserService#login(arg0).appKey]
[app_key may not be null or empty]
[]
However, when I deploy my application to a remote host and call the same service (e.g. remotehost:16880/rest/user/login) bean validation is not invoked at all.
I am using the #ValidateRequest annotation for the service and #Valid annotation for the bean parameter.
My Resteasy version is 3.0.13.Final, though I have tried earlier versions as well. I have tried to write my custom validator, but that didn't work either.
I am puzzled why the validation works locally, but not on remote server. Any suggestions would be highly appreciated.
Since you are using Jetty as standalone server, you have to define RESTEasy validation providers where you define ServletContextHandler. Note that in standalone server there is no container to scan for #Provider classes and to activate them, so you must do it manually.
I expect that you create and start your server app something like:
//create a server listening at some port
Server server= new Server(port);
//add server handlers
HandlerList handlers= new HandlerList();
initHandlers(handlers);
server.setHandler(handlers);
//start the server
server.start();
In initHandlers you must have defined your RESTEasy support:
public void initHandlers(List<HandlerList> handlers) {
//define root context handler
ServletContextHandler servletContextHandler= new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
handlers.addHandler(servletContextHandler);
//define RESTEasy handler
ServletHolder restServlet= new ServletHolder(new HttpServlet30Dispatcher());
//since this is a standalone server, somewhere you have to define RESTful services and Singletons
restServlet.setInitParameter("javax.ws.rs.Application", "com.exampleapp.MyRestApplication");
restServlet.setInitParameter("resteasy.servlet.mapping.prefix", "rest");
servletContextHandler.addServlet(restServlet, "rest/*");
}
So what is left to do now is to add Validation provider as init parameter:
restServlet.setInitParameter("resteasy.providers", "org.jboss.resteasy.plugins.validation.ValidatorContextResolver,org.jboss.resteasy.api.validation.ResteasyViolationExceptionMapper");
On this link I tried to find the name of the validator providers: https://docs.jboss.org/resteasy/docs/3.0.4.Final/userguide/html/Validation.html
RESTEasy obtains a bean validation implemenation by looking in the available META-INF/services/javax.ws.rs.Providers files for an implementation of ContextResolver
So it does not say what, but says where. Now open the "resteasy-hibernatevalidator-provider-3...*.jar (from Eclipse -> Maven dependencies or manually unzip) and look into META-INF/services/javax.ws.rs.ext.Providers It says:
org.jboss.resteasy.plugins.validation.hibernate.ValidatorContextResolver
org.jboss.resteasy.api.validation.ResteasyViolationExceptionMapper
If you don't have this dependency, then add it to your pom file:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-hibernatevalidator-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
One more note: that at the same place where you described validation providers, you also add other providers, if you happen to need them (such as JacksonJaxbJson, etc).

RMI using spring. Executing method in server with object as parameter

I am trying to execute a method from client to server using RMI.
As long as the parameters are String, it is getting executed correctly. If I am using object as method parameter.
I am getting following exception :
java.rmi.UnmarshalException: Error unmarshaling return; nested exception is:
java.lang.ClassNotFoundException: org.eclipse.persistence.exceptions.DatabaseException (no security manager: RMI class loader disabled)
Server configuration:
#Bean
public RmiServiceExporter getUserService() {
RmiServiceExporter exporter = new RmiServiceExporter();
exporter.setService(userService);
exporter.setServiceName("UserService");
exporter.setServiceInterface(UserService.class);
exporter.setRegistryPort(1192);
exporter.setReplaceExistingBinding(true);
return exporter;
}
Client configuration:
public #Bean RmiProxyFactoryBean getUserService() {
RmiProxyFactoryBean rmi = new RmiProxyFactoryBean();
rmi.setServiceInterface(UserService.class);
rmi.setServiceUrl("rmi://localhost:1192/UserService");
return rmi;
}
Test code :
User user = userService.getUser(String userName);
Works perfectly fine.
userService.save(user);
Save user throws RMI exception.
I made sure that the package name for User object in server and client is same. Still I am getting the exception.
Am I missing any configuration? How can I make RMI server to load the other classes?