diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
index e516134467886402082cb7c16d0f16d1dcddb422..bfbdf5c8c79d66a02f8695c2d40c685e59c1555b 100644
--- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
@@ -49,6 +49,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 import java.util.logging.Logger;
@@ -65,15 +66,15 @@ import static org.junit.Assert.assertTrue;
 
 public class ForumSharingIntegrationTest extends BriarTestCase {
 
-	LifecycleManager lifecycleManager0, lifecycleManager1;
-	SyncSessionFactory sync0, sync1;
-	ForumManager forumManager0, forumManager1;
-	ContactManager contactManager0, contactManager1;
-	ContactId contactId0, contactId1;
-	IdentityManager identityManager0, identityManager1;
-	LocalAuthor author0, author1;
+	LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
+	SyncSessionFactory sync0, sync1, sync2;
+	ForumManager forumManager0, forumManager1, forumManager2;
+	ContactManager contactManager0, contactManager1, contactManager2;
+	ContactId contactId0, contactId2, contactId1, contactId21;
+	IdentityManager identityManager0, identityManager1, identityManager2;
+	LocalAuthor author0, author1, author2;
 	Forum forum0;
-	SharerListener listener0;
+	SharerListener listener0, listener2;
 	InviteeListener listener1;
 
 	@Inject
@@ -84,6 +85,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 	// objects accessed from background threads need to be volatile
 	private volatile ForumSharingManager forumSharingManager0;
 	private volatile ForumSharingManager forumSharingManager1;
+	private volatile ForumSharingManager forumSharingManager2;
 	private volatile Waiter eventWaiter;
 	private volatile Waiter msgWaiter;
 
@@ -92,11 +94,12 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 	private final int TIMEOUT = 15000;
 	private final String SHARER = "Sharer";
 	private final String INVITEE = "Invitee";
+	private final String SHARER2 = "Sharer2";
 
 	private static final Logger LOG =
 			Logger.getLogger(ForumSharingIntegrationTest.class.getName());
 
-	private ForumSharingIntegrationTestComponent t0, t1;
+	private ForumSharingIntegrationTestComponent t0, t1, t2;
 
 	@Rule
 	public ExpectedException thrown=ExpectedException.none();
@@ -117,17 +120,26 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 		t1 = DaggerForumSharingIntegrationTestComponent.builder()
 				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
 		injectEagerSingletons(t1);
+		File t2Dir = new File(testDir, SHARER2);
+		t2 = DaggerForumSharingIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(t2);
 
 		identityManager0 = t0.getIdentityManager();
 		identityManager1 = t1.getIdentityManager();
+		identityManager2 = t2.getIdentityManager();
 		contactManager0 = t0.getContactManager();
 		contactManager1 = t1.getContactManager();
+		contactManager2 = t2.getContactManager();
 		forumManager0 = t0.getForumManager();
 		forumManager1 = t1.getForumManager();
+		forumManager2 = t2.getForumManager();
 		forumSharingManager0 = t0.getForumSharingManager();
 		forumSharingManager1 = t1.getForumSharingManager();
+		forumSharingManager2 = t2.getForumSharingManager();
 		sync0 = t0.getSyncSessionFactory();
 		sync1 = t1.getSyncSessionFactory();
+		sync2 = t2.getSyncSessionFactory();
 
 		// initialize waiters fresh for each test
 		eventWaiter = new Waiter();
@@ -474,7 +486,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 			assertEquals(1, forumManager1.getForums().size());
 
 			// invitee now shares same forum back
-			forumSharingManager1.sendForumInvitation(forum0.getId(), contactId0,
+			forumSharingManager1.sendForumInvitation(forum0.getId(),
+					contactId0,
 					"I am re-sharing this forum with you.");
 
 			// sync re-share invitation
@@ -526,7 +539,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 
 			// contacts now remove each other
 			contactManager0.removeContact(contactId1);
+			contactManager2.removeContact(contactId21);
 			contactManager1.removeContact(contactId0);
+			contactManager1.removeContact(contactId2);
 
 			// make sure sharer does share the forum with nobody now
 			assertEquals(0,
@@ -572,6 +587,75 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 		}
 	}
 
+	@Test
+	public void testTwoContactsShareSameForum() throws Exception {
+		startLifecycles();
+		try {
+			// initialize
+			addDefaultIdentities();
+			addDefaultContacts();
+			addForumForSharer();
+
+			// second sharer adds the same forum
+			DatabaseComponent db2 = t2.getDatabaseComponent();
+			Transaction txn = db2.startTransaction(false);
+			db2.addGroup(txn, forum0.getGroup());
+			txn.setComplete();
+			db2.endTransaction(txn);
+
+			// add listeners
+			listener0 = new SharerListener();
+			t0.getEventBus().addListener(listener0);
+			listener1 = new InviteeListener(true, false);
+			t1.getEventBus().addListener(listener1);
+			listener2 = new SharerListener();
+			t2.getEventBus().addListener(listener2);
+
+			// send invitation
+			forumSharingManager0
+					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
+			// sync first request message
+			syncToInvitee();
+
+			// second sharer sends invitation for same forum
+			forumSharingManager2
+					.sendForumInvitation(forum0.getId(), contactId1, null);
+			// sync second request message
+			deliverMessage(sync2, contactId2, sync1, contactId1,
+					"Sharer2 to Invitee");
+
+			// make sure we have only one forum available
+			Collection<Forum> forums =
+					forumSharingManager1.getAvailableForums();
+			assertEquals(1, forums.size());
+
+			// make sure both sharers actually share the forum
+			Collection<Contact> contacts =
+					forumSharingManager1.getSharedBy(forum0.getId());
+			assertEquals(2, contacts.size());
+
+			// answer second request
+			Contact c2 = contactManager1.getContact(contactId2);
+			forumSharingManager1.respondToInvitation(forum0, c2, true);
+			// sync response
+			deliverMessage(sync1, contactId21, sync2, contactId2,
+					"Invitee to Sharer2");
+			eventWaiter.await(TIMEOUT, 1);
+			assertTrue(listener2.responseReceived);
+
+			// answer first request
+			Contact c0 =
+					contactManager1.getContact(contactId0);
+			forumSharingManager1.respondToInvitation(forum0, c0, true);
+			// sync response
+			syncToSharer();
+			eventWaiter.await(TIMEOUT, 1);
+			assertTrue(listener0.responseReceived);
+		} finally {
+			stopLifecycles();
+		}
+	}
+
 
 	@After
 	public void tearDown() throws InterruptedException {
@@ -609,7 +693,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 				requestReceived = true;
 				Forum f = event.getForum();
 				try {
-					forumSharingManager0.respondToInvitation(f, true);
+					Contact c = contactManager0.getContact(contactId1);
+					forumSharingManager0.respondToInvitation(f, c, true);
 				} catch (DbException ex) {
 					eventWaiter.rethrow(ex);
 				} finally {
@@ -624,10 +709,15 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 		public volatile boolean requestReceived = false;
 		public volatile boolean responseReceived = false;
 
-		private final boolean accept;
+		private final boolean accept, answer;
 
-		InviteeListener(boolean accept) {
+		InviteeListener(boolean accept, boolean answer) {
 			this.accept = accept;
+			this.answer = answer;
+		}
+
+		InviteeListener(boolean accept) {
+			this(accept, true);
 		}
 
 		public void eventOccurred(Event e) {
@@ -644,11 +734,13 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 			} else if (e instanceof ForumInvitationReceivedEvent) {
 				ForumInvitationReceivedEvent event =
 						(ForumInvitationReceivedEvent) e;
-				eventWaiter.assertEquals(contactId0, event.getContactId());
 				requestReceived = true;
+				if (!answer) return;
 				Forum f = event.getForum();
 				try {
-					forumSharingManager1.respondToInvitation(f, accept);
+					Contact c =
+							contactManager1.getContact(event.getContactId());
+					forumSharingManager1.respondToInvitation(f, c, accept);
 				} catch (DbException ex) {
 					eventWaiter.rethrow(ex);
 				} finally {
@@ -670,18 +762,23 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 		// Start the lifecycle manager and wait for it to finish
 		lifecycleManager0 = t0.getLifecycleManager();
 		lifecycleManager1 = t1.getLifecycleManager();
+		lifecycleManager2 = t2.getLifecycleManager();
 		lifecycleManager0.startServices();
 		lifecycleManager1.startServices();
+		lifecycleManager2.startServices();
 		lifecycleManager0.waitForStartup();
 		lifecycleManager1.waitForStartup();
+		lifecycleManager2.waitForStartup();
 	}
 
 	private void stopLifecycles() throws InterruptedException {
 		// Clean up
 		lifecycleManager0.stopServices();
 		lifecycleManager1.stopServices();
+		lifecycleManager2.stopServices();
 		lifecycleManager0.waitForShutdown();
 		lifecycleManager1.waitForShutdown();
+		lifecycleManager2.waitForShutdown();
 	}
 
 	private void defaultInit(boolean accept) throws DbException {
@@ -700,6 +797,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
 				TestUtils.getRandomBytes(123));
 		identityManager1.addLocalAuthor(author1);
+		author2 = authorFactory.createLocalAuthor(SHARER2,
+				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
+				TestUtils.getRandomBytes(123));
+		identityManager2.addLocalAuthor(author2);
 	}
 
 	private void addDefaultContacts() throws DbException {
@@ -708,11 +809,20 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 				author0.getId(), master, clock.currentTimeMillis(), true,
 				true
 		);
-		// invitee adds sharer back
+		// second sharer does the same
+		contactId21 = contactManager2.addContact(author1,
+				author2.getId(), master, clock.currentTimeMillis(), true,
+				true
+		);
+		// invitee adds sharers back
 		contactId0 = contactManager1.addContact(author0,
 				author1.getId(), master, clock.currentTimeMillis(), true,
 				true
 		);
+		contactId2 = contactManager1.addContact(author2,
+				author1.getId(), master, clock.currentTimeMillis(), true,
+				true
+		);
 	}
 
 	private void addForumForSharer() throws DbException {
@@ -725,6 +835,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 		t0.getEventBus().addListener(listener0);
 		listener1 = new InviteeListener(accept);
 		t1.getEventBus().addListener(listener1);
+		listener2 = new SharerListener();
+		t2.getEventBus().addListener(listener2);
 	}
 
 	private void syncToInvitee() throws IOException, TimeoutException {
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index bcf39e8360766b1e722912f3a6c7faec994f4ceb..ed05d2863e38de8d947f730094691ef20954ba89 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -153,7 +153,7 @@ public class AvailableForumsActivity extends BriarActivity
 
 	@Override
 	public void onItemClick(AvailableForumsItem item, boolean accept) {
-		respondToInvitation(item.getForum(), accept);
+		respondToInvitation(item, accept);
 
 		// show toast
 		int res = R.string.forum_declined_toast;
@@ -161,12 +161,16 @@ public class AvailableForumsActivity extends BriarActivity
 		Toast.makeText(this, res, LENGTH_SHORT).show();
 	}
 
-	private void respondToInvitation(final Forum f, final boolean accept) {
-		runOnDbThread(new Runnable() {
+	private void respondToInvitation(final AvailableForumsItem item,
+			final boolean accept) {
+		briarController.runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
 				try {
-					forumSharingManager.respondToInvitation(f, accept);
+					Forum f = item.getForum();
+					for (Contact c : item.getContacts()) {
+						forumSharingManager.respondToInvitation(f, c, accept);
+					}
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
index 9f4cc87b6620aebb593a32f3f2e9e3655207aa9a..d20f427f6dc95dea0b23bc3b6bbf6a3e35fb928f 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
@@ -24,7 +24,8 @@ public interface ForumSharingManager {
 	/**
 	 * Responds to a pending forum invitation
 	 */
-	void respondToInvitation(Forum f, boolean accept) throws DbException;
+	void respondToInvitation(Forum f, Contact c, boolean accept)
+			throws DbException;
 
 	/**
 	 * Returns all forum sharing messages sent by the Contact
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
index 99cdce517842fcceb6ff98bc6b22b82921713388..01572fbcb6ec221dc7fb933488f0d84e341669d8 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
@@ -283,13 +283,14 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 	}
 
 	@Override
-	public void respondToInvitation(Forum f, boolean accept)
+	public void respondToInvitation(Forum f, Contact c, boolean accept)
 			throws DbException {
 
 		Transaction txn = db.startTransaction(false);
 		try {
 			// find session state based on forum
-			InviteeSessionState localState = getSessionStateForResponse(txn, f);
+			InviteeSessionState localState =
+					getSessionStateForResponse(txn, f, c);
 
 			// define action
 			InviteeSessionState.Action localAction;
@@ -562,17 +563,15 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 						"More than one session state found for message with session ID " +
 								Arrays.hashCode(sessionId.getBytes()));
 			}
-
-			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-				return fromBdfDictionary(m.getValue());
-			}
-
-			if (warn && LOG.isLoggable(WARNING)) {
-				LOG.warning(
-						"No session state found for message with session ID " +
-								Arrays.hashCode(sessionId.getBytes()));
+			if (map.isEmpty()) {
+				if (warn && LOG.isLoggable(WARNING)) {
+					LOG.warning(
+							"No session state found for message with session ID " +
+									Arrays.hashCode(sessionId.getBytes()));
+				}
+				throw new FormatException();
 			}
-			throw new FormatException();
+			return fromBdfDictionary(map.values().iterator().next());
 		}
 	}
 
@@ -590,11 +589,12 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 	}
 
 	private InviteeSessionState getSessionStateForResponse(Transaction txn,
-			Forum f) throws DbException, FormatException {
+			Forum f, Contact c) throws DbException, FormatException {
 
 		// query for invitee states for that forum in state await response
 		BdfDictionary query = BdfDictionary.of(
 				new BdfEntry(IS_SHARER, false),
+				new BdfEntry(CONTACT_ID, c.getId().getInt()),
 				new BdfEntry(FORUM_ID, f.getId()),
 				new BdfEntry(STATE,
 						InviteeSessionState.State.AWAIT_LOCAL_RESPONSE
@@ -604,26 +604,24 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 		Map<MessageId, BdfDictionary> map = clientHelper
 				.getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
 
-		// TODO we might have been invited to the same forum from several people
-		// in different sessions, so we need to handle this (#391)
 		if (map.size() > 1 && LOG.isLoggable(WARNING)) {
 			LOG.warning(
 					"More than one session state found for forum with ID " +
 							Arrays.hashCode(f.getId().getBytes()) +
-							" in state AWAIT_LOCAL_RESPONSE");
+							" in state AWAIT_LOCAL_RESPONSE for contact " +
+							c.getAuthor().getName());
 		}
-
-		for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-			return (InviteeSessionState) fromBdfDictionary(m.getValue());
-		}
-
-		if (LOG.isLoggable(WARNING)) {
-			LOG.warning(
-					"No session state found for forum with ID " +
-							Arrays.hashCode(f.getId().getBytes()) +
-							" in state AWAIT_LOCAL_RESPONSE");
+		if (map.isEmpty()) {
+			if (LOG.isLoggable(WARNING)) {
+				LOG.warning(
+						"No session state found for forum with ID " +
+								Arrays.hashCode(f.getId().getBytes()) +
+								" in state AWAIT_LOCAL_RESPONSE");
+			}
+			throw new DbException();
 		}
-		throw new DbException();
+		return (InviteeSessionState) fromBdfDictionary(
+				map.values().iterator().next());
 	}
 
 	private ForumSharingSessionState getSessionStateForLeaving(Transaction txn,