Issue with remember-me persistent token - spring-security

I have a issue when implement spring security remember-me persistent token.
Already successful implement remember-me persistent token, but issue occurs when user logout of system.
Here are implementation:
spring-security.xml
<global-method-security pre-post-annotations="enabled"/>
<http auto-config="true" use-expressions="true" >
...some url parten
<form-login login-page="/login.html"
authentication-failure-url="/loginfailed.html"
authentication-success-handler-ref="customAuthenticationHandler"/>
<logout logout-success-url="/logout.html" delete-cookies='JSESSIONID' />
<remember-me services-ref="pfRememberMeServices"
key="pf_token_key"/>
</http>
<beans:bean id="pfRememberMeServices"
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:property name="tokenRepository" ref="pfTokenRepository" />
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="tokenValiditySeconds" value="86400"/> <!-- alive in 1 day -->
<beans:property name="key" value="pf_token_key" />
<beans:property name="cookieName" value="mycookie" />
<beans:property name="alwaysRemember" value="true" />
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>
<beans:bean id="userDetailsService"
class="com.platform.authenticate.model.UserDetailsServiceImpl" >
</beans:bean>.
Token repository:
#Override
public void removeUserTokens(String userid) {
// TODO Auto-generated method stub
tokenDao.removeUserTokens(userid);
}
TokenDao:
#Transactional
public void removeUserTokens(final String username) {
//Session session = getSessionFactory().getCurrentSession();
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Token token =
(Token) session.createCriteria(Token.class)
.add(Restrictions.eq("username", username)).uniqueResult();
if (token != null) {
session.delete(token);
}
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e; // or display error message
} finally {
session.close();
}
}
When I login with the same user on two browsers, or two clients, there are two records in persistent_logins table as following:
"2JLIh8E8vifKOdlaidCIog==";"user12";"OKjbqqIAhx74JpmPsNQHaw==";"2013-07-03 16:19:05.12"
"gQ2EDtl87ZC6XSjV6cTYrA==";"user12";"iYrG7dlnjPyKxUz/hwQMdQ==";"2013-07-03 15:47:24.011"
Is my implementation is right when there are two record for the same user?
Then, when I logout from one browser, or one client, the removeUserTokens() function is fired, but:
Token token =
(Token) session.createCriteria(Token.class)
.add(Restrictions.eq("username", username)).uniqueResult();
with above code, I could not remove token for logout user by username, when there are 2 records of user12, it is not unique result.
If I force delete all user12, then all session/token for all clients will be deleted. It is not right?
So how could I remove session/token info for logout user only, but keep session/token for same user on others client?
I have already ask mr google but my issue is seem to be unique, could not find any same one out there.
If my implementation is wrong, please let me know.
Update:
Here are stack trace when I send j_spring_security_logout from one client:
exception
org.hibernate.NonUniqueResultException: query did not return a unique
result: 2
org.hibernate.impl.AbstractQueryImpl.uniqueElement(AbstractQueryImpl.java:899)
org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:369)

I got same implementation - i got same problem.
But no i decide to delete all tokens, because to look up token for definitely
List<Token> tokens = sessionFactory.getCurrentSession().createCriteria(Token.class)
.add(Restrictions.eq("username", username)).list();
if (tokens.size() > 0) {
for (Token token : tokens) {
sessionFactory.getCurrentSession().delete(token);
}
}

Related

Getting logged out in short time in mvc application

I have an ASP.NET MVC application and I have received complaints from users that they are getting logged out after a relatively short time.
I have the following settings in web.config but apparently it does not work.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
Any idea why this is not working?
I believe you have same issue as here
So you should place machine key in your Web.Config. Ex:
<configuration>
<system.web>
<machineKey decryptionKey="F6722806843145965513817CEBDECBB1F94808E4A6C0B2F2,IsolateApps" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45,IsolateApps" />
</system.web>
</configuration>
You can learn how to generate machine key here or here
If you want user stays login until his/her browser is open, I do a trick. I create an Action or any Handler like below, it just return some dummy text (ex: context.User.Identity.IsAuthenticated), and then use jQuery.get to request this. I keeps user login because browser keep sends requests:
Handler:
public class KeepAlive : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write(context.User.Identity.IsAuthenticated);
}
public bool IsReusable
{
get
{
return false;
}
}
}
MVC Action:
public bool KeppChecking()
{
return User.Identity.IsAuthenticated;
}
jQuery:
setInterval(function () {
$.get('/Ajax/KeepAlive.ashx');
}, 10000);

Redirection takes place , but url is not updated accordingly

