/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.core.security.authentication.token;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import javax.jcr.Credentials;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;
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>TokenBasedAuthenticationCompatTest</code>...
*/
public class TokenBasedAuthenticationCompatTest extends AbstractJCRTest {
SessionImpl adminSession;
User testUser;
Node tokenNode;
String token;
TokenBasedAuthentication nullTokenAuth;
TokenBasedAuthentication validTokenAuth;
TokenCredentials tokenCreds;
Credentials simpleCreds = new SimpleCredentials("uid", "pw".toCharArray());
Credentials creds = new Credentials() {};
@Override
protected void setUp() throws Exception {
super.setUp();
System.setProperty(TokenBasedAuthentication.PARAM_COMPAT, Boolean.TRUE.toString());
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, "");
CompatTokenProvider tp = new CompatTokenProvider(adminSession, TokenBasedAuthentication.TOKEN_EXPIRATION);
TokenInfo ti = tp.createToken(testUser, sc);
tokenNode = CompatTokenProvider.getTokenNode(ti.getToken(), adminSession);
token = ti.getToken();
nullTokenAuth = new TokenBasedAuthentication(null, -1, adminSession);
validTokenAuth = new TokenBasedAuthentication(token, 7200, adminSession);
tokenCreds = new TokenCredentials(token);
}
@Override
protected void tearDown() throws Exception {
System.setProperty(TokenBasedAuthentication.PARAM_COMPAT, Boolean.FALSE.toString());
super.tearDown();
}
private TokenBasedAuthentication expiredToken() throws RepositoryException, LockException, ConstraintViolationException, VersionException {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(new Date().getTime() - 100);
tokenNode.setProperty(".token.exp", cal);
adminSession.save();
return new TokenBasedAuthentication(token, TokenBasedAuthentication.TOKEN_EXPIRATION, adminSession);
}
public void testCanHandle() throws RepositoryException {
assertTrue(validTokenAuth.canHandle(tokenCreds));
assertFalse(nullTokenAuth.canHandle(tokenCreds));
assertFalse(validTokenAuth.canHandle(simpleCreds));
assertFalse(nullTokenAuth.canHandle(simpleCreds));
assertFalse(validTokenAuth.canHandle(creds));
assertFalse(nullTokenAuth.canHandle(creds));
TokenBasedAuthentication expiredToken = expiredToken();
assertTrue(expiredToken.canHandle(tokenCreds));
}
public void testExpiry() throws RepositoryException {
assertTrue(validTokenAuth.authenticate(tokenCreds));
TokenBasedAuthentication expiredToken = expiredToken();
assertFalse(expiredToken.authenticate(tokenCreds));
}
public void testRemoval() throws RepositoryException {
String identifier = tokenNode.getIdentifier();
TokenBasedAuthentication expiredToken = expiredToken();
assertFalse(expiredToken.authenticate(tokenCreds));
try {
adminSession.getNodeByIdentifier(identifier);
fail("expired token node should be removed.");
} catch (ItemNotFoundException e) {
// success
}
}
public void testInvalidCredentials() throws RepositoryException {
try {
validTokenAuth.authenticate(creds);
fail("RepositoryException expected");
} catch (RepositoryException e) {
// success
}
try {
assertFalse(validTokenAuth.authenticate(simpleCreds));
fail("RepositoryException expected");
} catch (RepositoryException e) {
// success
}
}
public void testAttributes() throws RepositoryException {
tokenNode.setProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
adminSession.save();
TokenBasedAuthentication auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION, adminSession);
assertFalse(auth.authenticate(tokenCreds));
tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + ".any", "wrong");
assertFalse(auth.authenticate(tokenCreds));
tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
assertTrue(auth.authenticate(tokenCreds));
// add informative property
tokenNode.setProperty("noMatchRequired", "abc");
adminSession.save();
auth = new TokenBasedAuthentication(tokenNode.getIdentifier(), TokenBasedAuthentication.TOKEN_EXPIRATION, adminSession);
assertTrue(auth.authenticate(tokenCreds));
}
public void testUpdateAttributes() throws RepositoryException {
tokenNode.setProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".any", "correct");
tokenNode.setProperty("informative","value");
adminSession.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, adminSession);
tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + ".any", "correct");
assertTrue(auth.authenticate(tokenCreds));
assertEquals("value", tokenCreds.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, adminSession);
tokenCreds.setAttribute("informative2", "value2");
assertTrue(auth.authenticate(tokenCreds));
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, adminSession);
tokenCreds.setAttribute("informative", "otherValue");
assertTrue(auth.authenticate(tokenCreds));
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, adminSession);
tokenCreds.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".toIgnore", "ignore");
assertTrue(auth.authenticate(tokenCreds));
assertFalse(tokenNode.hasProperty(TokenBasedAuthentication.TOKEN_ATTRIBUTE +".toIgnore"));
}
public void testIsTokenBasedLogin() {
assertFalse(TokenBasedAuthentication.isTokenBasedLogin(simpleCreds));
assertFalse(TokenBasedAuthentication.isTokenBasedLogin(creds));
assertTrue(TokenBasedAuthentication.isTokenBasedLogin(tokenCreds));
}
public void testIsMandatoryAttribute() {
assertFalse(TokenBasedAuthentication.isMandatoryAttribute("noMatchRequired"));
assertTrue(TokenBasedAuthentication.isMandatoryAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + ".exp"));
assertTrue(TokenBasedAuthentication.isMandatoryAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + ".custom"));
assertTrue(TokenBasedAuthentication.isMandatoryAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + "_custom"));
assertTrue(TokenBasedAuthentication.isMandatoryAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE + "custom"));
}
public void testDoCreateToken() {
assertFalse(TokenBasedAuthentication.doCreateToken(creds));
assertFalse(TokenBasedAuthentication.doCreateToken(simpleCreds));
assertFalse(TokenBasedAuthentication.doCreateToken(tokenCreds));
SimpleCredentials sc = new SimpleCredentials("uid", "pw".toCharArray());
sc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE, null);
assertFalse(TokenBasedAuthentication.doCreateToken(sc));
sc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE, "somevalue");
assertFalse(TokenBasedAuthentication.doCreateToken(sc));
sc.setAttribute(TokenBasedAuthentication.TOKEN_ATTRIBUTE, "");
assertTrue(TokenBasedAuthentication.doCreateToken(sc));
}
}