/*
* 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.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;
public class TokenProviderTest extends AbstractJCRTest {
private User testuser;
private String userId;
private SessionImpl session;
private TokenProvider tokenProvider;
@Override
protected void setUp() throws Exception {
super.setUp();
if (superuser instanceof SessionImpl) {
UserManager umgr = ((SessionImpl) superuser).getUserManager();
if (!umgr.isAutoSave()) {
umgr.autoSave(true);
}
String uid = "test";
while (umgr.getAuthorizable(uid) != null) {
uid += "_";
}
testuser = umgr.createUser(uid, uid);
userId = testuser.getID();
} else {
throw new NotExecutableException();
}
if (superuser.nodeExists(((ItemBasedPrincipal) testuser.getPrincipal()).getPath())) {
session = (SessionImpl) superuser;
} else {
session = (SessionImpl) getHelper().getSuperuserSession("security");
}
tokenProvider = new TokenProvider((SessionImpl) session, TokenBasedAuthentication.TOKEN_EXPIRATION);
}
@Override
protected void tearDown() throws Exception {
try {
testuser.remove();
session.logout();
} finally {
super.tearDown();
}
}
public void testCreateTokenFromInvalidCredentials() throws Exception {
assertNull(tokenProvider.createToken(testuser, new SimpleCredentials("unknownUserId", new char[0])));
}
public void testCreateTokenFromCredentials() throws Exception {
TokenInfo info = tokenProvider.createToken(testuser, new SimpleCredentials(userId, new char[0]));
assertTokenInfo(info);
}
public void testCreateTokenIsCaseInsensitive() throws Exception {
String upperCaseUserId = userId.toUpperCase();
TokenInfo info = tokenProvider.createToken(testuser, new SimpleCredentials(upperCaseUserId, new char[0]));
assertTokenInfo(info);
}
public void testTokenNode() throws Exception {
Map<String, String> privateAttributes = new HashMap<String, String>();
privateAttributes.put(".token_exp", "value");
privateAttributes.put(".tokenTest", "value");
privateAttributes.put(".token_something", "value");
Map<String, String> publicAttributes = new HashMap<String, String>();
publicAttributes.put("any", "value");
publicAttributes.put("another", "value");
Map<String, String> attributes = new HashMap<String, String>();
attributes.putAll(publicAttributes);
attributes.putAll(privateAttributes);
SimpleCredentials sc = new SimpleCredentials(userId, userId.toCharArray());
for (String s : attributes.keySet()) {
sc.setAttribute(s, attributes.get(s));
}
TokenInfo info = tokenProvider.createToken(testuser, sc);
Node tokenNode = getTokenNode(info);
Property prop = tokenNode.getProperty("rep:token.key");
assertNotNull(prop);
assertEquals(PropertyType.STRING, prop.getType());
assertTrue(prop.getDefinition().isProtected());
prop = tokenNode.getProperty("rep:token.exp");
assertNotNull(prop);
assertEquals(PropertyType.DATE, prop.getType());
assertTrue(prop.getDefinition().isProtected());
for (String key : privateAttributes.keySet()) {
assertEquals(privateAttributes.get(key), tokenNode.getProperty(key).getString());
}
for (String key : publicAttributes.keySet()) {
assertEquals(publicAttributes.get(key), tokenNode.getProperty(key).getString());
}
}
public void testGetTokenInfoFromInvalidToken() throws Exception {
List<String> invalid = new ArrayList<String>();
invalid.add("/invalid");
invalid.add(UUID.randomUUID().toString());
try {
for (String token : invalid) {
TokenInfo info = tokenProvider.getTokenInfo(token);
assertNull(info);
}
} catch (Exception e) {
// success
}
}
public void testGetTokenInfo() throws Exception {
String token = tokenProvider.createToken(testuser, new SimpleCredentials(userId, userId.toCharArray())).getToken();
TokenInfo info = tokenProvider.getTokenInfo(token);
assertTokenInfo(info);
}
public void testIsExpired() throws Exception {
TokenInfo info = tokenProvider.createToken(testuser, new SimpleCredentials(userId, userId.toCharArray()));
long loginTime = waitForSystemTimeIncrement(System.currentTimeMillis());
assertFalse(info.isExpired(loginTime));
assertTrue(info.isExpired(loginTime + TokenBasedAuthentication.TOKEN_EXPIRATION));
}
public void testReset() throws Exception {
TokenInfo info = tokenProvider.createToken(testuser, new SimpleCredentials(userId, userId.toCharArray()));
long expTime = getTokenNode(info).getProperty("rep:token.exp").getLong();
long loginTime = waitForSystemTimeIncrement(System.currentTimeMillis());
assertFalse(info.resetExpiration(loginTime));
assertFalse(info.resetExpiration(loginTime + TokenBasedAuthentication.TOKEN_EXPIRATION));
assertTrue(info.resetExpiration(loginTime + TokenBasedAuthentication.TOKEN_EXPIRATION / 2));
long expTime2 = getTokenNode(info).getProperty("rep:token.exp").getLong();
assertFalse(expTime == expTime2);
}
//--------------------------------------------------------------------------
private static void assertTokenInfo(TokenInfo info) {
assertNotNull(info);
assertNotNull(info.getToken());
assertFalse(info.isExpired(new Date().getTime()));
}
private Node getTokenNode(TokenInfo info) throws RepositoryException {
return TokenProvider.getTokenNode(info.getToken(), session);
}
private static long waitForSystemTimeIncrement(long old){
while (old == System.currentTimeMillis()) {
// wait for system timer to move
}
return System.currentTimeMillis();
}
}