i have used navigation rules , to navigate from one page to another in jsf . But the problem is the url is not getting updated though i used in faces-config page .
code snippet is below:
faces-config.xml :
<navigation-rule>
<display-name>faces/layout.xhtml</display-name>
<from-view-id>/faces/layout.xhtml</from-view-id>
<navigation-case>
<from-outcome>logout</from-outcome>
<to-view-id>/faces/logout.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
source.java
public String Logout() {
FacesContext facesContext = FacesContext.getCurrentInstance();
isLogged = false;
session = (HttpSession)facesContext.getExternalContext().getSession(false);
if(session != null)
{
session.setAttribute("username", "");
session.invalidate();
}
return "logout";
}
sample.xhtml :
<p:splitButton value="#{loginBean.getUsername()}" icon="ui-icon-person">
<p:menuitem value="Logout" icon="ui-icon-close" action="#{source.Logout()}" ajax="false"/>
</p:splitButton>
any help is always appreciated
Thanks in advance

Swagger REST API annotation not working on interface but working on implementation class

This is my Interface ClassA .java
#Path("/"+Paths.STORIES)
#ApiModel(value = "Name API")
#Api(value = "/stories", description = "Name API")
public interface ClassA {
#GET
#Path("/"+Paths.STORYID)
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Fetch Story by ID", notes = "More notes about this method")
#ApiResponses(value = {
#ApiResponse(code = 400, message = "Invalid ID supplied"),
#ApiResponse(code = 200, message = "Invalid ID supplied"),
})
public Response getNameFromID(#PathParam("nameId") String nameId);
}
this is my implementation class.
#Singleton
#Component
public class ClassB implements ClassA,InitializingBean{
#Override
#SuppressWarnings({ "unchecked", "rawtypes" })
public Response getNameFromID(final String nameId) {
Map NameResponse = new HashMap<String,Object>();
NameResponse.put("repsonseCode", "200");
NameResponse.put("errorCode", "");
return Response.status(200).entity(NameResponse).build();
}
}
Application-context.xml entry
<bean id="swaggerConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="com.razak.sample" />
<property name="version" value="1.0.0" />
<property name="basePath" value="http://localhost:8080/api" />
<property name="title" value="Petstore sample app" />
<property name="description" value="This is a app." />
<property name="contact" value="apiteam#wordnik.com" />
<property name="license" value="Apache 2.0 License" />
<property name="licenseUrl"
value="http://www.apache.org/licenses/LICENSE-2.0.html" />
<property name="scan" value="true" />
</bean>
web.xml entry
<param-name>swagger.version</param-name>
<param-value>1.1</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080/api</param-value>
</init-param>
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>com.wordnik.swagger.sample.util.ApiAuthorizationFilterImpl</param-value>
</init-param>
#Api(value = "/stories", description = "Story API") at class level and
#GET
#Path("/"+Paths.STORYID)
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Fetch Story by ID", notes = "More notes about this method")
#ApiResponses(value = {
#ApiResponse(code = 400, message = "Invalid ID supplied"),
#ApiResponse(code = 200, message = "Invalid ID supplied"),
})
When i moved these entry from interface to Implementation class.i m able to access rest endpoints in swagger.swagger is working.but when i placed that annotation in interface itself.it is not working.
This is an open issue: https://github.com/wordnik/swagger-core/issues/562
There is also an open issue to document how to override the default scanner: https://github.com/wordnik/swagger-core/issues/513
I have not tried this out yet, but I think the solution to both the issues is found in this solution: https://github.com/wordnik/swagger-core/wiki/Java-Setup-for-Spring---Jersey---JAX-RS
The trick is to get Swagger to use the ReflectiveJaxrsScanner instead of the DefaultJaxrsScanner.
In swagger-core-1.3.10, #Inherited has been added to the annotations, so I believe this will work now.

SpringSecurity - Best way to disable to perform "fake login"

