blob: 3e62958f5df77588c68c4f8c21fcf12e7342dcb6 [file] [log] [blame]
/*
* 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.
*/
import com.google.common.collect.Sets;
import org.apache.fineract.cn.anubis.api.v1.client.Anubis;
import org.apache.fineract.cn.anubis.api.v1.domain.*;
import org.apache.fineract.cn.anubis.test.v1.SystemSecurityEnvironment;
import org.apache.fineract.cn.api.context.AutoUserContext;
import org.apache.fineract.cn.api.util.InvalidTokenException;
import org.apache.fineract.cn.api.util.NotFoundException;
import org.apache.fineract.cn.identity.api.v1.domain.*;
import org.apache.fineract.cn.lang.AutoTenantContext;
import org.apache.fineract.cn.lang.security.RsaPublicKeyBuilder;
import org.apache.fineract.cn.test.env.TestEnvironment;
import org.junit.Assert;
import org.junit.Test;
import java.security.PublicKey;
import java.util.*;
import static org.apache.fineract.cn.identity.api.v1.events.EventConstants.OPERATION_POST_PERMITTABLE_GROUP;
import static org.apache.fineract.cn.identity.api.v1.events.EventConstants.OPERATION_POST_ROLE;
import static org.apache.fineract.cn.identity.api.v1.events.EventConstants.OPERATION_POST_USER;
import static org.apache.fineract.cn.identity.api.v1.events.EventConstants.OPERATION_PUT_USER_PASSWORD;
/**
* @author Myrle Krantz
*/
public class TestAuthentication extends AbstractComponentTest {
@Test
//@Repeat(25)
public void testAdminLogin() throws InterruptedException {
//noinspection EmptyTryBlock
try (final AutoUserContext ignore = loginAdmin()) {
}
}
@Test
public void testAdminLogout() throws InterruptedException {
try (final AutoUserContext ignore = loginAdmin()) {
getTestSubject().logout();
try {
getTestSubject().refresh();
Assert.fail("Refresh should fail after logout has occurred.");
}
catch (final InvalidTokenException ignored)
{
//Expected.
}
}
}
@Test(expected = NotFoundException.class)
public void testAdminIncorrectLogin() throws InterruptedException {
getTestSubject().login(ADMIN_IDENTIFIER, TestEnvironment.encodePassword("set"));
Assert.fail("login with wrong password should fail with not found exception.");
}
@Test(expected = IllegalArgumentException.class)
public void testAdminMissingTenantHeader() throws InterruptedException {
try (final AutoUserContext ignored = tenantApplicationSecurityEnvironment.createAutoSeshatContext()) {
try (final AutoTenantContext ignored2 = new AutoTenantContext())
{
getTestSubject().login(ADMIN_IDENTIFIER, TestEnvironment.encodePassword(ADMIN_PASSWORD));
}
}
Assert.fail("login without tenant header set should fail with bad request.");
}
@Test()
public void testPermissionsCorrectInAdminToken() throws InterruptedException {
try (final AutoUserContext ignore = loginAdmin()) {
final Authentication adminAuthentication =
getTestSubject().login(ADMIN_IDENTIFIER, TestEnvironment.encodePassword(ADMIN_PASSWORD));
Assert.assertNotNull(adminAuthentication);
final TokenContent tokenContent = SystemSecurityEnvironment.getTokenContent(adminAuthentication.getAccessToken(), getPublicKey());
final Set<TokenPermission> tokenPermissions = new HashSet<>(tokenContent.getTokenPermissions());
final Set<TokenPermission> expectedTokenPermissions = new HashSet<>();
Collections.addAll(expectedTokenPermissions,
new TokenPermission("identity-v1/permittablegroups/*", Sets.newHashSet(AllowedOperation.CHANGE, AllowedOperation.DELETE, AllowedOperation.READ)),
new TokenPermission("identity-v1/roles/*", Sets.newHashSet(AllowedOperation.CHANGE, AllowedOperation.DELETE, AllowedOperation.READ)),
new TokenPermission("identity-v1/users/*", Sets.newHashSet(AllowedOperation.CHANGE, AllowedOperation.DELETE, AllowedOperation.READ)));
//This is not a complete list. This is a spot check.
Assert.assertTrue("Expected: " + expectedTokenPermissions + "\nActual: " + tokenPermissions,
tokenPermissions.containsAll(expectedTokenPermissions));
}
}
@Test()
public void testPermissionsCorrectInTokenWhenMultiplePermittableGroupsInRole() throws InterruptedException {
try (final AutoUserContext ignore = loginAdmin()) {
final PermittableEndpoint horusEndpoint = buildPermittableEndpoint("horus");
final PermittableGroup horusGroup = buildPermittableGroup("horus_Group", horusEndpoint);
getTestSubject().createPermittableGroup(horusGroup);
final PermittableEndpoint maatEndpoint = buildPermittableEndpoint("maat");
final PermittableGroup maatGroup = buildPermittableGroup("maat_Group", maatEndpoint);
getTestSubject().createPermittableGroup(maatGroup);
Assert.assertTrue(eventRecorder.wait(OPERATION_POST_PERMITTABLE_GROUP, horusGroup.getIdentifier()));
Assert.assertTrue(eventRecorder.wait(OPERATION_POST_PERMITTABLE_GROUP, maatGroup.getIdentifier()));
final Permission horusGroupPermission = new Permission(horusGroup.getIdentifier(), Collections.singleton(AllowedOperation.READ));
final Permission maatGroupPermission = new Permission(maatGroup.getIdentifier(), AllowedOperation.ALL);
final Role compositeRole = new Role("composite_role", Arrays.asList(horusGroupPermission, maatGroupPermission));
getTestSubject().createRole(compositeRole);
Assert.assertTrue(eventRecorder.wait(OPERATION_POST_ROLE, compositeRole.getIdentifier()));
final UserWithPassword user = new UserWithPassword("user_with_composite_role", compositeRole.getIdentifier(), "asdfasdfasdf");
getTestSubject().createUser(user);
Assert.assertTrue(eventRecorder.wait(OPERATION_POST_USER, user.getIdentifier()));
final Authentication passwordChangeOnlyAuthentication = getTestSubject().login(user.getIdentifier(), user.getPassword());
try (final AutoUserContext ignore2 = new AutoUserContext(user.getIdentifier(), passwordChangeOnlyAuthentication.getAccessToken()))
{
getTestSubject().changeUserPassword(user.getIdentifier(), new Password(user.getPassword()));
Assert.assertTrue(eventRecorder.wait(OPERATION_PUT_USER_PASSWORD, user.getIdentifier()));
}
final Authentication authentication = getTestSubject().login(user.getIdentifier(), user.getPassword());
final TokenContent tokenContent = SystemSecurityEnvironment
.getTokenContent(authentication.getAccessToken(), getPublicKey());
final Set<TokenPermission> tokenPermissions = new HashSet<>(tokenContent.getTokenPermissions());
final Set<TokenPermission> expectedTokenPermissions= new HashSet<>();
Collections.addAll(expectedTokenPermissions,
new TokenPermission(horusEndpoint.getPath(), Collections.singleton(AllowedOperation.READ)),
new TokenPermission(maatEndpoint.getPath(), Collections.singleton(AllowedOperation.READ)),
new TokenPermission("identity-v1/users/{useridentifier}/password",
Sets.newHashSet(AllowedOperation.READ, AllowedOperation.CHANGE, AllowedOperation.DELETE)),
new TokenPermission("identity-v1/users/{useridentifier}/permissions", Sets.newHashSet(AllowedOperation.READ)),
new TokenPermission("identity-v1/token/_current", Collections.singleton(AllowedOperation.DELETE)));
Assert.assertTrue("Expected: " + expectedTokenPermissions + "\nActual: " + tokenPermissions,
tokenPermissions.containsAll(expectedTokenPermissions));
}
}
private PermittableGroup buildPermittableGroup(final String identifier, final PermittableEndpoint... permittableEndpoint) {
final PermittableGroup ret = new PermittableGroup();
ret.setIdentifier(identifier);
ret.setPermittables(Arrays.asList(permittableEndpoint));
return ret;
}
private PermittableEndpoint buildPermittableEndpoint(final String group) {
final PermittableEndpoint ret = new PermittableEndpoint();
ret.setPath(group + "/v1/x/y/z");
ret.setMethod("GET");
ret.setGroupId(group);
return ret;
}
public PublicKey getPublicKey() {
try (final AutoUserContext ignored = tenantApplicationSecurityEnvironment.createAutoSeshatContext())
{
final Anubis anubis = tenantApplicationSecurityEnvironment.getAnubis();
final List<String> signatureKeyTimestamps = anubis.getAllSignatureSets();
Assert.assertTrue(!signatureKeyTimestamps.isEmpty());
final Signature sig = anubis.getApplicationSignature(signatureKeyTimestamps.get(0));
return new RsaPublicKeyBuilder()
.setPublicKeyMod(sig.getPublicKeyMod())
.setPublicKeyExp(sig.getPublicKeyExp())
.build();
}
}
}