jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bae...@apache.org
Subject svn commit: r1574098 - in /jackrabbit/branches/2.6: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/...
Date Tue, 04 Mar 2014 13:43:29 GMT
Author: baedke
Date: Tue Mar  4 13:43:28 2014
New Revision: 1574098

URL: http://svn.apache.org/r1574098
Log:
JCR-3687 : Backport improvements made to token based auth in OAK

Added:
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/CompatTokenProvider.java
      - copied unchanged from r1537027, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/CompatTokenProvider.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenInfo.java
      - copied unchanged from r1537027, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenInfo.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenProvider.java
      - copied unchanged from r1537027, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenProvider.java
    jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationCompatTest.java
      - copied unchanged from r1537027, jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationCompatTest.java
Modified:
    jackrabbit/branches/2.6/   (props changed)
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DefaultLoginModule.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthentication.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
    jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TestAll.java
    jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationTest.java

Propchange: jackrabbit/branches/2.6/
------------------------------------------------------------------------------
  Merged /jackrabbit/trunk:r1537027

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
Tue Mar  4 13:43:28 2014
@@ -16,10 +16,17 @@
  */
 package org.apache.jackrabbit.core;
 
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.retention.RetentionManagerImpl;
 import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.authentication.token.TokenProvider;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
 import org.apache.jackrabbit.core.security.user.UserManagerImpl;
@@ -30,12 +37,6 @@ import org.apache.jackrabbit.core.value.
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.ItemExistsException;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-
 /**
  * <code>ProtectedItemModifier</code>: An abstract helper class to allow classes
  * residing outside of the core package to modify and remove protected items.
@@ -58,6 +59,7 @@ public abstract class ProtectedItemModif
         if (!(UserManagerImpl.class.isAssignableFrom(cl) ||
               RetentionManagerImpl.class.isAssignableFrom(cl) ||
               ACLEditor.class.isAssignableFrom(cl) ||
+              TokenProvider.class.isAssignableFrom(cl) ||
               org.apache.jackrabbit.core.security.authorization.principalbased.ACLEditor.class.isAssignableFrom(cl)))
{
             throw new IllegalArgumentException("Only UserManagerImpl, RetentionManagerImpl
and ACLEditor may extend from the ProtectedItemModifier");
         }

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DefaultLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DefaultLoginModule.java?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DefaultLoginModule.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/DefaultLoginModule.java
Tue Mar  4 13:43:28 2014
@@ -16,29 +16,25 @@
  */
 package org.apache.jackrabbit.core.security.authentication;
 
+import java.security.Principal;
+import java.util.Map;
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
 import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
-import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.security.authentication.token.TokenBasedAuthentication;
-import org.apache.jackrabbit.core.security.user.UserImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.FailedLoginException;
-import javax.security.auth.login.LoginException;
-import java.security.Principal;
-import java.util.Map;
-
 /**
  * The <code>DefaultLoginModule</code> authenticates Credentials related to
  * a {@link User} of the Repository<br>
@@ -229,20 +225,7 @@ public class DefaultLoginModule extends 
             // special token based login
             tokenCredentials = ((TokenCredentials) credentials);
             try {
-                Node n = TokenBasedAuthentication.getTokenNode(tokenCredentials, session);
-                final NodeImpl userNode = (NodeImpl) n.getParent().getParent();
-                final String principalName = userNode.getProperty(UserImpl.P_PRINCIPAL_NAME).getString();
-                if (userNode.isNodeType(UserImpl.NT_REP_USER)) {
-                    Authorizable a = userManager.getAuthorizable(new ItemBasedPrincipal()
{
-                        public String getPath() throws RepositoryException {
-                            return userNode.getPath();
-                        }
-                        public String getName() {
-                            return principalName;
-                        }
-                    });
-                    return a.getID();
-                }
+                return TokenBasedAuthentication.getUserId(tokenCredentials, session);
             } catch (RepositoryException e) {
                 if (log.isDebugEnabled()) {
                     log.warn("Failed to retrieve UserID from token-based credentials", e);

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthentication.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthentication.java?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthentication.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthentication.java
Tue Mar  4 13:43:28 2014
@@ -16,41 +16,22 @@
  */
 package org.apache.jackrabbit.core.security.authentication.token;
 
