/*
* *****************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
* *****************************************************************************
*/
package org.cloudfoundry.identity.uaa.mock.token;
import org.cloudfoundry.identity.uaa.constants.OriginKeys;
import org.cloudfoundry.identity.uaa.mock.InjectedMockContextTest;
import org.cloudfoundry.identity.uaa.oauth.UaaTokenServices;
import org.cloudfoundry.identity.uaa.oauth.client.ClientConstants;
import org.cloudfoundry.identity.uaa.oauth.token.RevocableTokenProvisioning;
import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning;
import org.cloudfoundry.identity.uaa.provider.JdbcIdentityProviderProvisioning;
import org.cloudfoundry.identity.uaa.scim.ScimGroup;
import org.cloudfoundry.identity.uaa.scim.ScimGroupMember;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning;
import org.cloudfoundry.identity.uaa.scim.exception.MemberAlreadyExistsException;
import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimGroupMembershipManager;
import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimGroupProvisioning;
import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimUserProvisioning;
import org.cloudfoundry.identity.uaa.zone.ClientServicesExtension;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneProvisioning;
import org.junit.Before;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.getClientCredentialsOAuthAccessToken;
import static org.junit.Assert.assertNull;
import static org.springframework.util.StringUtils.hasText;
public abstract class AbstractTokenMockMvcTests extends InjectedMockContextTest {
public static final String SECRET = "secret";
public static final String GRANT_TYPES = "password,implicit,client_credentials,authorization_code,refresh_token";
public static final String TEST_REDIRECT_URI = "http://test.example.org/redirect";
protected ClientServicesExtension clientDetailsService;
protected JdbcScimUserProvisioning userProvisioning;
protected JdbcScimGroupProvisioning groupProvisioning;
protected JdbcScimGroupMembershipManager groupMembershipManager;
protected UaaTokenServices tokenServices;
protected Set<String> defaultAuthorities;
protected IdentityZoneProvisioning identityZoneProvisioning;
protected JdbcScimUserProvisioning jdbcScimUserProvisioning;
protected IdentityProviderProvisioning identityProviderProvisioning;
protected String adminToken;
protected RevocableTokenProvisioning tokenProvisioning;
protected RandomValueStringGenerator generator = new RandomValueStringGenerator();
@Before
public void setUpContext() throws Exception {
clientDetailsService = (ClientServicesExtension) getWebApplicationContext().getBean("jdbcClientDetailsService");
userProvisioning = (JdbcScimUserProvisioning) getWebApplicationContext().getBean("scimUserProvisioning");
groupProvisioning = (JdbcScimGroupProvisioning) getWebApplicationContext().getBean("scimGroupProvisioning");
groupMembershipManager = (JdbcScimGroupMembershipManager) getWebApplicationContext().getBean("groupMembershipManager");
tokenServices = (UaaTokenServices) getWebApplicationContext().getBean("tokenServices");
defaultAuthorities = (Set<String>) getWebApplicationContext().getBean("defaultUserAuthorities");
identityZoneProvisioning = getWebApplicationContext().getBean(IdentityZoneProvisioning.class);
jdbcScimUserProvisioning = getWebApplicationContext().getBean(JdbcScimUserProvisioning.class);
identityProviderProvisioning = getWebApplicationContext().getBean(JdbcIdentityProviderProvisioning.class);
IdentityZoneHolder.clear();
adminToken =
getClientCredentialsOAuthAccessToken(
getMockMvc(),
"admin",
"adminsecret",
"uaa.admin",
null
);
tokenProvisioning = (RevocableTokenProvisioning) getWebApplicationContext().getBean("revocableTokenProvisioning");
}
public String setUpUserForPasswordGrant() throws Exception {
String username = "testuser" + generator.generate();
String userScopes = "uaa.user";
ScimUser user = setUpUser(username, userScopes, OriginKeys.UAA, IdentityZone.getUaa().getId());
ScimUserProvisioning provisioning = getWebApplicationContext().getBean(ScimUserProvisioning.class);
ScimUser scimUser = provisioning.retrieve(user.getId());
assertNull(scimUser.getLastLogonTime());
assertNull(scimUser.getPreviousLogonTime());
return username;
}
protected IdentityZone setupIdentityZone(String subdomain) {
IdentityZone zone = new IdentityZone();
zone.getConfig().getTokenPolicy().setKeys(Collections.singletonMap(subdomain+"_key", "key_for_"+subdomain));
zone.setId(UUID.randomUUID().toString());
zone.setName(subdomain);
zone.setSubdomain(subdomain);
zone.setDescription(subdomain);
identityZoneProvisioning.create(zone);
return zone;
}
protected IdentityProvider setupIdentityProvider() {
return setupIdentityProvider(OriginKeys.UAA);
}
protected IdentityProvider setupIdentityProvider(String origin) {
IdentityProvider defaultIdp = new IdentityProvider();
defaultIdp.setName(origin);
defaultIdp.setType(origin);
defaultIdp.setOriginKey(origin);
defaultIdp.setIdentityZoneId(IdentityZoneHolder.get().getId());
return identityProviderProvisioning.create(defaultIdp);
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove) {
return setUpClients(id, authorities, scopes, grantTypes, autoapprove, null);
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove, String redirectUri) {
return setUpClients(id, authorities, scopes, grantTypes, autoapprove, redirectUri, null);
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove, String redirectUri, List<String> allowedIdps) {
return setUpClients(id, authorities, scopes, grantTypes, autoapprove, redirectUri, allowedIdps, -1);
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove, String redirectUri, List<String> allowedIdps, int accessTokenValidity) {
return setUpClients(id, authorities, scopes, grantTypes, autoapprove, redirectUri, allowedIdps, accessTokenValidity, null);
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove, String redirectUri, List<String> allowedIdps, int accessTokenValidity, IdentityZone zone) {
return setUpClients(id, authorities, scopes, grantTypes, autoapprove, redirectUri, allowedIdps, accessTokenValidity, zone, Collections.emptyMap());
}
protected BaseClientDetails setUpClients(String id, String authorities, String scopes, String grantTypes, Boolean autoapprove, String redirectUri, List<String> allowedIdps, int accessTokenValidity, IdentityZone zone, Map<String,Object> additionalInfo) {
IdentityZone original = IdentityZoneHolder.get();
if (zone!=null) {
IdentityZoneHolder.set(zone);
}
BaseClientDetails c = new BaseClientDetails(id, "", scopes, grantTypes, authorities);
if (!"implicit".equals(grantTypes)) {
c.setClientSecret(SECRET);
}
c.setRegisteredRedirectUri(new HashSet<>(Arrays.asList(TEST_REDIRECT_URI)));
c.setAutoApproveScopes(Collections.singleton(autoapprove.toString()));
Map<String, Object> additional = new HashMap<>();
if (allowedIdps!=null && !allowedIdps.isEmpty()) {
additional.put(ClientConstants.ALLOWED_PROVIDERS, allowedIdps);
}
additional.putAll(additionalInfo);
c.setAdditionalInformation(additional);
if (hasText(redirectUri)) {
c.setRegisteredRedirectUri(new HashSet<>(Arrays.asList(redirectUri)));
}
if (accessTokenValidity>0) {
c.setAccessTokenValiditySeconds(accessTokenValidity);
}
try {
clientDetailsService.addClientDetails(c);
return (BaseClientDetails) clientDetailsService.loadClientByClientId(c.getClientId());
} finally {
IdentityZoneHolder.set(original);
}
}
protected ScimUser setUpUser(String username, String scopes, String origin, String zoneId) {
IdentityZone original = IdentityZoneHolder.get();
ScimUser user = new ScimUser(null, username, "GivenName", "FamilyName");
if (hasText(zoneId)) {
IdentityZone zone = identityZoneProvisioning.retrieve(zoneId);
IdentityZoneHolder.set(zone);
user.setZoneId(zoneId);
}
try {
user.setPassword(SECRET);
ScimUser.Email email = new ScimUser.Email();
email.setValue("test@test.org");
email.setPrimary(true);
user.setEmails(Arrays.asList(email));
user.setVerified(true);
user.setOrigin(origin);
user = userProvisioning.createUser(user, SECRET);
Set<String> scopeSet = StringUtils.commaDelimitedListToSet(scopes);
Set<ScimGroup> groups = new HashSet<>();
for (String scope : scopeSet) {
ScimGroup g = createIfNotExist(scope, zoneId);
groups.add(g);
addMember(user, g);
}
return userProvisioning.retrieve(user.getId());
} finally {
IdentityZoneHolder.set(original);
}
}
protected ScimUser syncGroups(ScimUser user) {
if (user == null) {
return user;
}
Set<ScimGroup> directGroups = groupMembershipManager.getGroupsWithMember(user.getId(), false);
Set<ScimGroup> indirectGroups = groupMembershipManager.getGroupsWithMember(user.getId(), true);
indirectGroups.removeAll(directGroups);
Set<ScimUser.Group> groups = new HashSet<ScimUser.Group>();
for (ScimGroup group : directGroups) {
groups.add(new ScimUser.Group(group.getId(), group.getDisplayName(), ScimUser.Group.Type.DIRECT));
}
for (ScimGroup group : indirectGroups) {
groups.add(new ScimUser.Group(group.getId(), group.getDisplayName(), ScimUser.Group.Type.INDIRECT));
}
user.setGroups(groups);
return user;
}
protected ScimGroupMember addMember(ScimUser user, ScimGroup group) {
ScimGroupMember gm = new ScimGroupMember(user.getId());
try {
return groupMembershipManager.addMember(group.getId(), gm);
}catch (MemberAlreadyExistsException x) {
return gm;
}
}
protected ScimGroup createIfNotExist(String scope, String zoneId) {
List<ScimGroup> exists = groupProvisioning.query("displayName eq \"" + scope + "\" and identity_zone_id eq \""+zoneId+"\"");
if (exists.size() > 0) {
return exists.get(0);
} else {
return groupProvisioning.create(new ScimGroup(null,scope,zoneId));
}
}
}