I would like to find the best/elegant/handy way to enable/disable spring security for test and dev environment. I would like to use a property on db, if this property is set to ON then the authentication is mandatory, otherwise the user does not need to authenticate and it reaches the application homepage directly with all roles associated and fake user name/properties.
By the way, my application has a simple authentication strategy: the user logged previously via a different web-application that provides him links to access many other web-app. One of this link redirect to my web-app with a simple submit containing user name and roles, my security chain catches this informations and perform an automatic authentication.
Any suggestion will be appreciated ;)
Bye!
Dolfiz
Some snippet of my code...
SpringSecurityContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http use-expressions="true" auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<security:intercept-url pattern="/fakeLogin*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/authError*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/VAADIN**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:logout logout-url="/logout" logout-success-url="http://milan-ias-vs.usersad.everis.int/DMTest/" invalidate-session="true" />
<security:custom-filter position="PRE_AUTH_FILTER" ref="preAuthenticatedProcessingFilter" />
</security:http>
<bean id="preAuthenticatedProcessingFilterEntryPoint" class="it.ram.authentication.LinkForbiddenEntryPoint" />
<bean id="preAuthenticatedProcessingFilter" class="it.ram.authentication.PreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean class="it.ram.authentication.PreAuthenticatedUserDetailsService" />
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>
</beans>
PreAuthenticatedProcessingFilter.java:
public class PreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
private final static Log log = LogFactory.getLog(PreAuthenticatedProcessingFilter.class);
public PreAuthenticatedProcessingFilter() {
super();
log.debug("PreAuthenticatedProcessingFilter default constructor");
setAuthenticationDetailsSource(new CustomAuthenticationDetailsSource());
}
public PreAuthenticatedProcessingFilter(AuthenticationManager authenticationManager) {
log.debug("PreAuthenticatedProcessingFilter constructor with AuthMan arg");
setAuthenticationDetailsSource(new CustomAuthenticationDetailsSource());
}
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String userName = request.getParameter(Constants.REQUEST_USER_PARAM);
log.debug("getPreAuthenticatedPrincipal - Returning " +userName);
return userName;
}
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
log.debug("getPreAuthenticatedCredentials - Returning N/A");
return "N/A";
}
public static class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, SessionUserDetails> {
#Override
public SessionUserDetails buildDetails(HttpServletRequest request) {
log.debug("buildDetails");
// create container for pre-auth data
String role = request.getParameter(Constants.REQUEST_ROLE_PARAM);
return new SessionUserDetails(role);
}
}
}
PreAuthenticatedUserDetailsService.xml:
public class PreAuthenticatedUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
private final static Log log = LogFactory.getLog(PreAuthenticatedUserDetailsService.class);
#Override
public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws UsernameNotFoundException {
log.debug("loadUserDetails - token.getName(): " +token.getName());
SessionUserDetails sessionUserDetails = (SessionUserDetails) token.getDetails();
List<SimpleGrantedAuthority> authorities = sessionUserDetails.getAuthorities();
return new User(token.getName(), "N/A", true, true, true, true, authorities);
}
}
Take a look at:
org.springframework.security.web.authentication.RememberMeServices#autoLogin(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
Poke around here for an implementation:
http://git.springsource.org/spring-security/spring-security/trees/c12c43da9eb59b664bc995a38859c6acac621390/web/src/main/java/org/springframework/security/web/authentication/rememberme
SecurityContextHolder is the place to look if you have existing credentials and to then change or replace them.
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
// authentication contains existing (if set and non-null) maybe it is anonymous
// so then you might have a better set of credentials to replace it with
WebappUserDetails webappUserDetails = userContextService.getPrincipal(WebappUserDetails.class);
// The above constructs my custom type that implement spring UserDetails interface
// this is the identity of the user
// You should check things are valid (account enable and valid, etc..)
// Then you make a fake Authentication and attach it to the session context
// There are many token kinds in spring representing different ways to auth
// this token is the kind that might be used for a HTML form based login with
// username and password.
String principal = "myusername"; // username
String credentials = "mypassword"; // password
// Note you should probably not want to hardwire passwords into code and the correct
// way is to setup a new Token type and configure main security XML to allow it
// to the secure URLs (or secured subjects)
Authentication authRequest = new UsernamePasswordAuthenticationToken(principal, credentials);
Authentication authResult = authenticationManager.authenticate(authRequest);
// Check the authResult then attach it to the context
SecurityContextHolder.getContext().setAuthentication(authResult);

changing spring security logout-success-url programmatically

I need to redirect the user to 2 different logout urls based on his role. How do i go about doing this?
i am using spring security 2.0 and my xml looks something like this:
<s:http access-denied-page="/" >
<s:intercept-url pattern="/pages/SplashPage.jsf" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<s:intercept-url pattern="/pages/Home.jsf" access="ROLE_USER,ROLE_MERCHANT"/>
<s:anonymous/>
<s:form-login
login-page="/"
login-processing-url="/j_spring_security_check"
default-target-url="/pages/Home.jsf"
authentication-failure-url="/" always-use-default-target='false' />
<s:logout invalidate-session="true" logout-url="/pages/logout.jsf" logout-success-url="/" />
<s:concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="false"/>
</s:http>
I couldnt find any right way to do this, so i ended up with a hack:
dont invalidate-session
change the logout-success-url to special redirect controller
in that controller, pull the user session to tell the user type
invalidate the session
redirect to proper url for the usertype
EDIT - updated to a Spring Security 2.0 solution.
Replace the LogoutFilter with your a subclass the overrides doFilterHttp:
public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException,
ServletException {
if (requiresLogout(request, response)) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (logger.isDebugEnabled()) {
logger.debug("Logging out user '" + auth + "' and redirecting to logout page");
}
for (int i = 0; i < handlers.length; i++) {
handlers[i].logout(request, response, auth);
}
// Do role-specific logic here to determine targetUrl
sendRedirect(request, response, targetUrl);
return;
}
chain.doFilter(request, response);
}
Replace the LogoutFilter as follows:
<beans:bean id="myLogoutFilter" class="com.mycompany.MyLogoutFilter">
<custom-filter position="LOGOUT_FILTER"/>
</beans:bean>

Resources