diff --git a/README.md b/README.md
index 2c5f978..1cf7e9f 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,7 @@ The following changes are already implemented:
 * [Custom Menu Items](https://github.com/etkecc/synapse-admin/pull/79)
 * [Add user profile to the top menu](https://github.com/etkecc/synapse-admin/pull/80)
 * [Enable visual customization](https://github.com/etkecc/synapse-admin/pull/81)
+* [Fix room state events display](https://github.com/etkecc/synapse-admin/pull/100)
 
 _the list will be updated as new changes are added_
 
diff --git a/src/resources/rooms.tsx b/src/resources/rooms.tsx
index 53e5d30..526c8bf 100644
--- a/src/resources/rooms.tsx
+++ b/src/resources/rooms.tsx
@@ -187,7 +187,7 @@ export const RoomShow = (props: ShowProps) => {
             <Datagrid style={{ width: "100%" }} bulkActionButtons={false}>
               <TextField source="type" sortable={false} />
               <DateField source="origin_server_ts" showTime options={DATE_FORMAT} sortable={false} />
-              <TextField source="content" sortable={false} />
+              <FunctionField source="content" sortable={false} render={record => `${JSON.stringify(record.content, null, 2)}`} />
               <ReferenceField source="sender" reference="users" sortable={false}>
                 <TextField source="id" />
               </ReferenceField>
diff --git a/src/synapse/authProvider.ts b/src/synapse/authProvider.ts
index 112a610..3de09a6 100644
--- a/src/synapse/authProvider.ts
+++ b/src/synapse/authProvider.ts
@@ -75,7 +75,7 @@ const authProvider: AuthProvider = {
 
       response = await fetchUtils.fetchJson(login_api_url, options);
       const json = response.json;
-      storage.setItem("home_server", accessToken ? base_url : json.home_server);
+      storage.setItem("home_server", accessToken ? json.user_id.split(":")[1] : json.home_server);
       storage.setItem("user_id", json.user_id);
       storage.setItem("access_token", accessToken ? accessToken : json.access_token);
       storage.setItem("device_id", json.device_id);
diff --git a/src/synapse/dataProvider.ts b/src/synapse/dataProvider.ts
index 9193586..9203d8a 100644
--- a/src/synapse/dataProvider.ts
+++ b/src/synapse/dataProvider.ts
@@ -575,13 +575,28 @@ const baseDataProvider: SynapseDataProvider = {
 
   getMany: async (resource, params) => {
     console.log("getMany " + resource);
-    const homeserver = storage.getItem("base_url");
-    if (!homeserver || !(resource in resourceMap)) throw Error("Homerserver not set");
+    const base_url = storage.getItem("base_url");
+    const homeserver = storage.getItem("home_server");
+    if (!base_url || !(resource in resourceMap)) throw Error("base_url not set");
 
     const res = resourceMap[resource];
 
-    const endpoint_url = homeserver + res.path;
-    const responses = await Promise.all(params.ids.map(id => jsonClient(`${endpoint_url}/${encodeURIComponent(id)}`)));
+    const endpoint_url = base_url + res.path;
+    const responses = await Promise.all(params.ids.map(id => {
+      // edge case: when user is external / federated, homeserver will return error, as querying external users via
+      // /_synapse/admin/v2/users is not allowed.
+      // That leads to an issue when a user is referenced (e.g., in room state datagrid) - the user cell is just empty.
+      // To avoid that, we fake the response with one specific field (name) which is used in the datagrid.
+      if (homeserver && resource === "users") {
+        if (!(<string>id).endsWith(homeserver)) {
+          const json = {
+              name: id,
+          };
+          return Promise.resolve({ json });
+        }
+      }
+      return jsonClient(`${endpoint_url}/${encodeURIComponent(id)}`);
+    }));
     return {
       data: responses.map(({ json }) => res.map(json)),
       total: responses.length,