From 042fcfeb508cde2647fedee53c28f4037255c5ed Mon Sep 17 00:00:00 2001
From: Dean Townsley <dean@townsley.com>
Date: Sat, 22 Jun 2019 12:34:54 -0500
Subject: [PATCH] Enable multi-auth in dfrn autoRedir

Update checks to account for a user being authenticated to multiple
contacts on the local server at the same time.
It was also necessary to remove a looping procection to make this work
correcly with browsers that open multiple connections because the
information about what contacts are authenticated is stored in the PHP
session.
---
 src/Protocol/DFRN.php | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index ec4557e82..0e2bfc579 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -2899,7 +2899,12 @@ class DFRN
 	{
 		// prevent looping
 		if (!empty($_REQUEST['redir'])) {
-			return;
+			Logger::log('autoRedir might be looping because is redir', Logger::DEBUG);
+			// looping prevention also appears to sometimes prevent authentication for images
+			// because browser may have multiple connections open and load an image on a connection
+			// whose session wasn't updated when a previous redirect authenticated
+			// Leaving commented in case looping reappears
+			//return;
 		}
 
 		if ((! $contact_nick) || ($contact_nick === $a->user['nickname'])) {
@@ -2923,6 +2928,9 @@ class DFRN
 			$baseurl = substr($baseurl, $domain_st + 3);
 			$nurl = Strings::normaliseLink($baseurl);
 
+			$r = DBA::selectFirst("user", ["uid"], ["nickname" => DBA::escape($contact_nick)], []);
+			$contact_uid = $r["uid"];
+
 			/// @todo Why is there a query for "url" *and* "nurl"? Especially this normalising is strange.
 			$r = q("SELECT `id` FROM `contact` WHERE `uid` = (SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1)
 					AND `nick` = '%s' AND NOT `self` AND (`url` LIKE '%%%s%%' OR `nurl` LIKE '%%%s%%') AND NOT `blocked` AND NOT `pending` LIMIT 1",
@@ -2931,9 +2939,18 @@ class DFRN
 				DBA::escape($baseurl),
 				DBA::escape($nurl)
 			);
-			if ((! DBA::isResult($r)) || $r[0]['id'] == remote_user()) {
+			if ((! DBA::isResult($r))) {
 				return;
 			}
+			// test if redirect authentication already succeeded
+			// Note that "contact" in the sense used in $contact_nick and the sense in the $remote[]["cid"]
+			// in the session are opposite.  In the session variable the user currently fetching is the contact
+			// while $contact_nick is the nick of tho user who owns the stuff being fetched.
+			foreach (\Friendica\Core\Session::get('remote', []) as $visitor) {
+				if ($visitor['uid'] == $contact_uid && $visitor['cid'] == $r[0]['id']) {
+					return;
+				}
+			}
 
 			$r = q("SELECT * FROM contact WHERE nick = '%s'
 					AND network = '%s' AND uid = %d  AND url LIKE '%%%s%%' LIMIT 1",