Support groups from external authentication resources

This commit is contained in:
René Pfeuffer
2019-02-14 15:42:27 +01:00
parent 733e719194
commit 75239a0104
4 changed files with 78 additions and 16 deletions

View File

@@ -73,18 +73,7 @@ public final class GroupNames implements Serializable, Iterable<String>
@SuppressWarnings("unchecked")
public GroupNames()
{
this.collection = Collections.EMPTY_LIST;
}
/**
* Constructs ...
*
*
* @param collection
*/
public GroupNames(Collection<String> collection)
{
this.collection = Collections.unmodifiableCollection(collection);
this(Collections.EMPTY_LIST);
}
/**
@@ -96,7 +85,30 @@ public final class GroupNames implements Serializable, Iterable<String>
*/
public GroupNames(String groupName, String... groupNames)
{
this.collection = Lists.asList(groupName, groupNames);
this(Lists.asList(groupName, groupNames));
}
/**
* Constructs ...
*
*
* @param collection
*/
public GroupNames(Collection<String> collection)
{
this(collection, false);
}
/**
* Constructs ...
*
*
* @param collection
*/
public GroupNames(Collection<String> collection, boolean external)
{
this.collection = Collections.unmodifiableCollection(collection);
this.external = external;
}
//~--- methods --------------------------------------------------------------
@@ -181,8 +193,13 @@ public final class GroupNames implements Serializable, Iterable<String>
return collection;
}
//~--- fields ---------------------------------------------------------------
public boolean isExternal() {
return external;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Collection<String> collection;
private final boolean external;
}

View File

@@ -108,11 +108,26 @@ public final class SyncingRealmHelper {
*/
public AuthenticationInfo createAuthenticationInfo(String realm, User user,
Collection<String> groups) {
return this.createAuthenticationInfo(realm, user, groups, false);
}
/**
* Create {@link AuthenticationInfo} from user and groups.
*
*
* @param realm name of the realm
* @param user authenticated user
* @param groups groups of the authenticated user
*
* @return authentication info
*/
public AuthenticationInfo createAuthenticationInfo(String realm, User user,
Collection<String> groups, boolean externalGroups) {
SimplePrincipalCollection collection = new SimplePrincipalCollection();
collection.add(user.getId(), realm);
collection.add(user, realm);
collection.add(new GroupNames(groups), realm);
collection.add(new GroupNames(groups, externalGroups), realm);
return new SimpleAuthenticationInfo(collection, user.getPassword());
}

View File

@@ -53,10 +53,13 @@ import sonia.scm.web.security.PrivilegedAction;
import java.io.IOException;
import static java.util.Collections.singletonList;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -113,7 +116,7 @@ public class SyncingRealmHelperTest {
public void testCreateAuthenticationInfo() {
User user = new User("tricia");
AuthenticationInfo authInfo = helper.createAuthenticationInfo("unit-test",
user, "heartOfGold");
user, singletonList("heartOfGold"));
assertNotNull(authInfo);
assertEquals("tricia", authInfo.getPrincipals().getPrimaryPrincipal());
@@ -123,6 +126,27 @@ public class SyncingRealmHelperTest {
GroupNames groups = authInfo.getPrincipals().oneByType(GroupNames.class);
assertThat(groups, hasItem("heartOfGold"));
assertFalse(groups.isExternal());
}
/**
* Tests {@link SyncingRealmHelper#createAuthenticationInfo(String, User, String...)}.
*/
@Test
public void testCreateAuthenticationInfoWithExternalGroups() {
User user = new User("tricia");
AuthenticationInfo authInfo = helper.createAuthenticationInfo("unit-test",
user, singletonList("heartOfGold"), true);
assertNotNull(authInfo);
assertEquals("tricia", authInfo.getPrincipals().getPrimaryPrincipal());
assertThat(authInfo.getPrincipals().getRealmNames(), hasItem("unit-test"));
assertEquals(user, authInfo.getPrincipals().oneByType(User.class));
GroupNames groups = authInfo.getPrincipals().oneByType(GroupNames.class);
assertThat(groups, hasItem("heartOfGold"));
assertTrue(groups.isExternal());
}
/**

View File

@@ -8,6 +8,7 @@ import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.group.GroupNames;
import sonia.scm.security.*;
import javax.servlet.http.HttpServletRequest;
@@ -91,6 +92,11 @@ public class AuthenticationResource {
tokenBuilder.scope(Scope.valueOf(authentication.getScope()));
}
GroupNames groupNames = subject.getPrincipals().oneByType(GroupNames.class);
if (groupNames != null && groupNames.isExternal()) {
tokenBuilder.groups(groupNames.getCollection().toArray(new String[]{}));
}
AccessToken token = tokenBuilder.build();
if (authentication.isCookie()) {