+import java.util.Date;
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
-import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.id.NodeIdFactory;
-import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.authentication.Authentication;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.util.ISO8601;
-import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * Authentication implementation that compares the tokens stored with a
  * given user node to the token present in the SimpleCredentials attributes.
@@ -72,60 +53,29 @@ public class TokenBasedAuthentication im
      */
     public static final String TOKEN_ATTRIBUTE = ".token";
 
-    private static final String TOKEN_ATTRIBUTE_EXPIRY = TOKEN_ATTRIBUTE + ".exp";
-    private static final String TOKEN_ATTRIBUTE_KEY = TOKEN_ATTRIBUTE + ".key";
-    private static final String TOKENS_NODE_NAME = ".tokens";
-    private static final String TOKENS_NT_NAME = "nt:unstructured"; // TODO: configurable
-
-    private static final char DELIM = '_';
-
-    private final String token;
-    private final long tokenExpiration;
-    private final Session session;
-
-    private final Map<String, String> attributes;
-    private final Map<String, String> info;
-    private final long expiry;
-    private final String key;
+    /**
+     * @deprecated This system parameter allows to enable backwards compatible
+     * behavior of the {@code TokenBasedAuthentication}. Note that as of OAK 1.0
+     * this flag will no be supported.
+     */
+    public static final String PARAM_COMPAT = "TokenCompatMode";
+
+    private final TokenInfo tokenInfo;
 
     public TokenBasedAuthentication(String token, long tokenExpiration, Session session)
