From cc742ce9e7a2df00f4309e4b3b9fc8d5642ff59f Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Fri, 12 Jan 2018 08:57:51 +0100 Subject: [PATCH 1/2] Fix bug with proxies Signed-off-by: Mario Danic --- core/Controller/ClientFlowLoginController.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/Controller/ClientFlowLoginController.php b/core/Controller/ClientFlowLoginController.php index 7d6e79d39b..0e7fbf892b 100644 --- a/core/Controller/ClientFlowLoginController.php +++ b/core/Controller/ClientFlowLoginController.php @@ -315,7 +315,18 @@ class ClientFlowLoginController extends Controller { $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/login/flow')); } - $serverPath = $this->request->getServerProtocol() . "://" . $this->request->getServerHost() . $serverPostfix; + $protocol = $this->request->getServerProtocol(); + + if ($protocol !== "https") { + $xForwardedProto = $this->request->getHeader('X-Forwarded-Proto'); + $xForwardedSSL = $this->request->getHeader('X-Forwarded-Ssl'); + if ($xForwardedProto === 'https' || $xForwardedSSL === 'on') { + $protocol = 'https'; + } + } + + + $serverPath = $protocol . "://" . $this->request->getServerHost() . $serverPostfix; $redirectUri = 'nc://login/server:' . $serverPath . '&user:' . urlencode($loginName) . '&password:' . urlencode($token); } From 7789fbdea6445f39da3866f9de4b7b2208f64ea7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 12 Jan 2018 09:39:21 +0100 Subject: [PATCH 2/2] Add unit test Signed-off-by: Joas Schilling --- .../ClientFlowLoginControllerTest.php | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/tests/Core/Controller/ClientFlowLoginControllerTest.php b/tests/Core/Controller/ClientFlowLoginControllerTest.php index 2167386322..0e04853822 100644 --- a/tests/Core/Controller/ClientFlowLoginControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginControllerTest.php @@ -587,4 +587,127 @@ class ClientFlowLoginControllerTest extends TestCase { $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } + + public function dataGeneratePasswordWithHttpsProxy() { + return [ + [ + [ + ['X-Forwarded-Proto', 'http'], + ['X-Forwarded-Ssl', 'off'], + ], + 'http', + 'http', + ], + [ + [ + ['X-Forwarded-Proto', 'http'], + ['X-Forwarded-Ssl', 'off'], + ], + 'https', + 'https', + ], + [ + [ + ['X-Forwarded-Proto', 'https'], + ['X-Forwarded-Ssl', 'off'], + ], + 'http', + 'https', + ], + [ + [ + ['X-Forwarded-Proto', 'https'], + ['X-Forwarded-Ssl', 'on'], + ], + 'http', + 'https', + ], + [ + [ + ['X-Forwarded-Proto', 'http'], + ['X-Forwarded-Ssl', 'on'], + ], + 'http', + 'https', + ], + ]; + } + + /** + * @dataProvider dataGeneratePasswordWithHttpsProxy + * @param array $headers + * @param string $protocol + * @param string $expected + */ + public function testGeneratePasswordWithHttpsProxy(array $headers, $protocol, $expected) { + $this->session + ->expects($this->once()) + ->method('get') + ->with('client.flow.state.token') + ->willReturn('MyStateToken'); + $this->session + ->expects($this->once()) + ->method('remove') + ->with('client.flow.state.token'); + $this->session + ->expects($this->once()) + ->method('getId') + ->willReturn('SessionId'); + $myToken = $this->createMock(IToken::class); + $myToken + ->expects($this->once()) + ->method('getLoginName') + ->willReturn('MyLoginName'); + $this->tokenProvider + ->expects($this->once()) + ->method('getToken') + ->with('SessionId') + ->willReturn($myToken); + $this->tokenProvider + ->expects($this->once()) + ->method('getPassword') + ->with($myToken, 'SessionId') + ->willReturn('MyPassword'); + $this->random + ->expects($this->once()) + ->method('generate') + ->with(72) + ->willReturn('MyGeneratedToken'); + $user = $this->createMock(IUser::class); + $user + ->expects($this->once()) + ->method('getUID') + ->willReturn('MyUid'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($user); + $this->tokenProvider + ->expects($this->once()) + ->method('generateToken') + ->with( + 'MyGeneratedToken', + 'MyUid', + 'MyLoginName', + 'MyPassword', + 'unknown', + IToken::PERMANENT_TOKEN, + IToken::DO_NOT_REMEMBER + ); + $this->request + ->expects($this->once()) + ->method('getServerProtocol') + ->willReturn($protocol); + $this->request + ->expects($this->once()) + ->method('getServerHost') + ->willReturn('example.com'); + $this->request + ->expects($this->atLeastOnce()) + ->method('getHeader') + ->willReturnMap($headers); + + $expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken'); + $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); + } }