Apache Shiro takes me back to login page after authentication - shiro

I am replacing Siteminder with Apache Shiro in my web application. I noticed that shiro logs me in successfully and takes me to the home page. When i click on any other link on the home page, I am taken back to the login page. I login again and i am forwarded to the page i was looking to goto. How can i fix this?
Here is my shiro.ini
[main]
authc.loginUrl = /login.jsp
ssl.enabled=false
[users]
user=admin
[urls]
/css/** = anon
/images/** = anon
/js/** = anon
/login.jsp = authc
/logout = logout
/** = authc
A section from my web.xml
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Printing out currentUser.isAuthenticated() in my User Class displays 'true'.
Is there any other info i can provide?

I believe the problem is related to the fact that in the shiro.ini file you are not enforcing SSL:
ssl.enabled=false
However, in the weblogic.xml file you are enforcing SSL for cookies:
<session-param>
<param-name>CookieSecure</param-name>
<param-value>true</param-value>
</session-param>
So, my recommendation would be to change shiro.ini to:
ssl.enabled=true
And leave the original weblogic.xml file in place.
That way you will only accept users who authenticated over SSL (which is a good practice).
Please let me know the results.
Thanks
Fabio #fcerullo

Your configuration looks almost exactly like the Shiro sample web app (in fact, yours is even better by using authc.loginUrl instead of the deprecated global 'shiro.loginUrl' that the sample app uses). The sample app does not exhibit the behavior you're seeing.
This leads me to believe that something else (another filter?) is causing problems for you. Do you have a little sample app that you can make available (maybe on Github) that demonstrates the problem? I'd be happy to take a look if this can be recreated.

I figured out what was going on. My application was deployed on Weblogic and i had the following section inside weblogic.xml which was causing the issue. Removing it, fixed it. Any idea why this caused it?
<session-param>
<param-name>CookieSecure</param-name>
<param-value>true</param-value>
</session-param>

I have experienced the same behaviour,but I am using Wildfly 10.0.0 , and apache shiro v 1.3.2.
I foun the solution here in this Jboss Forum article.
Setting the cookie name from JSESSIONID to something else fixes the issue.
The solution provided here was to add the following in shiro.ini
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = shiro.session.id
sessionManager.sessionIdCookie = $cookie
This worked for me.

Related

Pentaho CDA: Basic Authentication and CORS conflict

Working on a web app which queries Pentaho BI server 7 with a Tomcat 8 inside I'm facing some issues.
First of all to avoid CORS (Cross-origin resource sharing) problems I have added the CORS filter inside the web.xml config file of the tomcat:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Afterwards, everything was fine until it was necessary to get some resources through Pentaho CDA (Pentaho Community Data Access). I've added a Basic Auth header and one line in the plugin settings file (pentaho-solutions/system/cda/settings.xml):
<allow-cross-domain-resources>true</allow-cross-domain-resources>
Every request my aplication does gets the same error:
XMLHttpRequest cannot load http://localhost:8080/pentaho/plugin/cda/api/doQuery?path=/whatever/dashboard.cda&dataAccessId=mdxGetSmth. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:xxx' is therefore not allowed access. The response had HTTP status code 401.
The funny thing is that the same query is working in Postman (of course with the same Basic auth header) just because Postman just jumps over the OPTIONS (preflight) request.
Used Ngnix as Reverse proxy on Apache-Tomcat and resolved this CORS error

Apache Shiro Login not working as intended (Session get created before login)

I'm having trouble to get the login / logout features to work with my web application....
I'm using apache shiro 1.2 and my accpilcation is named SSP
here is my configuration:
EDIT: Updated Code
some code from web.xml:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
some code from shiro.ini: (Edit: changed url filter order)
[main]
shiro.loginUrl = /login.jsp
# this is my own AuthenticationFilter which works fine
authc = com.mycompany.ssp.AuthFilter
authc.failureKeyAttribute=shiroLoginFailure
# redirect after successful login
authc.successUrl = portal.jsp
######################################
# NOT ACTIVE CODE ####################
# login URL
#authc.loginUrl = /login.jsp
# redirect after logout
#logout.redirectUrl = /login.jsp
######################################
[urls]
# enable logout filter
/logout = logout
# enable authc filter for all application pages
/** = authc
some code from portal.jsp
Log out V2 </br>
I'm having 1 Problem and 1 issue that I dont understand:
Problem
When I visit my webapplication via https://localhost:8443/SSP/
I get a session id eventhough the user is not logged in yet:
https://localhost:8443/SSP/login.jsp;JSESSIONID=6560e585-d871-4839-a606-464b4b314457
Login works as intended, redirection to portal.jsp works
Here I just want to be redirected to https://localhost:8443/SSP/login.jsp without a session being created !!
EDIT:
My Session Management right now looks like this (shiro.ini
# SESSION MANAGEMENT #
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
# Use the configured native session manager:
securityManager.sessionManager = $sessionManager
# 3,600,000 milliseconds = 1 hour
securityManager.sessionManager.globalSessionTimeout = 3600000
########################################################################
# CACHE MANAGEMENT #
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager
Issue -> SOLVED thx to Markus K
The logout via the Link "Log out V2" which uses the LogoutFilter (configured in shiro.ini) works fine but I dont understand how I get redirected back to /SSP/login.jsp although the line logout.redirectUrl = /login.jsp in shiro.ini is not active??
My best guess here is that the line shiro.loginUrl = /login.jsp tells shiro "hey after a logout go here again", but I'm not sure.
Can anyone help me with this?
I am new to shiro too. But maybe I can help with some of your problems.
be able to log out the user via the LogoutFilter configured in shiro.ini
In your shiro.ini you configured to use the authc filter to be used for all incoming requests /**:
/** = authc
/logout = logout
This means that a request to a url like /logout will be passed through the authc filter and not through the logout filter as intended. Changing the filter order should solve the problem.
/logout = logout
/** = authc
See http://shiro.apache.org/web.html#Web-URLPathExpressions.
Regarding the logout servlet mapping in your web.xml. I'm not sure what you want to achieve there. I think you can just remove it and use the shiro logout filter as described above.
Show user login.jsp when he visits the wep applicaton page
login the user
Restricting all urls and providing a login.jsp should solve it. As I said, I am new to shiro too. So instead of giving possibly erroneous explanations I give you a configuration which works for me for the described requirenments.
[main]
shiro.loginUrl = /login.jsp
[urls]
/login.jsp = authc
/logout = logout
/specific/url = authc, roles[ADMIN]
/** = authc
See the order of the rules. Put the more specific rules first and the more general rules last.

FORM scope always empty? URL scope is fine?

I'm running a legacy CF Fusebox 5.5 app within Railo 4.0.2.002 Express with Jetty 8 on Mac OS X 10.8 with java 1.7.
I'm also using jetty urlrewrite http://tuckey.org/urlrewrite/ (if that's relevant)
Why is the FORM scope always blank upon form submissions? But if I use the URL scope it works fine.
The app has worked fine in all other versions of CF and should also work fine here.
UPDATE 1:
Also, when I do onRequestStart within Application.cfc and I dump the FORM scope it's empty there too.
Anyone have trouble with this? I don't think it's necessarily "fusebox" so I'm wondering if it's a Railo 4 compatibility issue?
UPDATE 2:
When the form posts to /admin/index.cfm?event=Main.Login
the form scope work fine. But when it posts to /admin/event/Main.Login the form scope is gone.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
"http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite>
<rule>
<from>^/admin/event/(.*)</from>
<to last="false">/admin/index.cfm?event=$1</to>
</rule>
<rule>
<from>^/lms/event/(.*)</from>
<to last="false">/lms/index.cfm?event=$1</to>
</rule>
</urlrewrite>
UPDATE 3:
It should also be noted that Charles (proxy) is properly detecting the 'POST' Request contains the Email / Password and other form elements properly sent to the server.
The Jetty server is simply not seeing them or not properly forwarding them on to the Railo engine or something?
UPDATE 4:
Here is the tuckey configuration that they tell you to place in your web.xml. I actually placed this in the webdefault.xml in etc/ directory of Railo Express which I guess could just be Jetty files.
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
I had a number of issues with Tuckey and ended up using Apache and modrewrite for features that Tuckey just didn't support. That being said Railo + Tomcat/Jetty is not ColdFusion with Jrun and the configuration was challenging to ensure that mod_rewrite had all the request information and even had the request at all. Even Adobe had to patch CF10 after release because they were missing original functionality from CF9-+JRUN connectors.
However, for your solution, you need to reach up and out. See the thread here.
https://groups.google.com/forum/#!msg/railo/uw-U9hCFu5k/bEmr_I2Kl8sJ
Other people have the same problem, and have worked around it by placing this in onRequestStart:
<cfscript>
if(gethTTPRequestData().method eq "POST") {
if(NOT structKeyExists(form,"fieldnames")) {
var paramMap = getPageContext().getRequest().getParameterMap();
var paramMapKeys = structKeyList(paramMap);
form.fieldnames = paramMapKeys;
for(x =1; x lte listLen(paramMapKeys); x++) {
param = listGetAt(paramMapKeys,x);
form[param] = paramMap[param][1];
}
}
}
</cfscript>
It's not clear if this is a bug in Jetty, Railo, or Tuckey.

Securing Glassfish REST Service with basic auth using annotations

I have been trying to secure an application, which is deployed to glassfish 3 using annotation instead of the deployment descriptor. However, I haven't been able to get it working correctly. If I try to access the service, I end up with a server error 500, which displays this message:
type Exception report
message
descriptionThe server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: javax.ejb.AccessLocalException: Client not authorized for this invocation
root cause
javax.ejb.AccessLocalException: Client not authorized for this invocation
The EJB looks like this:
#Path("/myresource")
#Stateless
#RolesAllowed("user-role")
public class MyResource {
#GET
#Path("/{uuid}")
public Response getData(#PathParam("uuid") final String uuid) {
....
}
}
sun-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN"
"http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app>
<security-role-mapping>
<role-name>user-role</role-name>
<group-name>user-group</group-name>
</security-role-mapping>
</sun-web-app>
This is the web.xml:
<web-app id="myservice" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>org.test.myservice</display-name>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.test.myservice.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>file</realm-name>
</login-config>
<security-role>
<role-name>user-role</role-name>
</security-role>
</web-app>
The file realm in glassfish is set up using the user and role specified in the sun-web.xml and has been working well, when setting up the application security via deployment descriptor.
If I understand this document correctly I do not have to link security role references if their names are the same. http://docs.oracle.com/javaee/5/tutorial/doc/bnbyl.html#bnbyt
Any ideas what I am missing?
Edit
Related to the problem of not being able to specify the required information with annotations, there is a another problem, which caused me to think about this issue. Maybe that will make the initial question a little clearer:
Taken above example, the resource /myresource/* is only available for users with role 'user-role'. However, if there is a second resource at path /myresource/*/thumbnail (translating to /myresource/[uuid]/thumbnail) which should be available without authentication, this is not possible by specifying security-constraints with url-mapping, since it does not seem to be possible to use the wildcard between constants. However, this would be doable by specifying the roles, that are allowed to access a method by annotions. As described above, I haven't been able to do so. How could a mapping like that be done?
You need to use the security-constraint element in web.xml descriptor in order to block specific resources and paths, and to specify the authorization constraints.
This doesn't mean that you can't add more fine-grained controls using Programmatic Security, as explained in Oracle's Java EE 6 Tutorial:
Programmatic security is embedded in an application and is used to make security decisions. Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application.
As per your edited question.
I would use the security-constraint element for blocking the access to all non-registered users. This will force everybody to authenticate, so that your application knows the roles they have.
Then you can fine-grain control the access to the various resources using programmatic security.
With basic authentication I guess there are no other ways. If you want to avoid authentication for basic users, you need to go with form authentication and handle the authentication programmatically behind the scenes, authenticating them even if they aren't aware of, by using HttpServletRequest#login().
In both ways you should be able to setup rights in the way you have described. If you want to handle the unauthorized exception more smoothly, you'd better remove the #RolesAllowed annotation and instead use something like:
#GET
#Path("/{uuid}")
public Response getData(#PathParam("uuid") final String uuid, #Context SecurityContext sc) {
if (sc.isUserInRole("MyRole")) {
return result;
} else {
return notAllowedResult;
}
}
The Roles-Allowed is an EJB construct and not congruent with access to the resource, which is handled by the security constraint.
Unfortunately, the two security concepts do not mesh as well as they should, and instead of getting a 401 if you're not authorized (a web concept), you get the security exception that you are receiving (and EJB concept). In fact, I don't know what error you will receive if you annotate an EJB web service with a RolesAllowed and try to access the web service with an invalid role. I assume you'll get a SOAP fault, in that case.
The EJB security is a system that keeps unauthorized people out, but it's a last ditch effort. It assumes that any decisions to route folks to the method calls is already done up front. For example, there's no high level way to test if a method is allowed or not, rather you can only call it and catch the exception.
So the harsh truth is beyond coarse gatekeepers, you want to leverage Programmatic Security.

