Jump to content

Token-based Authentication - How to create new session when a new token is sent


marcelo.soares_1
Go to solution Solved by marcelo.soares_1,

Recommended Posts

Hi everyone,


 


I'm using a token based authentication to integrate jasperserver with my web application. I was successful using token to login my external users.


 


My problem is...


 


When jaspserver starts a session, I can't start a new session if I send a new token for other users. It's so bad, because if there is a active session, the next user passing on token, will be logged as the previours users. Jasperserver not log in and user's synchronization when a session is active. I don't know how to fix this problem. If two or more users share the same computer, may be dangerous. 


 


I think that a possible solution is change the jasperserver code to do authentication every time the token is sent. But, I don't  know how can I do.


 


Where is the implementation code, like a front controller, that decide if a synchronization will happen or not?


 


Can anyone help me?

Link to comment
Share on other sites

  • 2 weeks later...
  • Replies 4
  • Created
  • Last Reply

Top Posters In This Topic

It's not so bad as sessions expire.

You can set the following properties in

<bean id="proxyPreAuthenticatedProcessingFilter" class="com.jaspersoft.jasperserver.api.security.externalAuth.preauth.BasePreAuthenticatedProcessingFilter">[/code]
<property name="checkForPrincipalChanges" value="true"/>
<property name="invalidateSessionOnPrincipalChange" value="true"/>
 
These properties are coming from Spring class of which the bean class is a subclass.

 

Link to comment
Share on other sites

  • 3 months later...
getPreAuthenticatedPrincipal in BasePreAuthenticatedProcessingFilter returns null when no token is sent and so the principal is changed which invalidates the session. When there is no token getPreAuthenticatedPrincipal should return the authenticated user instead.
Link to comment
Share on other sites

  • 10 months later...
  • Solution

Hi everyone,

I found a solution to fix this issue. I needed to change the class BasePreAuthenticatedProcessingFilter.java.

Full path: /jasperserver-api-impl/externalAuth/src/main/java/com/jaspersoft/jasperserver/api/security/externalAuth/preauth/BasePreAuthenticatedProcessingFilter.java

Like I said, I changed the doFilter method to verify if a token was sent. If so, I get the user sent by token and I also catch the session's user. Then, I compare the users to know if the user that was sent by token is the same user from session or else if is a other user.

If is a different user, I invalidate the session and call super.doFilter(request, response, chain) normaly to do a new authentication. 

    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)            throws IOException, ServletException {        if(isJsonResponseRequested((HttpServletRequest) request)){            // it's visualize authentication. Correct JSON success response is required here.            // The only way to get correct redirect is to authenticate again. So, let's clear security context.            SecurityContextHolder.clearContext();        }                /**         * CHANGE'S START         * Veryfing if a new user was send by token         */        HttpSession session = ((HttpServletRequest) request).getSession(false);                Object principal = getPreAuthenticatedPrincipal((HttpServletRequest)request);                if(principal != null && session != null){//Token was send                        Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();                        String newUser = null;                        String preAuthTokenStr = principal.toString();            String[] tokenKeyValuePairs = preAuthTokenStr.split(tokenPairSeparator);                        //Getting the user from token            for (String tokenPair : tokenKeyValuePairs) {                String[] tokenPairArr = tokenPair.split(TOKEN_KEY_VALUE_PAIR_SEPARATOR);                if (tokenPairArr.length != 2) {                    logger.error("Invalid pre-authenticated token format. Pair " + tokenPair + " is missing key-value separator "                           + TOKEN_KEY_VALUE_PAIR_SEPARATOR + ". Skipping this pair processing.");                    continue;                }                final String tokenKey = tokenPairArr[0];                final String tokenValue = tokenPairArr[1];                final String[] tokenValuesArr = tokenValue.split(TOKEN_VALUE_SEPARATOR);                if (tokenKey.equalsIgnoreCase(String.valueOf(tokenFormatMapping.get(PREAUTH_USERNAME)))) {                    if (tokenValuesArr.length != 1)                        logger.warn("A list of users was passed in. Only one user is supported.  Using only the 1st user: " + tokenValuesArr[0]);                    newUser = tokenValuesArr[0];                }            }                        if (logger.isDebugEnabled()){                logger.debug("Main parameter was send. Check if is a new user: " + principal);                                      if(currentUser != null)                       logger.debug("currentUser: " + currentUser.getName());                                           if(newUser != null)                       logger.debug("newUser: " + newUser);            }                        if((currentUser != null && newUser != null) && (!currentUser.getName().equals(newUser))){                if (logger.isDebugEnabled())                    logger.debug("New user " + newUser + " different from " + currentUser.getName() + ". Destroy the session to do a new authenticate");                SecurityContextHolder.clearContext();                session.invalidate();            }        }        /**         * CHANGE'S END         */                super.doFilter(request, response, chain);    }[/code]

I also needed to add these methods in the same class:

        public void setTokenPairSeparator(String tokenPairSeparator) {        this.tokenPairSeparator = Pattern.quote(tokenPairSeparator);    }        public void setTokenFormatMapping(Map<String, Object> tokenFormatMapping) {        this.tokenFormatMapping = tokenFormatMapping;    }[/code]

... and classes variables:

    private Map<String,Object> tokenFormatMapping = new HashMap<String, Object>();    private String tokenPairSeparator = "\|";        public static final String TOKEN_KEY_VALUE_PAIR_SEPARATOR = "=";    public static final String TOKEN_VALUE_SEPARATOR = ",";        public static final String PREAUTH_USERNAME = "username";[/code]

... and imports:

import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.regex.Pattern;import javax.servlet.http.HttpSession;import org.apache.log4j.Logger;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;import com.jaspersoft.jasperserver.api.common.crypto.CipherI;import com.jaspersoft.jasperserver.api.common.crypto.PlainTextNonCipher;import com.jaspersoft.jasperserver.api.security.externalAuth.ExternalDataSynchronizer;[/code]

Remember you need to compile the application.

I hope it helps you!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...