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") @SuppressWarnings("unchecked")
public GroupNames() public GroupNames()
{ {
this.collection = Collections.EMPTY_LIST; this(Collections.EMPTY_LIST);
}
/**
* Constructs ...
*
*
* @param collection
*/
public GroupNames(Collection<String> collection)
{
this.collection = Collections.unmodifiableCollection(collection);
} }
/** /**
@@ -96,7 +85,30 @@ public final class GroupNames implements Serializable, Iterable<String>
*/ */
public GroupNames(String groupName, String... groupNames) 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 -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -181,8 +193,13 @@ public final class GroupNames implements Serializable, Iterable<String>
return collection; return collection;
} }
//~--- fields --------------------------------------------------------------- public boolean isExternal() {
return external;
}
//~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */
private final Collection<String> collection; 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, public AuthenticationInfo createAuthenticationInfo(String realm, User user,
Collection<String> groups) { 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(); SimplePrincipalCollection collection = new SimplePrincipalCollection();
collection.add(user.getId(), realm); collection.add(user.getId(), realm);
collection.add(user, realm); collection.add(user, realm);
collection.add(new GroupNames(groups), realm); collection.add(new GroupNames(groups, externalGroups), realm);
return new SimpleAuthenticationInfo(collection, user.getPassword()); return new SimpleAuthenticationInfo(collection, user.getPassword());
} }

View File

@@ -53,10 +53,13 @@ import sonia.scm.web.security.PrivilegedAction;
import java.io.IOException; import java.io.IOException;
import static java.util.Collections.singletonList;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -113,7 +116,7 @@ public class SyncingRealmHelperTest {
public void testCreateAuthenticationInfo() { public void testCreateAuthenticationInfo() {
User user = new User("tricia"); User user = new User("tricia");
AuthenticationInfo authInfo = helper.createAuthenticationInfo("unit-test", AuthenticationInfo authInfo = helper.createAuthenticationInfo("unit-test",
user, "heartOfGold"); user, singletonList("heartOfGold"));
assertNotNull(authInfo); assertNotNull(authInfo);
assertEquals("tricia", authInfo.getPrincipals().getPrimaryPrincipal()); assertEquals("tricia", authInfo.getPrincipals().getPrimaryPrincipal());
@@ -123,6 +126,27 @@ public class SyncingRealmHelperTest {
GroupNames groups = authInfo.getPrincipals().oneByType(GroupNames.class); GroupNames groups = authInfo.getPrincipals().oneByType(GroupNames.class);
assertThat(groups, hasItem("heartOfGold")); 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.apache.shiro.subject.Subject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.group.GroupNames;
import sonia.scm.security.*; import sonia.scm.security.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -91,6 +92,11 @@ public class AuthenticationResource {
tokenBuilder.scope(Scope.valueOf(authentication.getScope())); 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(); AccessToken token = tokenBuilder.build();
if (authentication.isCookie()) { if (authentication.isCookie()) {