Keycloak, Tomcat 9, and #RolesAllowed? - security

I am trying to configure my Tomcat 9-based web application to leverage Keycloak for its security provider. I've done this in the past on Wildfly with no problem using the Wildfly adapter. I'm running into issues doing this in Tomcat 9, though. Here's what I've done...
I've added the Keycloak Tomcat adapter to my project using maven:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat8-adapter</artifactId>
<version>6.0.1</version>
</dependency>
In my context.xml file I've defined the Keycloak authenticator valve:
<Context path="/myapp">
<Valve
className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve" />
</Context>
In my web.xml file I've added a login-config and security-role:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>KEYCLOAK</realm-name>
</login-config>
<security-role>
<role-name>*</role-name>
</security-role>
I've also added my keycloak.json file to my /WEB-INF directory within the WAR file. Now I'm trying to test it by adding a #RolesAllowed annotation to a test Servlet I've created:
#WebServlet(urlPatterns = { "/TestServlet" })
#RolesAllowed({ "roleA", "roleB", "roleXXX" })
public class TestServlet extends HttpServlet {
...
}
I am not authenticated at this point, so I would expect that hitting /TestServlet would cause me to receive a 403 or 401. However, Tomcat lets me in just fine. No errors or anything. As a sanity check, I changed the #RolesAllowed annotation to #DenyAll, expecting that I would be prevented from hitting the servlet in my browser. Even after this change I'm still able to get through.
Does anyone have any idea why this is not working as expected? Is #RolesAllowed not supported for Servlets? I was under the impression that it was. If not, is there something different I should be doing to integrate Keycloak and Tomcat 9?

Related

Java EE Container Based Security

I am attempting to implement JDBC Realm Authentication with Wildfly.
I have used this article as reference:
http://blog.eisele.net/2015/01/jdbc-realm-wildfly820-primefaces51.html
As well as the accompanying source code on GitHub at https://github.com/myfear/SimpleJDBCRealmWildFly/
I am presented with the login form if I try to access one of the protected areas of the application but after filling in my username and password it never seems to successfully authenticate(loginError.xhtml).
The only difference between my application and the above example is that my form specifies
action="j_security_check"
whereas the GitHib example uses
onsubmit="document.loginForm.action = 'j_security_check';"
In my web.xml I specify
<security-role>
<role-name>ADMIN</role-name>
</security-role>
Which matches what I specified for my user in my role table..What am I still missing?

EJBAccessException when invoke local EJB on Wildfly

When I try to invoke local EJB I get EJBAccessException running my migrated Glassfish web application on Wildfly 8.2. I found the JBoss documentation all other than strait forward and need help, i.e. no link to JBoss documentation please.
I have no #DeclareRoles notation on my EJB to make it simple for now. I tried with and without using the security realm other adding jboss-web and jboss-ejb3 to tie the bean to a realm. But I still get the same exception.
I've read these tutorials, but can't get it to work. I am using MongoDB and JDBC security realm setup don't help me much. But for now I bypass the user-role authentication.
Migrating a Java EE App from GlassFish to WildFly
Invoke EJB from WildFly safely
And others
How can I run local EJB on Wildfly in my web application?
#Stateless
public class MyBean {
public String sayHello() {
...
jboss-web.xml
<jboss-web>
<security-domain>other</security-domain>
</jboss-web>
jboss-ejb3.xml
<assembly-descriptor>
<s:security>
<!-- Even wildcard * is supported -->
<ejb-name>*</ejb-name>
<!-- Name of the security domain which is configured in the EJB3 subsystem -->
<s:security-domain>other</s:security-domain>
</s:security>
</assembly-descriptor>
In WildFly 8, such methods which have no explicit security configurations, in a secured bean, will be treated similar to a method with #DenyAll configuration.
This behaviour can be controlled via the jboss-ejb3.xml deployment descriptor at a per bean level or a per deployment level as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss:jboss
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="urn:security:1.1"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<!-- Even wildcard * is supported where * is equivalent to all EJBs in the deployment -->
<ejb-name>FooBean</ejb-name>
<s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
</s:security>
</assembly-descriptor>
</jboss:jboss>
Setting missing-method-permissions-deny-access to false allows access to such methods for all users i.e. the behaviour will be switched to be similar to #PermitAll.

JSF 1.2 application not getting deployed on websphere 8.5

I am trying to deploy JSF 1.2 application on WAS 8.5 server. But it is throwing below error on deployment.
Note: In the WAS admin, Under JSF implementation use console, I have selected the "Sun Reference Implementation 1.2 " option . But still problem persist.
[12/17/14 15:12:41:222 PST] 00000095 webapp E com.ibm.ws.webcontainer.webapp.WebApp notifyServletContextDestroyed SRVE0285E: Exception caught while destroying context: {0}
java.lang.IllegalStateException: No Factories configured for this Application. This happens if the faces-initialization does not work at all - make sure that you properly include all configuration settings necessary for a basic faces application and that all the necessary libs are included. Also check the logging output of your web application and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use some special web-containers which do not support registering context-listeners via TLD files and a context listener is not setup in your web.xml.
A typical config looks like this;
<listener>
<listener- class> org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:196)
at org.apache.myfaces.context.servlet.FacesContextImplBase.getApplication(FacesContextImplBase.java:131)
at org.apache.myfaces.webapp.AbstractFacesInitializer._dispatchApplicationEvent(AbstractFacesInitializer.java:261)
at org.apache.myfaces.webapp.AbstractFacesInitializer.destroyFaces(AbstractFacesInitializer.java:293)
at org.apache.myfaces.webapp.StartupServletContextListener.contextDestroyed(StartupServletContextListener.java:153)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextDestroyed(WebApp.java:1748)
You should restart the application server (not just the app). You should also make sure jsf-api.api and jsf-impl.jar are not in WEB-INF/lib of your app.

Oracle WebLogic GroovyServlet Error

We have a J2EE app running beautifully on tomcat-based app servers, but all groovy scripts seem to fail on weblogic (10.3.5.0) and also IBM WebSphere. It seems the script processing, not the content of the scripts are the issue. The app itsells is a spring MVC web app and the GroovyServlet is part of the web.xml descriptor:
<!-- Servlets -->
<servlet>
<servlet-name>Groovlet</servlet-name>
<servlet-class>groovy.servlet.GroovyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Groovlet</servlet-name>
<url-pattern>*.groovy</url-pattern>
</servlet-mapping>
Calling a simple executor.groovy file results in an exception. My test script is small:
response.contentType = "application/json"
out.println "test"
But fails:
GroovyServlet Error: script: '/executor.groovy': Script processing failed.null
java.lang.NullPointerException
Anyone has a solution? Are there general issues with Groovy on weblogic or websphere?
Don't know if you're still having this issue :)
I had the same problem - the NullPointerException is caused by ServletContext.getRealPath(...) returning null.
There is a setting in Weblogic admin console which controls whether getRealPath() can be used.
It can also be configured in your weblogic.xml file by inserting the following (not sure how to deal with this in Websphere).
<container-descriptor>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
</container-descriptor>
Sounds like response or out are not properly binded in weblogic. Did you try your servlet on another container. Also publishing more about the stacktrace and the web.xml could help