Rest - Jersey.Client pass #SecurityContext to Server

I want to pass a security context to my rest service.
On server side I try to get this with:
public Response postObject(#Context SecurityContext security, JAXBElement<Object> object) {
System.out.println("Security Context: " + security.getUserPrincipal());
.....
But actually the Syso is null.
On Client side im just doing:
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.addFilter(new HTTPBasicAuthFilter("user", "password"));
So, do I have to change in addition something in my web.xml to get it working?
I hoped its working without setting up static users in the tomcat user xml. So I can compare the user/password from security context with my "persistent" user/password hashmap located server sided. But when it is not working without tomcat user xml, how can it be done to add dynamically user to that user xml? When I ve static users I cant register a new user. I dont want to use this attempt: http://objecthunter.congrace.de/tinybo/blog/articles/89 cuz I want just to work with a semi persistence like a HashMap of user/password.
Besides another question: Why does everybody refer to Apache HttpClient when it is about security in Jersey, when it is working like I wrote as well?
My attempt refers to this post:
Jersey Client API - authentication
You need to set up your application on the server so that it requires Basic authentication. I.e. include something like the following in the web.xml in your application war file - otherwise Tomcat does not perform the authentication and does not populate the security context.
<security-constraint>
<display-name>Authentication Constraint</display-name>
<web-resource-collection>
<web-resource-name>all</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>authentication required</description>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>realm_name</realm-name>
</login-config>