throws RepositoryException {
-        this.session = session;
-        this.tokenExpiration = tokenExpiration;
-        this.token = token;
-        long expTime = Long.MAX_VALUE;
-        String keyV = null;
-        if (token != null) {
-            attributes = new HashMap<String, String>();
-            info = new HashMap<String, String>();
-
-            Node n = getTokenNode(token, session);
-            PropertyIterator it = n.getProperties();
-            while (it.hasNext()) {
-                Property p = it.nextProperty();
-                String name = p.getName();
-                if (TOKEN_ATTRIBUTE_EXPIRY.equals(name)) {
-                    expTime = p.getLong();
-                } else if (TOKEN_ATTRIBUTE_KEY.equals(name)) {
-                    keyV = p.getString();
-                } else if (isMandatoryAttribute(name)) {
-                    attributes.put(name, p.getString());
-                } else if (isInfoAttribute(name)) {
-                    info.put(name, p.getString());
-                } // else: jcr property -> ignore
-            }
+        if (compatMode()) {
+            this.tokenInfo = new CompatTokenProvider((SessionImpl) session, tokenExpiration).getTokenInfo(token);
         } else {
-            attributes = Collections.emptyMap();
-            info = Collections.emptyMap();
+            this.tokenInfo = new TokenProvider((SessionImpl) session, tokenExpiration).getTokenInfo(token);
         }
-        expiry = expTime;
-        key = keyV;
+
     }
 
     /**
      * @see Authentication#canHandle(javax.jcr.Credentials)
      */
     public boolean canHandle(Credentials credentials) {
-        return token != null && isTokenBasedLogin(credentials);
+        return tokenInfo != null && isTokenBasedLogin(credentials);
     }
 
     /**
@@ -136,105 +86,31 @@ public class TokenBasedAuthentication im
             throw new RepositoryException("TokenCredentials expected. Cannot handle " + credentials.getClass().getName());
         }
         TokenCredentials tokenCredentials = (TokenCredentials) credentials;
+        return validateCredentials(tokenCredentials);
+    }
 
-        // credentials without userID -> check if attributes provide
-        // sufficient information for successful authentication.
-        if (token.equals(tokenCredentials.getToken())) {
-            long loginTime = new Date().getTime();
-            // test if the token has already expired
-            if (expiry < loginTime) {
-                // already expired -> login fails.
-                // ... remove the expired token node before aborting the login
-                removeToken();
-                return false;
-            }
-
-            // test for matching key
-            if (key != null && !key.equals(getDigestedKey(tokenCredentials))) {
-                return false;
-            }
-
-            // check if all other required attributes match
-            for (String name : attributes.keySet()) {
-                if (!attributes.get(name).equals(tokenCredentials.getAttribute(name))) {
-                    // no match -> login fails.
-                    return false;
-                }
-            }
-
-            // update set of informative attributes on the credentials
-            // based on the properties present on the token node.
-            Collection<String> attrNames = Arrays.asList(tokenCredentials.getAttributeNames());
-            for (String key : info.keySet()) {
-                if (!attrNames.contains(key)) {
-                    tokenCredentials.setAttribute(key, info.get(key));
-                }
-            }
+    private boolean validateCredentials(TokenCredentials tokenCredentials) throws RepositoryException
{
+        if (tokenInfo == null) {
+            log.debug("No valid TokenInfo for token.");
+            return false;
+        }
 
-            // update token node if required: optionally resetting the expiration
-            updateTokenNode(expiry, loginTime);
+        long loginTime = new Date().getTime();
+        if (tokenInfo.isExpired(loginTime)) {
+            // token is expired
+            log.debug("Token is expired");
+            tokenInfo.remove();
+            return false;
+        }
 
+        if (tokenInfo.matches(tokenCredentials)) {
+            tokenInfo.resetExpiration(loginTime);
             return true;
         }
 
-        // wrong credentials that cannot be compared by this authentication
         return false;
     }
 
-    /**
-     * Performs the following checks/updates:
-     * <ol>
-     * <li>Reset the expiration if half of the expiration has passed in order to
-     * minimize write operations (avoid resetting upon each login).</li>
-     * </ol>
-     *
-     * @param tokenExpiry
-     * @param loginTime
-     */
-    private void updateTokenNode(long tokenExpiry, long loginTime) {
-        Node tokenNode;
-        Session s = null;
-        try {
-            // expiry...
-            if (tokenExpiry - loginTime <= tokenExpiration/2) {
-                long expirationTime = loginTime + tokenExpiration;
-                Calendar cal = GregorianCalendar.getInstance();
-                cal.setTimeInMillis(expirationTime);
-
-                s = ((SessionImpl) session).createSession(session.getWorkspace().getName());
-                tokenNode = getTokenNode(token, s);
-                tokenNode.setProperty(TOKEN_ATTRIBUTE_EXPIRY, s.getValueFactory().createValue(cal));
-                s.save();
-            }
-        } catch (RepositoryException e) {
-            log.warn("Failed to update expiry or informative attributes of token node.",
e);
-        } finally {
-            if (s != null) {
-                s.logout();
-            }
-        }
-    }
-
-    /**
-     * Remove the node associated with the expired token defined by this TokenBasedAuthentication.
-     */
-    private void removeToken() {
-        Session s = null;
-        try {
-            s = ((SessionImpl) session).createSession(session.getWorkspace().getName());
-            Node tokenNode = getTokenNode(token, s);
-            
-            tokenNode.remove();
-            s.save();
-        } catch (RepositoryException e) {
-            log.warn("Internal error while removing token node.", e);
-        } finally {
-            if (s != null) {
-                s.logout();
-            }
-        }
-    }
-
     //--------------------------------------------------------------------------
     /**
      * Returns <code>true</code> if the given <code>credentials</code>
object
@@ -251,28 +127,17 @@ public class TokenBasedAuthentication im
     /**
      * Returns <code>true</code> if the specified <code>attributeName</code>
      * starts with or equals {@link #TOKEN_ATTRIBUTE}.
-     *  
+     *
      * @param attributeName
      * @return <code>true</code> if the specified <code>attributeName</code>
      * starts with or equals {@link #TOKEN_ATTRIBUTE}.
      */
     public static boolean isMandatoryAttribute(String attributeName) {
-        return attributeName != null && attributeName.startsWith(TOKEN_ATTRIBUTE);
-    }
-
-    /**
-     * Returns <code>false</code> if the specified attribute name doesn't have
-     * a 'jcr' or 'rep' namespace prefix; <code>true</code> otherwise. This is
-     * a lazy evaluation in order to avoid testing the defining node type of
-     * the associated jcr property.
-     *
-     * @param propertyName
-     * @return <code>true</code> if the specified property name doesn't seem
-     * to represent repository internal information.
-     */
-    private static boolean isInfoAttribute(String propertyName) {
-        String prefix = Text.getNamespacePrefix(propertyName);
-        return !Name.NS_JCR_PREFIX.equals(prefix) && !Name.NS_REP_PREFIX.equals(prefix);
+        if (compatMode()) {
+            return CompatTokenProvider.isMandatoryAttribute(attributeName);
+        } else {
+            return TokenProvider.isMandatoryAttribute(attributeName);
+        }
     }
 
     /**
@@ -305,122 +170,48 @@ public class TokenBasedAuthentication im
      * creating the token node.
      */
     public static Credentials createToken(User user, SimpleCredentials credentials,
-                                                       long tokenExpiration, Session session)
throws RepositoryException {
+                                          long tokenExpiration, Session session) throws RepositoryException
{
         String workspaceName = session.getWorkspace().getName();
         if (user == null) {
             throw new RepositoryException("Cannot create login token: No corresponding node
for 'null' user in workspace '" + workspaceName + "'.");
         }
-        String userPath = null;
-        Principal pr = user.getPrincipal();
-        if (pr instanceof ItemBasedPrincipal) {
-            userPath = ((ItemBasedPrincipal) pr).getPath();
-        }
-
-        TokenCredentials tokenCredentials;
-        if (userPath != null && session.nodeExists(userPath)) {
-            Node userNode = session.getNode(userPath);
-            Node tokenParent;
-            if (!userNode.hasNode(TOKENS_NODE_NAME)) {
-                userNode.addNode(TOKENS_NODE_NAME, TOKENS_NT_NAME);
-                try {
-                    session.save();
-                } catch (RepositoryException e) {
-                    // may happen when .tokens node is created concurrently
-                    session.refresh(false);
-                }
-            }
-            tokenParent = userNode.getNode(TOKENS_NODE_NAME);
-
-            long creationTime = new Date().getTime();
-            long expirationTime = creationTime + tokenExpiration;
-
-            Calendar cal = GregorianCalendar.getInstance();
-            cal.setTimeInMillis(creationTime);
 
-            // generate key part of the login token
-            String key = generateKey(8);
-
-            // create the token node
-            String tokenName = Text.replace(ISO8601.format(cal), ":", ".");
-            Node tokenNode;
-            // avoid usage of sequential nodeIDs
-            if (System.getProperty(NodeIdFactory.SEQUENTIAL_NODE_ID) == null) {
-                tokenNode = tokenParent.addNode(tokenName);
-            } else {
-                tokenNode = ((NodeImpl) tokenParent).addNodeWithUuid(tokenName, NodeId.randomId().toString());
-            }
-
-            StringBuilder sb = new StringBuilder(tokenNode.getIdentifier());
-            sb.append(DELIM).append(key);
+        TokenInfo ti;
+        if (compatMode()) {
+            ti = new CompatTokenProvider((SessionImpl) session, tokenExpiration).createToken(user,
credentials);
+        } else {
+            ti = new TokenProvider((SessionImpl) session, tokenExpiration).createToken(user,
credentials);
+        }
 
-            String token = sb.toString();
-            tokenCredentials = new TokenCredentials(token);
-            credentials.setAttribute(TOKEN_ATTRIBUTE, token);
-
-            // add key property
-            tokenNode.setProperty(TOKEN_ATTRIBUTE_KEY, getDigestedKey(key));
-
-            // add expiration time property
-            cal.setTimeInMillis(expirationTime);
-            tokenNode.setProperty(TOKEN_ATTRIBUTE_EXPIRY, session.getValueFactory().createValue(cal));
-
-            // add additional attributes passed in by the credentials.
-            for (String name : credentials.getAttributeNames()) {
-                if (!TOKEN_ATTRIBUTE.equals(name)) {
-                    String value = credentials.getAttribute(name).toString();
-                    tokenNode.setProperty(name, value);
-                    tokenCredentials.setAttribute(name, value);
-                }
-            }
-            session.save();
-            return tokenCredentials;
+        if (ti != null) {
+            return ti.getCredentials();
         } else {
-            throw new RepositoryException("Cannot create login token: No corresponding node
for User " + user.getID() +" in workspace '" + workspaceName + "'.");
+            throw new RepositoryException("Cannot create login token.");
         }
     }
 
     public static Node getTokenNode(TokenCredentials credentials, Session session) throws
RepositoryException {
-        return getTokenNode(credentials.getToken(), session);
+        if (compatMode()) {
+            return CompatTokenProvider.getTokenNode(credentials.getToken(), session);
+        } else {
+            return TokenProvider.getTokenNode(credentials.getToken(), session);
+        }
     }
 
-    private static Node getTokenNode(String token, Session session) throws RepositoryException
{
-        int pos = token.indexOf(DELIM);
-        String id = (pos == -1) ? token : token.substring(0, pos);
-        return session.getNodeByIdentifier(id);
-    }
-
-    private static String generateKey(int size) {
-        SecureRandom random = new SecureRandom();
-        byte key[] = new byte[size];
-        random.nextBytes(key);
-
-        StringBuffer res = new StringBuffer(key.length * 2);
-        for (byte b : key) {
-            res.append(Text.hexTable[(b >> 4) & 15]);
-            res.append(Text.hexTable[b & 15]);
-        }
-        return res.toString();
-    }
-
-    private static String getDigestedKey(TokenCredentials tc) throws RepositoryException
{
-        String tk = tc.getToken();
-        int pos = tk.indexOf(DELIM);
-        if (pos > -1) {
-            return getDigestedKey(tk.substring(pos+1));
-        }     
-        return null;
-    }
-
-    private static String getDigestedKey(String key) throws RepositoryException {
-        try {
-            StringBuilder sb = new StringBuilder();
-            sb.append("{").append(SecurityConstants.DEFAULT_DIGEST).append("}");
-            sb.append(Text.digest(SecurityConstants.DEFAULT_DIGEST, key, "UTF-8"));
-            return sb.toString();
-        } catch (NoSuchAlgorithmException e) {
-            throw new RepositoryException("Failed to generate login token.");
-        } catch (UnsupportedEncodingException e) {
-            throw new RepositoryException("Failed to generate login token.");
+
+    public static String getUserId(TokenCredentials tokenCredentials, Session session) throws
RepositoryException {
+        if (compatMode()) {
+            return CompatTokenProvider.getUserId(tokenCredentials, session);
+        } else {
+            if (!(session instanceof JackrabbitSession)) {
+                throw new RepositoryException("JackrabbitSession expected");
+            }
+            NodeImpl n = (NodeImpl) getTokenNode(tokenCredentials, session);
+            return TokenProvider.getUserId(n, ((JackrabbitSession) session).getUserManager());
         }
     }
+
+    private static boolean compatMode() {
+        return Boolean.parseBoolean(System.getProperty(PARAM_COMPAT));
+    }
 }
\ No newline at end of file

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
Tue Mar  4 13:43:28 2014
@@ -627,3 +627,12 @@
   mixin
   - rep:hold (UNDEFINED) protected  multiple IGNORE
   - rep:retentionPolicy (UNDEFINED) protected IGNORE
+
+// -----------------------------------------------------------------------------
+// Token Management (backported from oak)
+// -----------------------------------------------------------------------------
+[rep:Token] > mix:referenceable
+  - rep:token.key (STRING) protected mandatory
+  - rep:token.exp (DATE) protected mandatory
+  - * (UNDEFINED) protected
+  - * (UNDEFINED) multiple protected

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TestAll.java?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TestAll.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TestAll.java
Tue Mar  4 13:43:28 2014
@@ -32,6 +32,7 @@ public class TestAll extends TestCase {
     public static Test suite() {
         TestSuite suite = new TestSuite("org.apache.jackrabbit.core.security.authentication.token
tests");
 
+        suite.addTestSuite(TokenBasedAuthenticationCompatTest.class);
         suite.addTestSuite(TokenBasedAuthenticationTest.class);
         suite.addTestSuite(TokenBasedLoginTest.class);
 

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationTest.java?rev=1574098&r1=1574097&r2=1574098&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationTest.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authentication/token/TokenBasedAuthenticationTest.java
Tue Mar  4 13:43:28 2014
@@ -16,9 +16,7 @@
  */
 package org.apache.jackrabbit.core.security.authentication.token;
 
-import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-
+import java.util.UUID;
 import javax.jcr.Credentials;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
@@ -27,45 +25,82 @@ import javax.jcr.SimpleCredentials;
 import javax.jcr.lock.LockException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.version.VersionException;
-import java.util.Calendar;
-import java.util.Date;
+
+import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.test.AbstractJCRTest;
 
 /**
- * <code>TokenBasedAuthenticationTest</code>...
+ * <code>TokenBasedAuthenticationOakTest</code>...
  */
 public class TokenBasedAuthenticationTest extends AbstractJCRTest {
 
-    Node tokenNode;
+    private SessionImpl adminSession;
+    private User testUser;
+
+    private String token;
+    private Node tokenNode;
+    private TokenCredentials tokenCreds;
+
+    private String expiredToken;
+    private Node expiredNode;
+    private TokenCredentials expiredCreds;
 
-    TokenBasedAuthentication nullTokenAuth;
-    TokenBasedAuthentication validTokenAuth;
 
-    TokenCredentials tokenCreds;
-    Credentials simpleCreds = new SimpleCredentials("uid", "pw".toCharArray());
-    Credentials creds = new Credentials() {};
+    private TokenBasedAuthentication nullTokenAuth;
+    private TokenBasedAuthentication validTokenAuth;
+
+    private Credentials simpleCreds = new SimpleCredentials("uid", "pw".toCharArray());
+    private Credentials creds = new Credentials() {};
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        tokenNode = testRootNode.addNode(nodeName1, "nt:unstructured");
-        tokenNode.setProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".exp", new Date().getTime()+TokenBasedAuthentication.TOKEN_EXPIRATION);
-        superuser.save();
+        adminSession = (SessionImpl) getHelper().getSuperuserSession("security");
+        testUser = adminSession.getUserManager().createUser(UUID.randomUUID().toString(),
"pw");
+        adminSession.save();
+
+        SimpleCredentials sc = new SimpleCredentials(testUser.getID(), "pw".toCharArray());
+        sc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE, "");
+        sc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE+".any", "correct");
+        sc.setAttribute("informative", "value");
 
-        String token = tokenNode.getIdentifier();
+        TokenProvider tp = new TokenProvider(adminSession, TokenBasedAuthentication.TOKEN_EXPIRATION);
+        TokenInfo ti = tp.createToken(testUser, sc);
+        tokenCreds = ti.getCredentials();
+        token = tokenCreds.getToken();
+        tokenNode = TokenProvider.getTokenNode(token, adminSession);
+
+        tp = new TokenProvider(adminSession, 1);
+        TokenInfo expired = tp.createToken(testUser, sc);
+        expiredCreds = expired.getCredentials();
+        expiredToken = expiredCreds.getToken();
+        expiredNode = TokenProvider.getTokenNode(expiredToken, adminSession);
 
-        nullTokenAuth = new TokenBasedAuthentication(null, -1, superuser);
-        validTokenAuth = new TokenBasedAuthentication(token, 7200, superuser);
+        nullTokenAuth = new TokenBasedAuthentication(null, -1, adminSession);
+        validTokenAuth = new TokenBasedAuthentication(token, 7200, adminSession);
 
-        tokenCreds = new TokenCredentials(token);
     }
 
-    private TokenBasedAuthentication expiredToken() throws RepositoryException, LockException,
ConstraintViolationException, VersionException {
-        Calendar cal = Calendar.getInstance();
-        cal.setTimeInMillis(new Date().getTime()-100);
-        tokenNode.setProperty(".token.exp", cal);
-        superuser.save();
-        return new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION,
superuser);
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            testUser.remove();
+            adminSession.save();
+            adminSession.logout();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    private TokenBasedAuthentication createAuthenticationForExpiredToken() throws RepositoryException,
LockException, ConstraintViolationException, VersionException {
+        return new TokenBasedAuthentication(expiredToken, TokenBasedAuthentication.TOKEN_EXPIRATION,
adminSession);
+    }
+
+    private TokenBasedAuthentication createAuthentication() throws RepositoryException {
+        return new TokenBasedAuthentication(token, TokenBasedAuthentication.TOKEN_EXPIRATION,
adminSession);
     }
 
     public void testCanHandle() throws RepositoryException {
@@ -77,23 +112,23 @@ public class TokenBasedAuthenticationTes
 
         assertFalse(validTokenAuth.canHandle(creds));
         assertFalse(nullTokenAuth.canHandle(creds));
+    }
 
-        TokenBasedAuthentication expiredToken = expiredToken();
-        assertTrue(expiredToken.canHandle(tokenCreds));
+    public void testCanHandleExpiredToken() throws RepositoryException {
+        TokenBasedAuthentication expiredToken = createAuthenticationForExpiredToken();
+        assertTrue(expiredToken.canHandle(expiredCreds));
     }
 
     public void testExpiry() throws RepositoryException {
-        assertTrue(validTokenAuth.authenticate(tokenCreds));
-
-        TokenBasedAuthentication expiredToken = expiredToken();
-        assertFalse(expiredToken.authenticate(tokenCreds));
+        TokenBasedAuthentication expiredToken = createAuthenticationForExpiredToken();
+        assertFalse(expiredToken.authenticate(expiredCreds));
     }
 
     public void testRemoval() throws RepositoryException {
-        String identifier = tokenNode.getIdentifier();
+        String identifier = expiredNode.getIdentifier();
 
-        TokenBasedAuthentication expiredToken = expiredToken();
-        assertFalse(expiredToken.authenticate(tokenCreds));
+        TokenBasedAuthentication expiredToken = createAuthenticationForExpiredToken();
+        assertFalse(expiredToken.authenticate(expiredCreds));
 
         try {
             superuser.getNodeByIdentifier(identifier);
@@ -120,57 +155,48 @@ public class TokenBasedAuthenticationTes
     }
 
     public void testAttributes() throws RepositoryException {
-        tokenNode.setProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
-        superuser.save();
-        TokenBasedAuthentication auth = new TokenBasedAuthentication(tokenNode.getIdentifier(),
TokenBasedAuthentication.TOKEN_EXPIRATION, superuser);
-
-        assertFalse(auth.authenticate(tokenCreds));
-
-        tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "wrong");
-        assertFalse(auth.authenticate(tokenCreds));
+        TokenBasedAuthentication auth = createAuthentication();
+        assertFalse(auth.authenticate(new TokenCredentials(token)));
 
-        tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
-        assertTrue(auth.authenticate(tokenCreds));
-
-        // add informative property
-        tokenNode.setProperty("noMatchRequired", "abc");
-        superuser.save();
-        auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION,
superuser);
+        TokenCredentials tc = new TokenCredentials(token);
+        tc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "wrong");
+        assertFalse(auth.authenticate(tc));
 
+        tc = new TokenCredentials(token);
+        tc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
         assertTrue(auth.authenticate(tokenCreds));
     }
 
     public void testUpdateAttributes() throws RepositoryException {
-        tokenNode.setProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
-        tokenNode.setProperty("informative","value");
-        superuser.save();
-
         // token credentials must be updated to contain the additional attribute
         // present on the token node.
-        TokenBasedAuthentication auth = new TokenBasedAuthentication(tokenNode.getIdentifier(),
TokenBasedAuthentication.TOKEN_EXPIRATION, superuser);
-        tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
-        assertTrue(auth.authenticate(tokenCreds));               
-        assertEquals("value", tokenCreds.getAttribute("informative"));
+        TokenBasedAuthentication auth = createAuthentication();
+
+        TokenCredentials tc = new TokenCredentials(token);
+        tc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
+
+        assertTrue(auth.authenticate(tc));
+        assertEquals("value", tc.getAttribute("informative"));
 
         // additional informative property present on credentials upon subsequent
         // authentication -> the node must not be updated
-        auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION,
superuser);
-        tokenCreds.setAttribute("informative2", "value2");
-        assertTrue(auth.authenticate(tokenCreds));
+        auth = createAuthentication();
+        tc.setAttribute("informative2", "value2");
+        assertTrue(auth.authenticate(tc));
         assertFalse(tokenNode.hasProperty("informative2"));
 
         // modified informative property present on credentials upon subsequent
         // authentication -> the node must not be updated
-        auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION,
superuser);
-        tokenCreds.setAttribute("informative", "otherValue");
-        assertTrue(auth.authenticate(tokenCreds));
+        auth = createAuthentication();
+        tc.setAttribute("informative", "otherValue");
+        assertTrue(auth.authenticate(tc));
         assertTrue(tokenNode.hasProperty("informative"));
         assertEquals("value", tokenNode.getProperty("informative").getString());
 
         // additional mandatory property on the credentials upon subsequent
         // authentication -> must be ignored
-        auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION,
superuser);        
-        tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".toIgnore", "ignore");
+        auth = createAuthentication();
+        tc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".toIgnore", "ignore");
         assertTrue(auth.authenticate(tokenCreds));
         assertFalse(tokenNode.hasProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".toIgnore"));
     }



Mime
View raw message