mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-26 13:50:48 +00:00
Account resource sharing resolves recipient by username before email, granting access to wrong user
Closes #49086 Signed-off-by: Martin Kanis <mkanis@ibm.com>
This commit is contained in:
+7
-3
@@ -244,12 +244,16 @@ public class ResourceService extends AbstractResourceService {
|
||||
|
||||
private UserModel getUser(String requester) {
|
||||
UserProvider users = provider.getKeycloakSession().users();
|
||||
UserModel user = users.getUserByUsername(provider.getRealm(), requester);
|
||||
UserModel userByUsername = users.getUserByUsername(provider.getRealm(), requester);
|
||||
UserModel userByEmail = users.getUserByEmail(provider.getRealm(), requester);
|
||||
|
||||
if (user == null) {
|
||||
user = users.getUserByEmail(provider.getRealm(), requester);
|
||||
if (userByUsername != null && userByEmail != null
|
||||
&& !userByUsername.getId().equals(userByEmail.getId())) {
|
||||
throw new BadRequestException("ambiguous_user");
|
||||
}
|
||||
|
||||
UserModel user = userByUsername != null ? userByUsername : userByEmail;
|
||||
|
||||
if (user == null) {
|
||||
throw new NotFoundException(requester);
|
||||
}
|
||||
|
||||
+29
@@ -448,6 +448,35 @@ public class ResourcesRestServiceTest extends AbstractRestServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShareResourceRejectsAmbiguousUsernameEmail() throws Exception {
|
||||
RealmRepresentation realm = managedRealm.admin().toRepresentation();
|
||||
realm.setLoginWithEmailAllowed(false);
|
||||
managedRealm.admin().update(realm);
|
||||
|
||||
UserRepresentation alice = findUser("alice");
|
||||
|
||||
// Create an attacker user whose username matches the email of a legitimate user.
|
||||
UserRepresentation attacker = createUser("alice@test.com", "password", "Attacker", "X", "attacker@test.com");
|
||||
managedRealm.admin().users().create(attacker);
|
||||
|
||||
alice.setEmail("alice@test.com");
|
||||
managedRealm.admin().users().get(alice.getId()).update(alice);
|
||||
|
||||
// The resource owner shares with "alice@test.com" intending alice (by email) but there is a clash as "alice@test.com"
|
||||
// is also the attacker's username -> reject the request due to unambiguity
|
||||
List<Permission> permissions = new ArrayList<>();
|
||||
permissions.add(new Permission("alice@test.com", "Scope A"));
|
||||
|
||||
String resourceId = getMyResources().get(0).getId();
|
||||
SimpleHttpResponse response = SimpleHttpDefault.doPut(
|
||||
getAccountUrl("resources/" + encodePathAsIs(resourceId) + "/permissions"), httpClient)
|
||||
.auth(tokenUtil.getToken())
|
||||
.json(permissions).asResponse();
|
||||
|
||||
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failShareResourceInvalidPermissions() throws Exception {
|
||||
List<Permission> permissions = new ArrayList<>();
|
||||
|
||||
Reference in New Issue
Block a user