How to use htpasswd protection in Tomcat?

I have already created a user database file using Apache's htpasswd command. This file is now used by several other application like apache and subversion.
Users in are created like this:
htpasswd /path/to/users.htpasswd peter
This user file is global, not per directory.
How I can make Tomcat 6 use this same file as a security realm?
Most similar to the htpasswd may be the MemoryRealm.
I had problems myself to find a simple example how to use it, so I'll post an easy example code here:
Set up a role, username and password in tomcat-users.xml
Your web.xml should contain something like:
<security-constraint>
<web-resource-collection>
<web-resource-name>
My Protected WebSite
</web-resource-name>
<url-pattern> /* </url-pattern>
<http-method> GET </http-method>
<http-method> POST </http-method>
</web-resource-collection>
<auth-constraint>
<!-- the same like in your tomcat-users.conf file -->
<role-name> test </role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method> BASIC </auth-method>
<realm-name> Basic Authentication </realm-name>
</login-config>
<security-role>
<description> Test role </description>
<role-name> test </role-name>
</security-role>
Add this to your server.xml file:
<Realm className="org.apache.catalina.realm.MemoryRealm"></Realm>
To secure access to your Tomcat webapp, you can implement your simple security constraint (e.g. in /var/lib/tomcat7/webapps/*/WEB-INF/web.xml) as below (just add it before </web-app> ending):
<!-- This security constraint protects your webapp interface. -->
<login-config>
<!-- Define the Login Configuration -->
<auth-method>BASIC</auth-method>
<realm-name>Webapp</realm-name>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<!-- Specifying a Secure Connection -->
<user-data-constraint>
<!-- transport-guarantee can be CONFIDENTIAL (forced SSL), INTEGRAL, or NONE -->
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- Authorization, see: tomcat-users.xml -->
<security-role>
<role-name>*</role-name>
</security-role>
The login-config element contains the auth-method element, which specifies the authentication method that we use, which is BASIC. The security-constraint element contains 3 elements: web-resource-collection, auth-constraint, and user-data-constraint. The web-resource-collection specifies the parts of our application that require authentication. The /* indicates that the whole application requires authentication. The auth-constraint specifies the role that a user needs to have in order to access the protected resources. The user-data-constraint's transport-guarantee can be NONE, CONFIDENTIAL or INTEGRAL. We set it to NONE, which means that redirecting to SSL is not required when you try to hit the protected resource.
Also make sure that you've line:
<Realm className="org.apache.catalina.realm.MemoryRealm" />
inside your conf/server.xml (Engine section).
If you have not changed any configuration files, please examine the file conf/tomcat-users.xml in your installation (locate tomcat-users.xml). That file must contain the credentials to let you use Tomcat webapp.
For example, to add the manager-gui role to a user named tomcat with a password of s3cret, add the following to the config file listed above:
<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>
Then you can access your webapps manager from /manager/html (e.g. reloading after config changes).
Read more: Manager App HOW-TO.
Then restart your Tomcat and when accessing your webapp, it should ask you for the right credentials.
See also:
HTTP Basic Authentication in Java at Oracle site
Specifying an Authentication Mechanism in Java at Oracle site
Realm Configuration HOW-TO at Apache Tomcat site
Setting up role based security in tomcat
How do I use Basic authentication with Tomcat?
There are two options:
Use Apache as a front end to the tomcat (using either mod_jk or mod_proxy_ajp) and the Apache do the authentication. You can find details on how to do so here
If you want the tomcat to do the authentication, then you need ot use something else than the htpasswd file. There are 4 ways to save the users' credentials - using database, JNDI/LDAP, an XML file or a JAAS provider. You can read about all the options in the Realm Configuration HOW-TO.

Resources