diff --git a/spaces.module b/spaces.module
index c87f245..fc89d2e 100644
--- a/spaces.module
+++ b/spaces.module
@@ -693,18 +693,19 @@ function spaces_menu_access() {
     }
     else {
       foreach (array_filter($args, 'is_object') as $object) {
-        if (isset($object->nid)) {
-          spaces_router('node', $object);
-          $feature = !empty($map[$object->type]) ? reset($map[$object->type]) : NULL;
-          if ($feature) {
-            return spaces_access_feature('view', $feature);
+        $type = isset($object->nid) ? 'node' : (isset($object->uid) ? 'user' : NULL);
+        if ($type && spaces_is_spaces_object($type, $object)) {
+          if ($type == 'node') {
+            $feature = !empty($map[$object->type]) ? reset($map[$object->type]) : NULL;
+            if ($feature) {
+              return spaces_access_feature('view', $feature);
+            }
           }
+          elseif ($type == 'user') {
+            return spaces_access_user('view', $object);
+          }
+          break;
         }
-        elseif (isset($object->uid)) {
-          spaces_router('user', $object);
-          return spaces_access_user('view', $object);
-        }
-        break;
       }
     }
     return TRUE;
@@ -778,6 +779,37 @@ function spaces_init() {
     menu_set_active_item('spaces-access-denied');
   }
   spaces_router('init');
+
+  /**
+   * If the current menu object is not part of the space, this will
+   * redirect it to the correct space.
+   *
+   * Since the menu returns TRUE in the cases a redirect is needed if
+   * the user has access to the item, the object will be stored in the
+   * menu for this to fetch and redirect.
+   */
+
+  // Can't call menu_get_item in hook_init without this.
+  if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {
+    menu_rebuild();
+  }
+
+  // Simplist case, get the node.
+  if ($object = menu_get_object()) {
+    $type = 'node';
+  }
+  // user has various load functions
+  elseif (($item = menu_get_item()) && isset($item['map'])) {
+    foreach (array_filter($item['map'], 'is_object') as $object) {
+      $type = isset($object->nid) ? 'node' : (isset($object->uid) ? 'user' : NULL);;
+      break;
+    }
+  }
+
+  // If the space is incorrect, reroute.
+  if ($type && !spaces_is_spaces_object($type, $object)) {
+    spaces_router($type, $object);
+  }
 }
 
 /**
@@ -976,3 +1008,36 @@ function _spaces_json_decode($json) {
   eval($out . ';');
   return $x;
 }
+
+/**
+ * Get the space that an $object is in.
+ */
+function spaces_get_space_from_object($type, $object) {
+  static $spaces;
+  $id = $type == 'node' ? $object->nid : $object->uid;
+  if (!isset($spaces[$type][$id])) {
+    $spaces = module_invoke_all('spaces_get_space_from_object', $type, $object);
+    if ($space = current($spaces)) {
+      $spaces[$type][$id] = array('type' => $space->type, 'id' => $space->id);
+    }
+    else {
+      $spaces[$type][$id] = FALSE;
+    }
+  }
+  return $spaces[$type][$id] ? spaces_load($spaces[$type][$id]['type'], $spaces[$type][$id]['id']) : FALSE;
+}
+
+/**
+ * Tests whether the object is part of the current space.
+ */
+function spaces_is_spaces_object($type, $object) {
+  if ($object_space = spaces_get_space_from_object($type, $object)) {
+    if (($current_space = spaces_get_space())) {
+      return $object_space->id == $current_space->id && $object_space->type == $current_space->type;
+    }
+    else {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
diff --git a/spaces_og/spaces_og.module b/spaces_og/spaces_og.module
index 878a22e..b577693 100644
--- a/spaces_og/spaces_og.module
+++ b/spaces_og/spaces_og.module
@@ -542,3 +542,18 @@ function spaces_og_views_api() {
     'path' => drupal_get_path('module', 'spaces_og') .'/views',
   );
 }
+
+/**
+ * Implementation of hook_spaces_get_space_from_object().
+ */
+function spaces_og_spaces_get_space_from_object($type, $object) {
+  if ($type == 'node') {
+    if (og_is_group_type($node->type)) {
+      return spaces_load('og', $node->nid);
+    }
+    elseif (!empty($object->og_groups)) {
+      reset($object->og_groups);
+      return spaces_load('og', current($object->og_groups));
+    }
+  }
+}
diff --git a/spaces_user/spaces_user.module b/spaces_user/spaces_user.module
index ddff36d..7c87dbe 100644
--- a/spaces_user/spaces_user.module
+++ b/spaces_user/spaces_user.module
@@ -102,3 +102,13 @@ function spaces_user_form_spaces_features_form_alter(&$form, &$form_state) {
     unset($form['site_frontpage']);
   }
 }
+
+
+/**
+ * Implementation of hook_spaces_get_space_from_object().
+ */
+function spaces_user_spaces_get_space_from_object($type, $object) {
+  if ($type == 'user') {
+    return spaces_load('user', $object->uid);
+  }
+}
