From 5d61d3390fd7b2c8f17ea5796b84b03ee61084eb Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Thu, 12 Mar 2020 21:14:40 +0000
Subject: [PATCH 01/20] Introduce App ID, closes #3 (#5)
---
src/AuthUri.php | 15 ++++++----
src/Authenticator.php | 4 +++
src/InitVectorNotSetException.php | 4 ---
test/phpunit/AuthUriTest.php | 43 +++++++++++++++++++++++++----
test/phpunit/AuthenticatorTest.php | 44 +++++++++++++++++++++++-------
5 files changed, 84 insertions(+), 26 deletions(-)
delete mode 100644 src/InitVectorNotSetException.php
diff --git a/src/AuthUri.php b/src/AuthUri.php
index 7472b60..df8e0a0 100644
--- a/src/AuthUri.php
+++ b/src/AuthUri.php
@@ -4,8 +4,9 @@
use Gt\Http\Uri;
class AuthUri extends Uri {
- const DEFAULT_BASE_URI = "login.authwave.com";
+ const DEFAULT_BASE_REMOTE_URI = "login.authwave.com";
+ const QUERY_STRING_ID = "id";
const QUERY_STRING_CIPHER = "cipher";
const QUERY_STRING_INIT_VECTOR = "iv";
const QUERY_STRING_CURRENT_PATH = "path";
@@ -14,20 +15,22 @@ class AuthUri extends Uri {
* @param Token $token This must be the same instance of the Token when
* creating Authenticator for the first time as it is when checking the
* response from the Authwave provider (store in a session).
+ * @param string $clientId
* @param string $currentPath
- * @param string $baseUri The base URI of the application. This is the
+ * @param string $baseRemoteUri The base URI of the application. This is the
* URI authority with optional scheme, as localhost allows http://
*/
public function __construct(
Token $token,
+ string $clientId,
string $currentPath = "/",
- string $baseUri = self::DEFAULT_BASE_URI
+ string $baseRemoteUri = self::DEFAULT_BASE_REMOTE_URI
) {
- $baseUri = $this->normaliseBaseUri($baseUri);
-
- parent::__construct($baseUri);
+ $baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
+ parent::__construct($baseRemoteUri);
$this->query = http_build_query([
+ self::QUERY_STRING_ID => $clientId,
self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher(),
self::QUERY_STRING_INIT_VECTOR => (string)$token->getIv(),
self::QUERY_STRING_CURRENT_PATH => $currentPath,
diff --git a/src/Authenticator.php b/src/Authenticator.php
index faa39b4..fae0113 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -14,8 +14,10 @@ class Authenticator {
private SessionContainer $session;
private SessionData $sessionData;
private RedirectHandler $redirectHandler;
+ private string $clientId;
public function __construct(
+ string $clientId,
string $clientKey,
string $currentUriPath,
string $authwaveHost = "login.authwave.com",
@@ -32,6 +34,7 @@ public function __construct(
$session->set(self::SESSION_KEY, new SessionData());
}
+ $this->clientId = $clientId;
$this->clientKey = $clientKey;
$this->currentUriPath = $currentUriPath;
$this->authwaveHost = $authwaveHost;
@@ -69,6 +72,7 @@ public function login(Token $token = null):void {
$loginUri = new AuthUri(
$token,
+ $this->clientId,
$this->currentUriPath,
$this->authwaveHost
);
diff --git a/src/InitVectorNotSetException.php b/src/InitVectorNotSetException.php
deleted file mode 100644
index ef6a6e3..0000000
--- a/src/InitVectorNotSetException.php
+++ /dev/null
@@ -1,4 +0,0 @@
-willReturn("https://example.com");
$token = self::createMock(Token::class);
- $sut = new AuthUri($token, "", $baseUri);
+ $sut = new AuthUri(
+ $token,
+ "example-app-id",
+ "",
+ $baseUri
+ );
self::assertEquals(
"https",
$sut->getScheme()
@@ -26,7 +31,13 @@ public function testAuthUriHttps() {
// But it should still default to HTTPS on localhost.
public function testGetAuthUriHostnameLocalhostHttpsByDefault() {
$token = self::createMock(Token::class);
- $sut = new AuthUri($token, "/", "localhost");
+ $sut = new AuthUri(
+ $token,
+ "example-app-id",
+ "/",
+ "localhost"
+ );
+
self::assertStringStartsWith(
"https://localhost",
$sut
@@ -36,7 +47,12 @@ public function testGetAuthUriHostnameLocalhostHttpsByDefault() {
// We should be able to set the scheme to HTTP for localhost hostname only.
public function testGetAuthUriHostnameLocalhostHttpAllowed() {
$token = self::createMock(Token::class);
- $sut = new AuthUri($token, "/", "http://localhost");
+ $sut = new AuthUri(
+ $token,
+ "example-app-id",
+ "/",
+ "http://localhost"
+ );
self::assertStringStartsWith(
"http://localhost",
$sut
@@ -47,7 +63,12 @@ public function testGetAuthUriHostnameLocalhostHttpAllowed() {
public function testGetAuthUriHostnameNotLocalhostHttpNotAllowed() {
$token = self::createMock(Token::class);
self::expectException(InsecureProtocolException::class);
- new AuthUri($token, "/", "http://localhost.com");
+ new AuthUri(
+ $token,
+ "example-app-id",
+ "/",
+ "http://localhost.com"
+ );
}
public function testAuthUriHttpsInferred() {
@@ -57,7 +78,12 @@ public function testAuthUriHttpsInferred() {
// Note on the line above, no scheme is passed in - we must assume https.
$token = self::createMock(Token::class);
- $sut = new AuthUri($token, "/", $baseUri);
+ $sut = new AuthUri(
+ $token,
+ "example-app-id",
+ "/",
+ $baseUri);
+
self::assertEquals(
"https",
$sut->getScheme()
@@ -79,7 +105,12 @@ public function testQueryString() {
->willReturn($iv);
$returnPath = "/examplePage";
- $sut = new AuthUri($token, $returnPath, $baseUri);
+ $sut = new AuthUri(
+ $token,
+ "example-app-id",
+ $returnPath,
+ $baseUri
+ );
parse_str($sut->getQuery(), $queryParts);
self::assertEquals(
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 5d87e7f..c603dd1 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -16,12 +16,20 @@
class AuthenticatorTest extends TestCase {
public function testConstructWithDefaultSessionNotStarted() {
self::expectException(SessionNotStartedException::class);
- new Authenticator("test-key","/");
+ new Authenticator(
+ "example-app-id",
+ "test-key",
+ "/"
+ );
}
public function testConstructWithDefaultSession() {
$_SESSION = [];
- new Authenticator("test-key", "/");
+ new Authenticator(
+ "example-app-id",
+ "test-key",
+ "/"
+ );
self::assertArrayHasKey(
Authenticator::SESSION_KEY,
$_SESSION
@@ -31,6 +39,7 @@ public function testConstructWithDefaultSession() {
public function testIsLoggedInFalseByDefault() {
$_SESSION = [];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/"
);
@@ -49,8 +58,9 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
- "/",
+ "/"
);
self::assertTrue($sut->isLoggedIn());
}
@@ -62,8 +72,9 @@ public function testLogoutClearsSession() {
];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
- "/",
+ "/"
);
$sut->logout();
self::assertEmpty($_SESSION);
@@ -76,13 +87,14 @@ public function testLoginRedirects() {
$redirectHandler->expects(self::once())
->method("redirect")
->with(self::callback(fn(UriInterface $uri) =>
- $uri->getHost() === AuthUri::DEFAULT_BASE_URI
+ $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
));
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/",
- AuthUri::DEFAULT_BASE_URI,
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -102,6 +114,7 @@ public function testLoginRedirectsLocalhost() {
));
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/",
"http://localhost:8081",
@@ -117,6 +130,7 @@ public function testLoginRedirectsWithCorrectQueryString() {
$key = uniqid("key-");
$currentPath = uniqid("/path/");
+ $id = "example-app-id";
$cipher = "example-cipher";
$ivString = "example-iv";
@@ -131,6 +145,7 @@ public function testLoginRedirectsWithCorrectQueryString() {
->willReturn($iv);
$expectedQueryParts = [
+ AuthUri::QUERY_STRING_ID => $id,
AuthUri::QUERY_STRING_CIPHER => $cipher,
AuthUri::QUERY_STRING_INIT_VECTOR => $ivString,
AuthUri::QUERY_STRING_CURRENT_PATH => $currentPath,
@@ -145,9 +160,10 @@ public function testLoginRedirectsWithCorrectQueryString() {
));
$sut = new Authenticator(
+ $id,
$key,
$currentPath,
- AuthUri::DEFAULT_BASE_URI,
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -165,9 +181,10 @@ public function testLoginDoesNothingWhenAlreadyLoggedIn() {
->method("redirect");
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/",
- AuthUri::DEFAULT_BASE_URI,
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -178,6 +195,7 @@ public function testLoginDoesNothingWhenAlreadyLoggedIn() {
public function testGetUuidThrowsExceptionWhenNotLoggedIn() {
$_SESSION = [];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/"
);
@@ -199,6 +217,7 @@ public function testGetUuid() {
Authenticator::SESSION_KEY => $sessionData,
];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/"
);
@@ -208,6 +227,7 @@ public function testGetUuid() {
public function testGetEmailThrowsExceptionWhenNotLoggedIn() {
$_SESSION = [];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/"
);
@@ -229,6 +249,7 @@ public function testGetEmail() {
Authenticator::SESSION_KEY => $sessionData,
];
$sut = new Authenticator(
+ "example-app-id",
"test-key",
"/"
);
@@ -243,6 +264,7 @@ public function testCompleteAuthNotLoggedIn() {
$_SESSION = [];
self::expectException(NotLoggedInException::class);
new Authenticator(
+ "example-app-id",
"test-key",
$currentUri
);
@@ -275,9 +297,10 @@ public function testCompleteAuth() {
Authenticator::SESSION_KEY => $sessionData,
];
new Authenticator(
+ "example-app-id",
"test-key",
$currentUri,
- AuthUri::DEFAULT_BASE_URI,
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -302,9 +325,10 @@ public function testCompleteAuthNotAffectedByQueryString() {
$_SESSION = [];
new Authenticator(
+ "example-app-id",
"test-key",
"/example-path?filter=something",
- AuthUri::DEFAULT_BASE_URI,
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
From 3a0a3cf1ea487ffe2c6a19bf5455aa05c63f09ef Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 18:30:20 +0000
Subject: [PATCH 02/20] Add missing ID to example
---
README.md | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/README.md b/README.md
index 925246d..7683900 100644
--- a/README.md
+++ b/README.md
@@ -15,15 +15,17 @@ With the following PHP code below, you can display a log in button that, when cl
use Authwave\Authenticator;
require __DIR__ . "/vendor/autoload.php";
-// This constant can be loaded from your application's configuration
-// or environment variables. They are supplied by the remote Authwave provider.
+// These constants can be loaded from your application's configuration
+// or environment variables. They are created in the remote Authwave provider.
+define("CLIENT_ID", "my-secure-application");
define("CLIENT_KEY", "1234567890abcdef");
// Construct the Authenticator class as soon as possible, as this handles the
// Authentication steps passed via the query string from the remote provider.
$auth = new Authenticator(
- CLIENT_KEY, // See above
- $_SERVER["REQUEST_URI"]
+ CLIENT_ID,
+ CLIENT_KEY,
+ $_SERVER["REQUEST_URI"]
);
// Handle authentication login/logout action via the querystring:
@@ -32,24 +34,24 @@ if(isset($_GET["login"])) {
// remote provider. The remote provider will in turn redirect the user agent
// back to the return URI (set as 3rd parameter of Authenticator's constructor),
// at which point the user will be considered authenticated.
- $auth->login();
+ $auth->login();
}
elseif(isset($_GET["logout"])) {
- $auth->logout();
+ $auth->logout();
}
// Authentication is handled by Authwave, so you can trust "isLoggedIn"
// as a mechanism for protecting your sensitive information.
if($auth->isLoggedIn()) {
- echo <<You are logged in as {$auth->getEmail()}
- Log out
- HTML;
+ echo <<You are logged in as {$auth->getEmail()}
+ Log out
+ HTML;
}
else {
- echo <<You are not logged in!
- Log in
- HTML;
+ echo <<You are not logged in!
+ Log in
+ HTML;
}
```
\ No newline at end of file
From 5a66aa66d9028100c34eb9d79a24f9afb755aff4 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 18:32:20 +0000
Subject: [PATCH 03/20] Implement remote logout for #7
---
src/Authenticator.php | 6 ++++++
src/ProviderUri/LogoutUri.php | 12 ++++++++++++
test/phpunit/AuthenticatorTest.php | 7 ++++++-
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 src/ProviderUri/LogoutUri.php
diff --git a/src/Authenticator.php b/src/Authenticator.php
index ce5e71c..bfaeb69 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -3,6 +3,7 @@
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LogoutUri;
use Gt\Http\Uri;
use Gt\Session\SessionContainer;
use Psr\Http\Message\UriInterface;
@@ -79,6 +80,7 @@ public function login(Token $token = null):void {
public function logout():void {
// TODO: Should the logout redirect the user agent to the redirectPath?
$this->session->remove(self::SESSION_KEY);
+ $this->redirectHandler->redirect($this->getLogoutUri());
}
public function getUuid():string {
@@ -109,6 +111,10 @@ public function getAdminUri(
);
}
+ public function getLogoutUri():UriInterface {
+ return new LogoutUri($this->authwaveHost);
+ }
+
private function completeAuth():void {
$responseCipher = $this->getResponseCipher();
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
new file mode 100644
index 0000000..debff7a
--- /dev/null
+++ b/src/ProviderUri/LogoutUri.php
@@ -0,0 +1,12 @@
+normaliseBaseUri($baseRemoteUri);
+ parent::__construct($baseRemoteUri);
+ $this->path = self::PATH_LOGOUT;
+ }
+}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index d20ad70..d1e4a35 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -72,10 +72,15 @@ public function testLogoutClearsSession() {
Authenticator::SESSION_KEY => $sessionData
];
+ $redirectHandler = self::createMock(RedirectHandler::class);
+
$sut = new Authenticator(
"example-app-id",
"test-key",
- "/"
+ "/",
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
+ null,
+ $redirectHandler
);
$sut->logout();
self::assertEmpty($_SESSION);
From 5f537a4914f48a225c0f93c6049375a0759a3e2d Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 18:35:55 +0000
Subject: [PATCH 04/20] Add assertion that correct logout URI is redirected
Closes #7
---
test/phpunit/AuthenticatorTest.php | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index d1e4a35..e0a6f19 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -6,6 +6,7 @@
use Authwave\NotLoggedInException;
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LogoutUri;
use Authwave\RedirectHandler;
use Authwave\SessionData;
use Authwave\SessionNotStartedException;
@@ -73,6 +74,12 @@ public function testLogoutClearsSession() {
];
$redirectHandler = self::createMock(RedirectHandler::class);
+ $redirectHandler->expects(self::once())
+ ->method("redirect")
+ ->with(self::callback(fn(UriInterface $uri) =>
+ $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
+ && $uri->getPath() === LogoutUri::PATH_LOGOUT
+ ));
$sut = new Authenticator(
"example-app-id",
From ca024155f696d6ed760d34e6df6504aecfd9f130 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 18:42:26 +0000
Subject: [PATCH 05/20] Log out via remote provider (#9)
* Implement remote logout for #7
* Add assertion that correct logout URI is redirected
Closes #7
---
src/Authenticator.php | 6 ++++++
src/ProviderUri/LogoutUri.php | 12 ++++++++++++
test/phpunit/AuthenticatorTest.php | 14 +++++++++++++-
3 files changed, 31 insertions(+), 1 deletion(-)
create mode 100644 src/ProviderUri/LogoutUri.php
diff --git a/src/Authenticator.php b/src/Authenticator.php
index ce5e71c..bfaeb69 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -3,6 +3,7 @@
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LogoutUri;
use Gt\Http\Uri;
use Gt\Session\SessionContainer;
use Psr\Http\Message\UriInterface;
@@ -79,6 +80,7 @@ public function login(Token $token = null):void {
public function logout():void {
// TODO: Should the logout redirect the user agent to the redirectPath?
$this->session->remove(self::SESSION_KEY);
+ $this->redirectHandler->redirect($this->getLogoutUri());
}
public function getUuid():string {
@@ -109,6 +111,10 @@ public function getAdminUri(
);
}
+ public function getLogoutUri():UriInterface {
+ return new LogoutUri($this->authwaveHost);
+ }
+
private function completeAuth():void {
$responseCipher = $this->getResponseCipher();
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
new file mode 100644
index 0000000..debff7a
--- /dev/null
+++ b/src/ProviderUri/LogoutUri.php
@@ -0,0 +1,12 @@
+normaliseBaseUri($baseRemoteUri);
+ parent::__construct($baseRemoteUri);
+ $this->path = self::PATH_LOGOUT;
+ }
+}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index d20ad70..e0a6f19 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -6,6 +6,7 @@
use Authwave\NotLoggedInException;
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LogoutUri;
use Authwave\RedirectHandler;
use Authwave\SessionData;
use Authwave\SessionNotStartedException;
@@ -72,10 +73,21 @@ public function testLogoutClearsSession() {
Authenticator::SESSION_KEY => $sessionData
];
+ $redirectHandler = self::createMock(RedirectHandler::class);
+ $redirectHandler->expects(self::once())
+ ->method("redirect")
+ ->with(self::callback(fn(UriInterface $uri) =>
+ $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
+ && $uri->getPath() === LogoutUri::PATH_LOGOUT
+ ));
+
$sut = new Authenticator(
"example-app-id",
"test-key",
- "/"
+ "/",
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
+ null,
+ $redirectHandler
);
$sut->logout();
self::assertEmpty($_SESSION);
From 4405e16501a2b666de774d69564c62edc323ae42 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 19:08:37 +0000
Subject: [PATCH 06/20] Test that returnTo parameter is passed
---
src/ProviderUri/LogoutUri.php | 8 +++++++-
test/phpunit/AuthenticatorTest.php | 3 ++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
index debff7a..806dd52 100644
--- a/src/ProviderUri/LogoutUri.php
+++ b/src/ProviderUri/LogoutUri.php
@@ -4,9 +4,15 @@
class LogoutUri extends AbstractProviderUri {
const PATH_LOGOUT = "/logout";
- public function __construct(string $baseRemoteUri) {
+ public function __construct(
+ string $baseRemoteUri,
+ string $returnToUri = "/"
+ ) {
$baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
parent::__construct($baseRemoteUri);
$this->path = self::PATH_LOGOUT;
+ $this->query = http_build_query([
+ "returnTo" => $returnToUri,
+ ]);
}
}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index e0a6f19..90fbcd1 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -67,7 +67,7 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
self::assertTrue($sut->isLoggedIn());
}
- public function testLogoutClearsSession() {
+ public function testLogoutClearsSessionAndRedirects() {
$sessionData = self::createMock(SessionData::class);
$_SESSION = [
Authenticator::SESSION_KEY => $sessionData
@@ -79,6 +79,7 @@ public function testLogoutClearsSession() {
->with(self::callback(fn(UriInterface $uri) =>
$uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
&& $uri->getPath() === LogoutUri::PATH_LOGOUT
+ && $uri->getQuery() === "returnTo=" . urlencode("/")
));
$sut = new Authenticator(
From 88ccea0fc1cf1cedaba45851ba5c674465442f57 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 18 Mar 2020 19:13:00 +0000
Subject: [PATCH 07/20] Test that current path is used for logout redirection
---
src/Authenticator.php | 8 ++++++--
test/phpunit/AuthenticatorTest.php | 25 +++++++++++++++++++++----
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index bfaeb69..b6b09af 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -111,8 +111,12 @@ public function getAdminUri(
);
}
- public function getLogoutUri():UriInterface {
- return new LogoutUri($this->authwaveHost);
+ public function getLogoutUri(string $returnToPath = null):UriInterface {
+ if(is_null($returnToPath)) {
+ $returnToPath = $this->currentUriPath;
+ }
+
+ return new LogoutUri($this->authwaveHost, $returnToPath);
}
private function completeAuth():void {
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 90fbcd1..572c6fb 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -67,31 +67,48 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
self::assertTrue($sut->isLoggedIn());
}
- public function testLogoutClearsSessionAndRedirects() {
+ public function testLogoutClearsSession() {
$sessionData = self::createMock(SessionData::class);
$_SESSION = [
Authenticator::SESSION_KEY => $sessionData
];
+ $redirectHandler = self::createMock(RedirectHandler::class);
+
+ $sut = new Authenticator(
+ "example-app-id",
+ "test-key",
+ "/",
+ AuthUri::DEFAULT_BASE_REMOTE_URI,
+ null,
+ $redirectHandler
+ );
+ $sut->logout();
+ self::assertEmpty($_SESSION);
+ }
+
+ public function testLogoutRedirectsToCurrentPath() {
+ $_SESSION = [];
+ $currentPath = "/current/example/path";
+
$redirectHandler = self::createMock(RedirectHandler::class);
$redirectHandler->expects(self::once())
->method("redirect")
->with(self::callback(fn(UriInterface $uri) =>
$uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
&& $uri->getPath() === LogoutUri::PATH_LOGOUT
- && $uri->getQuery() === "returnTo=" . urlencode("/")
+ && $uri->getQuery() === "returnTo=" . urlencode($currentPath)
));
$sut = new Authenticator(
"example-app-id",
"test-key",
- "/",
+ $currentPath,
AuthUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
$sut->logout();
- self::assertEmpty($_SESSION);
}
public function testLoginRedirects() {
From 8e51531fa50f8a153360917587704aaed838464d Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Thu, 19 Mar 2020 17:24:25 +0000
Subject: [PATCH 08/20] Remove unneeded AppID
---
README.md | 6 ++----
src/Authenticator.php | 4 ----
src/ProviderUri/AuthUri.php | 3 ---
test/phpunit/AuthenticatorTest.php | 21 -------------------
.../ProviderUri/AbstractProviderUriTest.php | 5 -----
test/phpunit/ProviderUri/AuthUriTest.php | 1 -
6 files changed, 2 insertions(+), 38 deletions(-)
diff --git a/README.md b/README.md
index 7683900..539097a 100644
--- a/README.md
+++ b/README.md
@@ -15,15 +15,13 @@ With the following PHP code below, you can display a log in button that, when cl
use Authwave\Authenticator;
require __DIR__ . "/vendor/autoload.php";
-// These constants can be loaded from your application's configuration
-// or environment variables. They are created in the remote Authwave provider.
-define("CLIENT_ID", "my-secure-application");
+// This constant can be loaded from your application's configuration
+// or environment variables. It is created in the remote Authwave provider.
define("CLIENT_KEY", "1234567890abcdef");
// Construct the Authenticator class as soon as possible, as this handles the
// Authentication steps passed via the query string from the remote provider.
$auth = new Authenticator(
- CLIENT_ID,
CLIENT_KEY,
$_SERVER["REQUEST_URI"]
);
diff --git a/src/Authenticator.php b/src/Authenticator.php
index b6b09af..94af684 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -18,10 +18,8 @@ class Authenticator {
private SessionContainer $session;
private SessionData $sessionData;
private RedirectHandler $redirectHandler;
- private string $clientId;
public function __construct(
- string $clientId,
string $clientKey,
string $currentUriPath,
string $authwaveHost = "login.authwave.com",
@@ -38,7 +36,6 @@ public function __construct(
$session->set(self::SESSION_KEY, new SessionData());
}
- $this->clientId = $clientId;
$this->clientKey = $clientKey;
$this->currentUriPath = $currentUriPath;
$this->authwaveHost = $authwaveHost;
@@ -96,7 +93,6 @@ public function getEmail():string {
public function getAuthUri(Token $token):AuthUri {
return new AuthUri(
$token,
- $this->clientId,
$this->currentUriPath,
$this->authwaveHost
);
diff --git a/src/ProviderUri/AuthUri.php b/src/ProviderUri/AuthUri.php
index e803e3e..dca18c5 100644
--- a/src/ProviderUri/AuthUri.php
+++ b/src/ProviderUri/AuthUri.php
@@ -5,7 +5,6 @@
use Gt\Http\Uri;
class AuthUri extends AbstractProviderUri {
- const QUERY_STRING_ID = "id";
const QUERY_STRING_CIPHER = "cipher";
const QUERY_STRING_INIT_VECTOR = "iv";
const QUERY_STRING_CURRENT_PATH = "path";
@@ -21,7 +20,6 @@ class AuthUri extends AbstractProviderUri {
*/
public function __construct(
Token $token,
- string $clientId,
string $currentPath = "/",
string $baseRemoteUri = self::DEFAULT_BASE_REMOTE_URI
) {
@@ -29,7 +27,6 @@ public function __construct(
parent::__construct($baseRemoteUri);
$this->query = http_build_query([
- self::QUERY_STRING_ID => $clientId,
self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher(),
self::QUERY_STRING_INIT_VECTOR => (string)$token->getIv(),
self::QUERY_STRING_CURRENT_PATH => $currentPath,
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 572c6fb..7ceab98 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -19,7 +19,6 @@ class AuthenticatorTest extends TestCase {
public function testConstructWithDefaultSessionNotStarted() {
self::expectException(SessionNotStartedException::class);
new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -28,7 +27,6 @@ public function testConstructWithDefaultSessionNotStarted() {
public function testConstructWithDefaultSession() {
$_SESSION = [];
new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -41,7 +39,6 @@ public function testConstructWithDefaultSession() {
public function testIsLoggedInFalseByDefault() {
$_SESSION = [];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -60,7 +57,6 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -76,7 +72,6 @@ public function testLogoutClearsSession() {
$redirectHandler = self::createMock(RedirectHandler::class);
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/",
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -101,7 +96,6 @@ public function testLogoutRedirectsToCurrentPath() {
));
$sut = new Authenticator(
- "example-app-id",
"test-key",
$currentPath,
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -122,7 +116,6 @@ public function testLoginRedirects() {
));
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/",
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -145,7 +138,6 @@ public function testLoginRedirectsLocalhost() {
));
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/",
"http://localhost:8081",
@@ -161,7 +153,6 @@ public function testLoginRedirectsWithCorrectQueryString() {
$key = uniqid("key-");
$currentPath = uniqid("/path/");
- $id = "example-app-id";
$cipher = "example-cipher";
$ivString = "example-iv";
@@ -176,7 +167,6 @@ public function testLoginRedirectsWithCorrectQueryString() {
->willReturn($iv);
$expectedQueryParts = [
- AuthUri::QUERY_STRING_ID => $id,
AuthUri::QUERY_STRING_CIPHER => $cipher,
AuthUri::QUERY_STRING_INIT_VECTOR => $ivString,
AuthUri::QUERY_STRING_CURRENT_PATH => $currentPath,
@@ -191,7 +181,6 @@ public function testLoginRedirectsWithCorrectQueryString() {
));
$sut = new Authenticator(
- $id,
$key,
$currentPath,
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -212,7 +201,6 @@ public function testLoginDoesNothingWhenAlreadyLoggedIn() {
->method("redirect");
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/",
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -226,7 +214,6 @@ public function testLoginDoesNothingWhenAlreadyLoggedIn() {
public function testGetUuidThrowsExceptionWhenNotLoggedIn() {
$_SESSION = [];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -248,7 +235,6 @@ public function testGetUuid() {
Authenticator::SESSION_KEY => $sessionData,
];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -258,7 +244,6 @@ public function testGetUuid() {
public function testGetEmailThrowsExceptionWhenNotLoggedIn() {
$_SESSION = [];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -280,7 +265,6 @@ public function testGetEmail() {
Authenticator::SESSION_KEY => $sessionData,
];
$sut = new Authenticator(
- "example-app-id",
"test-key",
"/"
);
@@ -295,7 +279,6 @@ public function testCompleteAuthNotLoggedIn() {
$_SESSION = [];
self::expectException(NotLoggedInException::class);
new Authenticator(
- "example-app-id",
"test-key",
$currentUri
);
@@ -328,7 +311,6 @@ public function testCompleteAuth() {
Authenticator::SESSION_KEY => $sessionData,
];
new Authenticator(
- "example-app-id",
"test-key",
$currentUri,
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -356,7 +338,6 @@ public function testCompleteAuthNotAffectedByQueryString() {
$_SESSION = [];
new Authenticator(
- "example-app-id",
"test-key",
"/example-path?filter=something",
AuthUri::DEFAULT_BASE_REMOTE_URI,
@@ -368,7 +349,6 @@ public function testCompleteAuthNotAffectedByQueryString() {
public function testGetAdminUri() {
$_SESSION = [];
$auth = new Authenticator(
- "example-app-id",
"test-key",
"/example-path",
AuthUri::DEFAULT_BASE_REMOTE_URI
@@ -383,7 +363,6 @@ public function testGetAdminUri() {
public function testGetAdminUriCustom() {
$_SESSION = [];
$auth = new Authenticator(
- "example-app-id",
"test-key",
"/example-path",
AuthUri::DEFAULT_BASE_REMOTE_URI
diff --git a/test/phpunit/ProviderUri/AbstractProviderUriTest.php b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
index 19a656c..28d2287 100644
--- a/test/phpunit/ProviderUri/AbstractProviderUriTest.php
+++ b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
@@ -17,7 +17,6 @@ public function testAuthUriHttps() {
$sut = new AuthUri(
$token,
- "example-app-id",
"",
$baseUri
);
@@ -33,7 +32,6 @@ public function testGetAuthUriHostnameLocalhostHttpsByDefault() {
$token = self::createMock(Token::class);
$sut = new AuthUri(
$token,
- "example-app-id",
"/",
"localhost"
);
@@ -49,7 +47,6 @@ public function testGetAuthUriHostnameLocalhostHttpAllowed() {
$token = self::createMock(Token::class);
$sut = new AuthUri(
$token,
- "example-app-id",
"/",
"http://localhost"
);
@@ -65,7 +62,6 @@ public function testGetAuthUriHostnameNotLocalhostHttpNotAllowed() {
self::expectException(InsecureProtocolException::class);
new AuthUri(
$token,
- "example-app-id",
"/",
"http://localhost.com"
);
@@ -80,7 +76,6 @@ public function testAuthUriHttpsInferred() {
$sut = new AuthUri(
$token,
- "example-app-id",
"/",
$baseUri);
diff --git a/test/phpunit/ProviderUri/AuthUriTest.php b/test/phpunit/ProviderUri/AuthUriTest.php
index 7db14bd..deac72e 100644
--- a/test/phpunit/ProviderUri/AuthUriTest.php
+++ b/test/phpunit/ProviderUri/AuthUriTest.php
@@ -25,7 +25,6 @@ public function testQueryString() {
$returnPath = "/examplePage";
$sut = new AuthUri(
$token,
- "example-app-id",
$returnPath,
$baseUri
);
From d9a28400c66f7e7c80c974358aae57db5d574573 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 25 Mar 2020 22:06:29 +0000
Subject: [PATCH 09/20] Use standard ports where not specified
---
src/ProviderUri/AbstractProviderUri.php | 2 +-
.../ProviderUri/AbstractProviderUriTest.php | 24 +++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/ProviderUri/AbstractProviderUri.php b/src/ProviderUri/AbstractProviderUri.php
index c7dac64..35f0dda 100644
--- a/src/ProviderUri/AbstractProviderUri.php
+++ b/src/ProviderUri/AbstractProviderUri.php
@@ -13,7 +13,7 @@ protected function normaliseBaseUri(string $baseUri):Uri {
$host = parse_url($baseUri, PHP_URL_HOST)
?? parse_url($baseUri, PHP_URL_PATH);
$port = parse_url($baseUri, PHP_URL_PORT)
- ?? 80;
+ ?? null;
$uri = (new Uri())
->withScheme($scheme)
diff --git a/test/phpunit/ProviderUri/AbstractProviderUriTest.php b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
index 28d2287..88ce4c0 100644
--- a/test/phpunit/ProviderUri/AbstractProviderUriTest.php
+++ b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
@@ -24,6 +24,30 @@ public function testAuthUriHttps() {
"https",
$sut->getScheme()
);
+ self::assertNull(
+ $sut->getPort()
+ );
+ }
+
+ public function testAuthUriWithNonStandardPort() {
+ $baseUri = self::createMock(UriInterface::class);
+ $baseUri->method("__toString")
+ ->willReturn("http://localhost:8081");
+ $token = self::createMock(Token::class);
+
+ $sut = new AuthUri(
+ $token,
+ "",
+ $baseUri
+ );
+ self::assertEquals(
+ "http",
+ $sut->getScheme()
+ );
+ self::assertEquals(
+ 8081,
+ $sut->getPort()
+ );
}
// All AuthUris MUST be served over HTTPS, with the one exception of localhost.
From 0dcae0979e796a4f76b85fd7d62cd59b145ef586 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sun, 29 Mar 2020 23:50:07 +0100
Subject: [PATCH 10/20] Native unserialisation rather than relying on JSON
---
composer.json | 1 -
src/Token.php | 13 ++++---------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/composer.json b/composer.json
index d21a9c8..b360806 100644
--- a/composer.json
+++ b/composer.json
@@ -5,7 +5,6 @@
"require": {
"php": ">=7.4",
"ext-openssl": "*",
- "ext-json": "*",
"phpgt/http": "1.*",
"phpgt/session": ">=1.1"
},
diff --git a/src/Token.php b/src/Token.php
index 9fe3c62..56abd95 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -60,15 +60,10 @@ public function decryptResponseCipher(string $cipher):UserData {
throw new ResponseCipherDecryptionException();
}
- try {
- $obj = json_decode(
- $decrypted,
- false,
- 2,
- JSON_THROW_ON_ERROR
- );
- }
- catch(JsonException $exception) {
+ $obj = unserialize(
+ $decrypted
+ );
+ if($obj === false) {
throw new InvalidUserDataSerializationException();
}
From 5f56e2656f1fff8c62ae5755549fceb2b0b20de0 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Wed, 1 Apr 2020 17:37:54 +0100
Subject: [PATCH 11/20] Simplify decryption data
---
src/Authenticator.php | 2 +-
src/Token.php | 15 +++++----------
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 94af684..4bb5c37 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -109,7 +109,7 @@ public function getAdminUri(
public function getLogoutUri(string $returnToPath = null):UriInterface {
if(is_null($returnToPath)) {
- $returnToPath = $this->currentUriPath;
+ $returnToPath = (new Uri($this->currentUriPath))->getPath();
}
return new LogoutUri($this->authwaveHost, $returnToPath);
diff --git a/src/Token.php b/src/Token.php
index 56abd95..2c6a655 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -1,8 +1,6 @@
key,
- $this->secretIv->getBytes(),
- ]),
+ $this->key,
0,
- $this->iv->getBytes()
+ $this->secretIv->getBytes()
);
if(!$decrypted) {
throw new ResponseCipherDecryptionException();
}
- $obj = unserialize(
+ $data = unserialize(
$decrypted
);
- if($obj === false) {
+ if($data === false) {
throw new InvalidUserDataSerializationException();
}
- return new UserData($obj->uuid, $obj->email);
+ return new UserData($data["uuid"], $data["email"]);
}
}
\ No newline at end of file
From eb3745c53d92549b08c7135c7ee209d6a5982101 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Mon, 13 Apr 2020 14:31:39 +0100
Subject: [PATCH 12/20] Use serialised stdClass object to represent user data
---
src/Authenticator.php | 6 +++++-
src/ProviderUri/AdminUri.php | 2 +-
src/Token.php | 4 ++--
test/phpunit/AuthenticatorTest.php | 2 +-
test/phpunit/ProviderUri/AdminUriTest.php | 4 ++--
test/phpunit/TokenTest.php | 21 ++++++++++-----------
6 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 4bb5c37..c029f99 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -80,6 +80,10 @@ public function logout():void {
$this->redirectHandler->redirect($this->getLogoutUri());
}
+ public function adminLogin():void {
+// TODO: Implement!
+ }
+
public function getUuid():string {
$userData = $this->sessionData->getUserData();
return $userData->getUuid();
@@ -99,7 +103,7 @@ public function getAuthUri(Token $token):AuthUri {
}
public function getAdminUri(
- string $path = AdminUri::PATH_ACCOUNT
+ string $path = AdminUri::PATH_ADMIN
):UriInterface {
return new AdminUri(
$this->authwaveHost,
diff --git a/src/ProviderUri/AdminUri.php b/src/ProviderUri/AdminUri.php
index 13a725a..31845ea 100644
--- a/src/ProviderUri/AdminUri.php
+++ b/src/ProviderUri/AdminUri.php
@@ -2,7 +2,7 @@
namespace Authwave\ProviderUri;
class AdminUri extends AbstractProviderUri {
- const PATH_ACCOUNT = "/account";
+ const PATH_ADMIN = "/admin";
const PATH_SETTINGS = "/settings";
public function __construct(
diff --git a/src/Token.php b/src/Token.php
index 2c6a655..a45de09 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -55,13 +55,13 @@ public function decryptResponseCipher(string $cipher):UserData {
throw new ResponseCipherDecryptionException();
}
- $data = unserialize(
+ $data = @unserialize(
$decrypted
);
if($data === false) {
throw new InvalidUserDataSerializationException();
}
- return new UserData($data["uuid"], $data["email"]);
+ return new UserData($data->{"uuid"}, $data->{"email"});
}
}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 7ceab98..8c7f68f 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -355,7 +355,7 @@ public function testGetAdminUri() {
);
$sut = $auth->getAdminUri();
self::assertEquals(
- AdminUri::PATH_ACCOUNT,
+ AdminUri::PATH_ADMIN,
$sut->getPath()
);
}
diff --git a/test/phpunit/ProviderUri/AdminUriTest.php b/test/phpunit/ProviderUri/AdminUriTest.php
index fe9b3f1..8de8623 100644
--- a/test/phpunit/ProviderUri/AdminUriTest.php
+++ b/test/phpunit/ProviderUri/AdminUriTest.php
@@ -8,10 +8,10 @@ class AdminUriTest extends TestCase {
public function testPathAccount() {
$sut = new AdminUri(
"example.com",
- AdminUri::PATH_ACCOUNT
+ AdminUri::PATH_ADMIN
);
self::assertEquals(
- AdminUri::PATH_ACCOUNT,
+ AdminUri::PATH_ADMIN,
$sut->getPath()
);
}
diff --git a/test/phpunit/TokenTest.php b/test/phpunit/TokenTest.php
index a77a2e0..a5c0849 100644
--- a/test/phpunit/TokenTest.php
+++ b/test/phpunit/TokenTest.php
@@ -65,7 +65,8 @@ public function testDecryptResponseCipherBadJson() {
}
public function testDecryptResponseCipher() {
- $key = uniqid("test-key-");
+ $clientKey = uniqid("test-key-");
+// SecretIv is stored in the client application's session only.
$secretIv = self::createMock(InitVector::class);
$secretIv->method("getBytes")
->willReturn(str_repeat("0", 16));
@@ -75,22 +76,20 @@ public function testDecryptResponseCipher() {
$uuid = "aabb-ccdd-eeff";
$email = "user@example.com";
- $json = << $uuid,
+ "email" => $email,
+ ]);
$cipher = openssl_encrypt(
- $json,
+ $serialized,
Token::ENCRYPTION_METHOD,
- implode("|", [$key, $secretIv->getBytes()]),
+ $clientKey,
0,
- $iv->getBytes()
+ $secretIv->getBytes()
);
$cipher = base64_encode($cipher);
- $sut = new Token($key, $secretIv, $iv);
+ $sut = new Token($clientKey, $secretIv, $iv);
$userData = $sut->decryptResponseCipher($cipher);
self::assertInstanceOf(UserData::class, $userData);
self::assertEquals($uuid, $userData->getUuid());
From a7148865dde1a6fbd19d7f32066647c9de62f95d Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Tue, 28 Apr 2020 22:29:59 +0100
Subject: [PATCH 13/20] Stub profile URI
---
src/ProviderUri/LogoutUri.php | 18 ------------------
src/ProviderUri/ProfileUri.php | 6 ++++++
test/phpunit/AuthenticatorTest.php | 23 -----------------------
3 files changed, 6 insertions(+), 41 deletions(-)
delete mode 100644 src/ProviderUri/LogoutUri.php
create mode 100644 src/ProviderUri/ProfileUri.php
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
deleted file mode 100644
index 806dd52..0000000
--- a/src/ProviderUri/LogoutUri.php
+++ /dev/null
@@ -1,18 +0,0 @@
-normaliseBaseUri($baseRemoteUri);
- parent::__construct($baseRemoteUri);
- $this->path = self::PATH_LOGOUT;
- $this->query = http_build_query([
- "returnTo" => $returnToUri,
- ]);
- }
-}
\ No newline at end of file
diff --git a/src/ProviderUri/ProfileUri.php b/src/ProviderUri/ProfileUri.php
new file mode 100644
index 0000000..da09f32
--- /dev/null
+++ b/src/ProviderUri/ProfileUri.php
@@ -0,0 +1,6 @@
+expects(self::once())
- ->method("redirect")
- ->with(self::callback(fn(UriInterface $uri) =>
- $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
- && $uri->getPath() === LogoutUri::PATH_LOGOUT
- && $uri->getQuery() === "returnTo=" . urlencode($currentPath)
- ));
-
- $sut = new Authenticator(
- "test-key",
- $currentPath,
- AuthUri::DEFAULT_BASE_REMOTE_URI,
- null,
- $redirectHandler
- );
- $sut->logout();
- }
-
public function testLoginRedirects() {
$_SESSION = [];
From 81ecf542c6ae1557ed498b7eba803673446f3e94 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Tue, 28 Apr 2020 22:30:33 +0100
Subject: [PATCH 14/20] Load user's data fields
---
src/Authenticator.php | 47 ++++++++++++++++++++++++++++++++-----------
src/Token.php | 8 +++++++-
src/UserData.php | 12 ++++++++++-
3 files changed, 53 insertions(+), 14 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index c029f99..3149825 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -1,6 +1,7 @@
isLoggedIn()) {
return;
}
@@ -71,17 +77,18 @@ public function login(Token $token = null):void {
$this->sessionData = new SessionData($token);
$this->session->set(self::SESSION_KEY, $this->sessionData);
- $this->redirectHandler->redirect($this->getAuthUri($token));
+ $this->redirectHandler->redirect(
+ $this->getAuthUri($token, $loginType)
+ );
}
public function logout():void {
// TODO: Should the logout redirect the user agent to the redirectPath?
$this->session->remove(self::SESSION_KEY);
- $this->redirectHandler->redirect($this->getLogoutUri());
}
- public function adminLogin():void {
-// TODO: Implement!
+ public function adminLogin(Token $token = null):void {
+ $this->login($token, self::LOGIN_TYPE_ADMIN);
}
public function getUuid():string {
@@ -94,7 +101,22 @@ public function getEmail():string {
return $userData->getEmail();
}
- public function getAuthUri(Token $token):AuthUri {
+ public function getField(string $name):?string {
+ $userData = $this->sessionData->getUserData();
+ return $userData->getField($name);
+ }
+
+ public function getAuthUri(
+ Token $token,
+ string $loginType = self::LOGIN_TYPE_DEFAULT
+ ):AbstractProviderUri {
+ if($loginType === self::LOGIN_TYPE_ADMIN) {
+ return new AdminUri(
+ $this->currentUriPath,
+ $this->authwaveHost
+ );
+ }
+
return new AuthUri(
$token,
$this->currentUriPath,
@@ -111,12 +133,13 @@ public function getAdminUri(
);
}
- public function getLogoutUri(string $returnToPath = null):UriInterface {
- if(is_null($returnToPath)) {
- $returnToPath = (new Uri($this->currentUriPath))->getPath();
- }
-
- return new LogoutUri($this->authwaveHost, $returnToPath);
+ public function getProfileUri(
+ string $path = ProfileUri::PATH_PROFILE
+ ):UriInterface {
+ return new ProfileUri(
+ $this->authwaveHost,
+ $path
+ );
}
private function completeAuth():void {
diff --git a/src/Token.php b/src/Token.php
index a45de09..047561b 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -1,6 +1,8 @@
{"uuid"}, $data->{"email"});
+ return new UserData(
+ $data->{"uuid"},
+ $data->{"email"},
+ $data->{"fields"} ?? new StdClass()
+ );
}
}
\ No newline at end of file
diff --git a/src/UserData.php b/src/UserData.php
index 7f5b0a4..6d741c6 100644
--- a/src/UserData.php
+++ b/src/UserData.php
@@ -4,10 +4,16 @@
class UserData {
private string $uuid;
private string $email;
+ private object $fields;
- public function __construct(string $uuid, string $email) {
+ public function __construct(
+ string $uuid,
+ string $email,
+ object $fields
+ ) {
$this->uuid = $uuid;
$this->email = $email;
+ $this->fields = $fields;
}
public function getUuid():string {
@@ -17,4 +23,8 @@ public function getUuid():string {
public function getEmail():string {
return $this->email;
}
+
+ public function getField(string $name):?string {
+ return $this->fields->{$name} ?? null;
+ }
}
\ No newline at end of file
From d3bea6178a80727cc73569dd5f59734e416c5019 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sun, 10 May 2020 18:01:18 +0100
Subject: [PATCH 15/20] Handle user data fields
---
src/Authenticator.php | 48 ++++++++++++++++++++++--------
src/ProviderUri/LogoutUri.php | 18 -----------
src/ProviderUri/ProfileUri.php | 6 ++++
src/Token.php | 6 +++-
src/UserData.php | 12 +++++++-
test/phpunit/AuthenticatorTest.php | 23 --------------
test/phpunit/TokenTest.php | 3 ++
7 files changed, 60 insertions(+), 56 deletions(-)
delete mode 100644 src/ProviderUri/LogoutUri.php
create mode 100644 src/ProviderUri/ProfileUri.php
diff --git a/src/Authenticator.php b/src/Authenticator.php
index c029f99..1f178d5 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -1,9 +1,9 @@
isLoggedIn()) {
return;
}
@@ -71,17 +76,18 @@ public function login(Token $token = null):void {
$this->sessionData = new SessionData($token);
$this->session->set(self::SESSION_KEY, $this->sessionData);
- $this->redirectHandler->redirect($this->getAuthUri($token));
+ $this->redirectHandler->redirect(
+ $this->getAuthUri($token, $loginType)
+ );
}
public function logout():void {
// TODO: Should the logout redirect the user agent to the redirectPath?
$this->session->remove(self::SESSION_KEY);
- $this->redirectHandler->redirect($this->getLogoutUri());
}
- public function adminLogin():void {
-// TODO: Implement!
+ public function adminLogin(Token $token = null):void {
+ $this->login($token, self::LOGIN_TYPE_ADMIN);
}
public function getUuid():string {
@@ -94,7 +100,22 @@ public function getEmail():string {
return $userData->getEmail();
}
- public function getAuthUri(Token $token):AuthUri {
+ public function getField(string $name):?string {
+ $userData = $this->sessionData->getUserData();
+ return $userData->getField($name);
+ }
+
+ public function getAuthUri(
+ Token $token,
+ string $loginType = self::LOGIN_TYPE_DEFAULT
+ ):AbstractProviderUri {
+ if($loginType === self::LOGIN_TYPE_ADMIN) {
+ return new AdminUri(
+ $this->currentUriPath,
+ $this->authwaveHost
+ );
+ }
+
return new AuthUri(
$token,
$this->currentUriPath,
@@ -111,12 +132,13 @@ public function getAdminUri(
);
}
- public function getLogoutUri(string $returnToPath = null):UriInterface {
- if(is_null($returnToPath)) {
- $returnToPath = (new Uri($this->currentUriPath))->getPath();
- }
-
- return new LogoutUri($this->authwaveHost, $returnToPath);
+ public function getProfileUri(
+ string $path = ProfileUri::PATH_PROFILE
+ ):UriInterface {
+ return new ProfileUri(
+ $this->authwaveHost,
+ $path
+ );
}
private function completeAuth():void {
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
deleted file mode 100644
index 806dd52..0000000
--- a/src/ProviderUri/LogoutUri.php
+++ /dev/null
@@ -1,18 +0,0 @@
-normaliseBaseUri($baseRemoteUri);
- parent::__construct($baseRemoteUri);
- $this->path = self::PATH_LOGOUT;
- $this->query = http_build_query([
- "returnTo" => $returnToUri,
- ]);
- }
-}
\ No newline at end of file
diff --git a/src/ProviderUri/ProfileUri.php b/src/ProviderUri/ProfileUri.php
new file mode 100644
index 0000000..da09f32
--- /dev/null
+++ b/src/ProviderUri/ProfileUri.php
@@ -0,0 +1,6 @@
+{"uuid"}, $data->{"email"});
+ return new UserData(
+ $data->{"uuid"},
+ $data->{"email"},
+ $data->{"fields"}
+ );
}
}
\ No newline at end of file
diff --git a/src/UserData.php b/src/UserData.php
index 7f5b0a4..6d741c6 100644
--- a/src/UserData.php
+++ b/src/UserData.php
@@ -4,10 +4,16 @@
class UserData {
private string $uuid;
private string $email;
+ private object $fields;
- public function __construct(string $uuid, string $email) {
+ public function __construct(
+ string $uuid,
+ string $email,
+ object $fields
+ ) {
$this->uuid = $uuid;
$this->email = $email;
+ $this->fields = $fields;
}
public function getUuid():string {
@@ -17,4 +23,8 @@ public function getUuid():string {
public function getEmail():string {
return $this->email;
}
+
+ public function getField(string $name):?string {
+ return $this->fields->{$name} ?? null;
+ }
}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 8c7f68f..5db819d 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -82,29 +82,6 @@ public function testLogoutClearsSession() {
self::assertEmpty($_SESSION);
}
- public function testLogoutRedirectsToCurrentPath() {
- $_SESSION = [];
- $currentPath = "/current/example/path";
-
- $redirectHandler = self::createMock(RedirectHandler::class);
- $redirectHandler->expects(self::once())
- ->method("redirect")
- ->with(self::callback(fn(UriInterface $uri) =>
- $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
- && $uri->getPath() === LogoutUri::PATH_LOGOUT
- && $uri->getQuery() === "returnTo=" . urlencode($currentPath)
- ));
-
- $sut = new Authenticator(
- "test-key",
- $currentPath,
- AuthUri::DEFAULT_BASE_REMOTE_URI,
- null,
- $redirectHandler
- );
- $sut->logout();
- }
-
public function testLoginRedirects() {
$_SESSION = [];
diff --git a/test/phpunit/TokenTest.php b/test/phpunit/TokenTest.php
index a5c0849..b81e46a 100644
--- a/test/phpunit/TokenTest.php
+++ b/test/phpunit/TokenTest.php
@@ -79,6 +79,9 @@ public function testDecryptResponseCipher() {
$serialized = serialize((object)[
"uuid" => $uuid,
"email" => $email,
+ "fields" => (object)[
+ "example1" => "value1",
+ ]
]);
$cipher = openssl_encrypt(
From 28676c45c049f7439961a359c107028777dbe9a7 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sun, 10 May 2020 18:31:37 +0100
Subject: [PATCH 16/20] WIP work with URI classes
---
src/Authenticator.php | 19 +++++--------------
src/ProviderUri/AdminUri.php | 8 ++------
src/ProviderUri/ProfileUri.php | 8 +++++++-
3 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 1f178d5..3e199c1 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -4,6 +4,7 @@
use Authwave\ProviderUri\AbstractProviderUri;
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\ProfileUri;
use Gt\Http\Uri;
use Gt\Session\SessionContainer;
use Psr\Http\Message\UriInterface;
@@ -123,22 +124,12 @@ public function getAuthUri(
);
}
- public function getAdminUri(
- string $path = AdminUri::PATH_ADMIN
- ):UriInterface {
- return new AdminUri(
- $this->authwaveHost,
- $path
- );
+ public function getAdminUri():UriInterface {
+ return new AdminUri($this->authwaveHost);
}
- public function getProfileUri(
- string $path = ProfileUri::PATH_PROFILE
- ):UriInterface {
- return new ProfileUri(
- $this->authwaveHost,
- $path
- );
+ public function getProfileUri():UriInterface {
+ return new ProfileUri($this->authwaveHost);
}
private function completeAuth():void {
diff --git a/src/ProviderUri/AdminUri.php b/src/ProviderUri/AdminUri.php
index 31845ea..f8b1ae3 100644
--- a/src/ProviderUri/AdminUri.php
+++ b/src/ProviderUri/AdminUri.php
@@ -2,15 +2,11 @@
namespace Authwave\ProviderUri;
class AdminUri extends AbstractProviderUri {
- const PATH_ADMIN = "/admin";
- const PATH_SETTINGS = "/settings";
-
public function __construct(
- string $baseRemoteUri,
- string $path
+ string $baseRemoteUri
) {
$baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
parent::__construct($baseRemoteUri);
- $this->path = $path;
+ $this->path = "/admin";
}
}
\ No newline at end of file
diff --git a/src/ProviderUri/ProfileUri.php b/src/ProviderUri/ProfileUri.php
index da09f32..0be2dde 100644
--- a/src/ProviderUri/ProfileUri.php
+++ b/src/ProviderUri/ProfileUri.php
@@ -2,5 +2,11 @@
namespace Authwave\ProviderUri;
class ProfileUri extends AbstractProviderUri {
-
+ public function __construct(
+ string $baseRemoteUri
+ ) {
+ $baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
+ parent::__construct($baseRemoteUri);
+ $this->path = "/profile";
+ }
}
\ No newline at end of file
From cec4846e69ca4f5ee4721db022a44d81f16cb17c Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sun, 10 May 2020 21:35:07 +0100
Subject: [PATCH 17/20] Remove custom admin uri
---
src/Authenticator.php | 34 +++++++----------------
test/phpunit/AuthenticatorTest.php | 17 +-----------
test/phpunit/ProviderUri/AdminUriTest.php | 27 ++----------------
3 files changed, 13 insertions(+), 65 deletions(-)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 3e199c1..8e227d2 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -38,12 +38,14 @@ public function __construct(
// need to store it to the current session at all?
$session->set(self::SESSION_KEY, new SessionData());
}
+ /** @var SessionData $sessionData*/
+ $sessionData = $session->get(self::SESSION_KEY);
$this->clientKey = $clientKey;
$this->currentUriPath = $currentUriPath;
$this->authwaveHost = $authwaveHost;
$this->session = $session;
- $this->sessionData = $session->get(self::SESSION_KEY);
+ $this->sessionData = $sessionData;
$this->redirectHandler = $redirectHandler ?? new RedirectHandler();
$this->completeAuth();
@@ -62,10 +64,7 @@ public function isLoggedIn():bool {
return isset($userData);
}
- public function login(
- Token $token = null,
- string $loginType = self::LOGIN_TYPE_DEFAULT
- ):void {
+ public function login(Token $token = null):void {
if($this->isLoggedIn()) {
return;
}
@@ -77,18 +76,15 @@ public function login(
$this->sessionData = new SessionData($token);
$this->session->set(self::SESSION_KEY, $this->sessionData);
- $this->redirectHandler->redirect(
- $this->getAuthUri($token, $loginType)
- );
+ $this->redirectHandler->redirect($this->getAuthUri($token));
}
- public function logout():void {
-// TODO: Should the logout redirect the user agent to the redirectPath?
+ public function logout(string $redirectToPath = "/"):void {
$this->session->remove(self::SESSION_KEY);
- }
- public function adminLogin(Token $token = null):void {
- $this->login($token, self::LOGIN_TYPE_ADMIN);
+ $uri = (new Uri())
+ ->withPath($redirectToPath);
+ $this->redirectHandler->redirect($uri);
}
public function getUuid():string {
@@ -106,17 +102,7 @@ public function getField(string $name):?string {
return $userData->getField($name);
}
- public function getAuthUri(
- Token $token,
- string $loginType = self::LOGIN_TYPE_DEFAULT
- ):AbstractProviderUri {
- if($loginType === self::LOGIN_TYPE_ADMIN) {
- return new AdminUri(
- $this->currentUriPath,
- $this->authwaveHost
- );
- }
-
+ public function getAuthUri(Token $token):AbstractProviderUri {
return new AuthUri(
$token,
$this->currentUriPath,
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 5db819d..8114978 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -332,22 +332,7 @@ public function testGetAdminUri() {
);
$sut = $auth->getAdminUri();
self::assertEquals(
- AdminUri::PATH_ADMIN,
- $sut->getPath()
- );
- }
-
- public function testGetAdminUriCustom() {
- $_SESSION = [];
- $auth = new Authenticator(
- "test-key",
- "/example-path",
- AuthUri::DEFAULT_BASE_REMOTE_URI
- );
- $path = "/custom-path";
- $sut = $auth->getAdminUri($path);
- self::assertEquals(
- $path,
+ "/admin",
$sut->getPath()
);
}
diff --git a/test/phpunit/ProviderUri/AdminUriTest.php b/test/phpunit/ProviderUri/AdminUriTest.php
index 8de8623..e2e5db7 100644
--- a/test/phpunit/ProviderUri/AdminUriTest.php
+++ b/test/phpunit/ProviderUri/AdminUriTest.php
@@ -6,33 +6,10 @@
class AdminUriTest extends TestCase {
public function testPathAccount() {
- $sut = new AdminUri(
- "example.com",
- AdminUri::PATH_ADMIN
- );
- self::assertEquals(
- AdminUri::PATH_ADMIN,
- $sut->getPath()
- );
- }
-
- public function testPathSettings() {
- $sut = new AdminUri(
- "example.com",
- AdminUri::PATH_SETTINGS
- );
+ $sut = new AdminUri("example.com");
self::assertEquals(
- AdminUri::PATH_SETTINGS,
+ "/admin",
$sut->getPath()
);
}
-
- public function testPathCustom() {
- $path = "/custom/path";
- $sut = new AdminUri(
- "example.com",
- $path
- );
- self::assertEquals($path, $sut->getPath());
- }
}
\ No newline at end of file
From 817f1f6da59eb4830d67ce656193c73be7518a19 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sat, 16 May 2020 19:01:31 +0100
Subject: [PATCH 18/20] Update provider uri and cipher to allow user session to
be maintained on provider
---
src/Authenticator.php | 44 ++++++++++++++-----
src/ProviderUri/AbstractProviderUri.php | 16 +++++++
src/ProviderUri/{AuthUri.php => LoginUri.php} | 19 ++++----
src/ProviderUri/ProfileUri.php | 6 +++
src/Token.php | 21 ++++++---
test/phpunit/AuthenticatorTest.php | 24 +++++-----
.../ProviderUri/AbstractProviderUriTest.php | 14 +++---
.../{AuthUriTest.php => LoginUriTest.php} | 12 ++---
8 files changed, 103 insertions(+), 53 deletions(-)
rename src/ProviderUri/{AuthUri.php => LoginUri.php} (63%)
rename test/phpunit/ProviderUri/{AuthUriTest.php => LoginUriTest.php} (77%)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 8e227d2..7eb6390 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -3,7 +3,7 @@
use Authwave\ProviderUri\AbstractProviderUri;
use Authwave\ProviderUri\AdminUri;
-use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LoginUri;
use Authwave\ProviderUri\ProfileUri;
use Gt\Http\Uri;
use Gt\Session\SessionContainer;
@@ -76,15 +76,18 @@ public function login(Token $token = null):void {
$this->sessionData = new SessionData($token);
$this->session->set(self::SESSION_KEY, $this->sessionData);
- $this->redirectHandler->redirect($this->getAuthUri($token));
+ $this->redirectHandler->redirect($this->getLoginUri($token));
}
- public function logout(string $redirectToPath = "/"):void {
- $this->session->remove(self::SESSION_KEY);
+ public function logout(Token $token = null):void {
+ if(is_null($token)) {
+ $token = new Token($this->clientKey);
+ }
+
+ $this->sessionData = new SessionData($token);
+ $this->session->set(self::SESSION_KEY, $this->sessionData);
- $uri = (new Uri())
- ->withPath($redirectToPath);
- $this->redirectHandler->redirect($uri);
+ $this->redirectHandler->redirect($this->getLogoutUri($token));
}
public function getUuid():string {
@@ -102,8 +105,16 @@ public function getField(string $name):?string {
return $userData->getField($name);
}
- public function getAuthUri(Token $token):AbstractProviderUri {
- return new AuthUri(
+ public function getLoginUri(Token $token):AbstractProviderUri {
+ return new LoginUri(
+ $token,
+ $this->currentUriPath,
+ $this->authwaveHost
+ );
+ }
+
+ private function getLogoutUri(Token $token):AbstractProviderUri {
+ return new LogoutUri(
$token,
$this->currentUriPath,
$this->authwaveHost
@@ -114,8 +125,17 @@ public function getAdminUri():UriInterface {
return new AdminUri($this->authwaveHost);
}
- public function getProfileUri():UriInterface {
- return new ProfileUri($this->authwaveHost);
+ public function getProfileUri(Token $token = null):UriInterface {
+ if(is_null($token)) {
+ $token = new Token($this->clientKey);
+ }
+
+ return new ProfileUri(
+ $token,
+ $this->getUuid(),
+ $this->currentUriPath,
+ $this->authwaveHost
+ );
}
private function completeAuth():void {
@@ -132,6 +152,8 @@ private function completeAuth():void {
new SessionData($token, $userData)
);
+ setcookie("authwave-trackshift", "test", 0, "/", "localhost");
+
$this->redirectHandler->redirect(
(new Uri($this->currentUriPath))
->withoutQueryValue(self::RESPONSE_QUERY_PARAMETER)
diff --git a/src/ProviderUri/AbstractProviderUri.php b/src/ProviderUri/AbstractProviderUri.php
index 35f0dda..747e795 100644
--- a/src/ProviderUri/AbstractProviderUri.php
+++ b/src/ProviderUri/AbstractProviderUri.php
@@ -2,10 +2,14 @@
namespace Authwave\ProviderUri;
use Authwave\InsecureProtocolException;
+use Authwave\Token;
use Gt\Http\Uri;
abstract class AbstractProviderUri extends Uri {
const DEFAULT_BASE_REMOTE_URI = "login.authwave.com";
+ const QUERY_STRING_CIPHER = "c";
+ const QUERY_STRING_INIT_VECTOR = "i";
+ const QUERY_STRING_CURRENT_PATH = "p";
protected function normaliseBaseUri(string $baseUri):Uri {
$scheme = parse_url($baseUri, PHP_URL_SCHEME)
@@ -27,4 +31,16 @@ protected function normaliseBaseUri(string $baseUri):Uri {
return $uri;
}
+
+ protected function buildQuery(
+ Token $token,
+ string $currentPath,
+ string $data = null
+ ):string {
+ return http_build_query([
+ self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher($data),
+ self::QUERY_STRING_INIT_VECTOR => (string)$token->getIv(),
+ self::QUERY_STRING_CURRENT_PATH => bin2hex($currentPath),
+ ]);
+ }
}
\ No newline at end of file
diff --git a/src/ProviderUri/AuthUri.php b/src/ProviderUri/LoginUri.php
similarity index 63%
rename from src/ProviderUri/AuthUri.php
rename to src/ProviderUri/LoginUri.php
index dca18c5..a24a6ba 100644
--- a/src/ProviderUri/AuthUri.php
+++ b/src/ProviderUri/LoginUri.php
@@ -4,11 +4,13 @@
use Authwave\Token;
use Gt\Http\Uri;
-class AuthUri extends AbstractProviderUri {
- const QUERY_STRING_CIPHER = "cipher";
- const QUERY_STRING_INIT_VECTOR = "iv";
- const QUERY_STRING_CURRENT_PATH = "path";
-
+/**
+ * The AuthUri class represents the Uri used to redirect the user agent to the
+ * Authwave provider in order to initiate authentication. A Token is used to
+ * pass the secret IV to the provider, encrypted with the API key. The secret
+ * IV is only ever stored in the client's session, and is unique to the session.
+ */
+class LoginUri extends AbstractProviderUri {
/**
* @param Token $token This must be the same instance of the Token when
* creating Authenticator for the first time as it is when checking the
@@ -25,11 +27,6 @@ public function __construct(
) {
$baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
parent::__construct($baseRemoteUri);
-
- $this->query = http_build_query([
- self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher(),
- self::QUERY_STRING_INIT_VECTOR => (string)$token->getIv(),
- self::QUERY_STRING_CURRENT_PATH => $currentPath,
- ]);
+ $this->query = $this->buildQuery($token, $currentPath);
}
}
\ No newline at end of file
diff --git a/src/ProviderUri/ProfileUri.php b/src/ProviderUri/ProfileUri.php
index 0be2dde..6ca73f7 100644
--- a/src/ProviderUri/ProfileUri.php
+++ b/src/ProviderUri/ProfileUri.php
@@ -1,12 +1,18 @@
normaliseBaseUri($baseRemoteUri);
parent::__construct($baseRemoteUri);
$this->path = "/profile";
+ $this->query = $this->buildQuery($token, $uuid);
}
}
\ No newline at end of file
diff --git a/src/Token.php b/src/Token.php
index 047561b..1a166f0 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -24,13 +24,22 @@ public function getIv():InitVector {
return $this->iv;
}
-// The request cipher is sent to the remote provider in the querystring. It
-// consists of the secret IV, encrypted with the client key. The remote provider
-// will decrypt the secret and use it as the key when encrypting the response
-// cipher, which will be sent back to the client application in the querystring.
- public function generateRequestCipher():string {
+/**
+ * The request cipher is sent to the remote provider in the querystring. It
+ * consists of the token's secret IV, encrypted with the client key, along with
+ * an optional message. The secret IV is required for two-way encryption. The
+ * remote provider will decrypt the secret and use it as the key if encrypting a
+ * response cipher, which will be sent back to the client application in the
+ * querystring.
+ */
+ public function generateRequestCipher(string $message = null):string {
+ $data = $this->secretIv;
+ if($message) {
+ $data .= "|" . $message;
+ }
+
$rawCipher = openssl_encrypt(
- $this->secretIv,
+ $data,
self::ENCRYPTION_METHOD,
$this->key,
0,
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 8114978..9c0e329 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -5,7 +5,7 @@
use Authwave\InitVector;
use Authwave\NotLoggedInException;
use Authwave\ProviderUri\AdminUri;
-use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LoginUri;
use Authwave\ProviderUri\LogoutUri;
use Authwave\RedirectHandler;
use Authwave\SessionData;
@@ -74,7 +74,7 @@ public function testLogoutClearsSession() {
$sut = new Authenticator(
"test-key",
"/",
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -89,13 +89,13 @@ public function testLoginRedirects() {
$redirectHandler->expects(self::once())
->method("redirect")
->with(self::callback(fn(UriInterface $uri) =>
- $uri->getHost() === AuthUri::DEFAULT_BASE_REMOTE_URI
+ $uri->getHost() === LoginUri::DEFAULT_BASE_REMOTE_URI
));
$sut = new Authenticator(
"test-key",
"/",
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -144,9 +144,9 @@ public function testLoginRedirectsWithCorrectQueryString() {
->willReturn($iv);
$expectedQueryParts = [
- AuthUri::QUERY_STRING_CIPHER => $cipher,
- AuthUri::QUERY_STRING_INIT_VECTOR => $ivString,
- AuthUri::QUERY_STRING_CURRENT_PATH => $currentPath,
+ LoginUri::QUERY_STRING_CIPHER => $cipher,
+ LoginUri::QUERY_STRING_INIT_VECTOR => $ivString,
+ LoginUri::QUERY_STRING_CURRENT_PATH => $currentPath,
];
$expectedQuery = http_build_query($expectedQueryParts);
@@ -160,7 +160,7 @@ public function testLoginRedirectsWithCorrectQueryString() {
$sut = new Authenticator(
$key,
$currentPath,
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -180,7 +180,7 @@ public function testLoginDoesNothingWhenAlreadyLoggedIn() {
$sut = new Authenticator(
"test-key",
"/",
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -290,7 +290,7 @@ public function testCompleteAuth() {
new Authenticator(
"test-key",
$currentUri,
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -317,7 +317,7 @@ public function testCompleteAuthNotAffectedByQueryString() {
new Authenticator(
"test-key",
"/example-path?filter=something",
- AuthUri::DEFAULT_BASE_REMOTE_URI,
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
null,
$redirectHandler
);
@@ -328,7 +328,7 @@ public function testGetAdminUri() {
$auth = new Authenticator(
"test-key",
"/example-path",
- AuthUri::DEFAULT_BASE_REMOTE_URI
+ LoginUri::DEFAULT_BASE_REMOTE_URI
);
$sut = $auth->getAdminUri();
self::assertEquals(
diff --git a/test/phpunit/ProviderUri/AbstractProviderUriTest.php b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
index 88ce4c0..e7deb34 100644
--- a/test/phpunit/ProviderUri/AbstractProviderUriTest.php
+++ b/test/phpunit/ProviderUri/AbstractProviderUriTest.php
@@ -3,7 +3,7 @@
use Authwave\InitVector;
use Authwave\InsecureProtocolException;
-use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LoginUri;
use Authwave\Token;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\UriInterface;
@@ -15,7 +15,7 @@ public function testAuthUriHttps() {
->willReturn("https://example.com");
$token = self::createMock(Token::class);
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
"",
$baseUri
@@ -35,7 +35,7 @@ public function testAuthUriWithNonStandardPort() {
->willReturn("http://localhost:8081");
$token = self::createMock(Token::class);
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
"",
$baseUri
@@ -54,7 +54,7 @@ public function testAuthUriWithNonStandardPort() {
// But it should still default to HTTPS on localhost.
public function testGetAuthUriHostnameLocalhostHttpsByDefault() {
$token = self::createMock(Token::class);
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
"/",
"localhost"
@@ -69,7 +69,7 @@ public function testGetAuthUriHostnameLocalhostHttpsByDefault() {
// We should be able to set the scheme to HTTP for localhost hostname only.
public function testGetAuthUriHostnameLocalhostHttpAllowed() {
$token = self::createMock(Token::class);
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
"/",
"http://localhost"
@@ -84,7 +84,7 @@ public function testGetAuthUriHostnameLocalhostHttpAllowed() {
public function testGetAuthUriHostnameNotLocalhostHttpNotAllowed() {
$token = self::createMock(Token::class);
self::expectException(InsecureProtocolException::class);
- new AuthUri(
+ new LoginUri(
$token,
"/",
"http://localhost.com"
@@ -98,7 +98,7 @@ public function testAuthUriHttpsInferred() {
// Note on the line above, no scheme is passed in - we must assume https.
$token = self::createMock(Token::class);
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
"/",
$baseUri);
diff --git a/test/phpunit/ProviderUri/AuthUriTest.php b/test/phpunit/ProviderUri/LoginUriTest.php
similarity index 77%
rename from test/phpunit/ProviderUri/AuthUriTest.php
rename to test/phpunit/ProviderUri/LoginUriTest.php
index deac72e..4b59ba2 100644
--- a/test/phpunit/ProviderUri/AuthUriTest.php
+++ b/test/phpunit/ProviderUri/LoginUriTest.php
@@ -2,12 +2,12 @@
namespace Authwave\Test\ProviderUri;
use Authwave\InitVector;
-use Authwave\ProviderUri\AuthUri;
+use Authwave\ProviderUri\LoginUri;
use Authwave\Token;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\UriInterface;
-class AuthUriTest extends TestCase {
+class LoginUriTest extends TestCase {
public function testQueryString() {
$mockCipherValue = str_repeat("f", 16);
$mockIvValue = str_repeat("0", 16);
@@ -23,7 +23,7 @@ public function testQueryString() {
->willReturn($iv);
$returnPath = "/examplePage";
- $sut = new AuthUri(
+ $sut = new LoginUri(
$token,
$returnPath,
$baseUri
@@ -32,17 +32,17 @@ public function testQueryString() {
self::assertEquals(
$mockCipherValue,
- $queryParts[AuthUri::QUERY_STRING_CIPHER],
+ $queryParts[LoginUri::QUERY_STRING_CIPHER],
);
self::assertEquals(
$mockIvValue,
- $queryParts[AuthUri::QUERY_STRING_INIT_VECTOR]
+ $queryParts[LoginUri::QUERY_STRING_INIT_VECTOR]
);
self::assertEquals(
$returnPath,
- $queryParts[AuthUri::QUERY_STRING_CURRENT_PATH]
+ $queryParts[LoginUri::QUERY_STRING_CURRENT_PATH]
);
}
}
\ No newline at end of file
From be5d06a3768253effc35885ce2d54b3818584bc3 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Sat, 16 May 2020 22:58:04 +0100
Subject: [PATCH 19/20] Refactor UserData to extend AbstractResponseData
---
src/Authenticator.php | 11 +++++------
src/ProviderUri/LogoutUri.php | 18 ++++++++++++++++++
src/ResponseData/AbstractResponseData.php | 14 ++++++++++++++
src/{ => ResponseData}/UserData.php | 9 ++++++---
src/SessionData.php | 15 +++++++++------
src/Token.php | 6 ++++--
test/phpunit/AuthenticatorTest.php | 20 ++++++++++++--------
test/phpunit/ProviderUri/LoginUriTest.php | 2 +-
test/phpunit/SessionDataTest.php | 6 +++---
test/phpunit/TokenTest.php | 2 +-
10 files changed, 73 insertions(+), 30 deletions(-)
create mode 100644 src/ProviderUri/LogoutUri.php
create mode 100644 src/ResponseData/AbstractResponseData.php
rename src/{ => ResponseData}/UserData.php (74%)
diff --git a/src/Authenticator.php b/src/Authenticator.php
index 7eb6390..ab1f471 100644
--- a/src/Authenticator.php
+++ b/src/Authenticator.php
@@ -4,6 +4,7 @@
use Authwave\ProviderUri\AbstractProviderUri;
use Authwave\ProviderUri\AdminUri;
use Authwave\ProviderUri\LoginUri;
+use Authwave\ProviderUri\LogoutUri;
use Authwave\ProviderUri\ProfileUri;
use Gt\Http\Uri;
use Gt\Session\SessionContainer;
@@ -55,7 +56,7 @@ public function isLoggedIn():bool {
$userData = null;
try {
- $userData = $this->sessionData->getUserData();
+ $userData = $this->sessionData->getData();
}
catch(NotLoggedInException $exception) {
return false;
@@ -91,17 +92,17 @@ public function logout(Token $token = null):void {
}
public function getUuid():string {
- $userData = $this->sessionData->getUserData();
+ $userData = $this->sessionData->getData();
return $userData->getUuid();
}
public function getEmail():string {
- $userData = $this->sessionData->getUserData();
+ $userData = $this->sessionData->getData();
return $userData->getEmail();
}
public function getField(string $name):?string {
- $userData = $this->sessionData->getUserData();
+ $userData = $this->sessionData->getData();
return $userData->getField($name);
}
@@ -152,8 +153,6 @@ private function completeAuth():void {
new SessionData($token, $userData)
);
- setcookie("authwave-trackshift", "test", 0, "/", "localhost");
-
$this->redirectHandler->redirect(
(new Uri($this->currentUriPath))
->withoutQueryValue(self::RESPONSE_QUERY_PARAMETER)
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
new file mode 100644
index 0000000..a64f1cd
--- /dev/null
+++ b/src/ProviderUri/LogoutUri.php
@@ -0,0 +1,18 @@
+normaliseBaseUri($baseRemoteUri);
+ $baseRemoteUri = $baseRemoteUri->withPath("/logout");
+
+ parent::__construct($baseRemoteUri);
+ $this->query = $this->buildQuery($token, $currentPath);
+ }
+}
\ No newline at end of file
diff --git a/src/ResponseData/AbstractResponseData.php b/src/ResponseData/AbstractResponseData.php
new file mode 100644
index 0000000..a3e4df6
--- /dev/null
+++ b/src/ResponseData/AbstractResponseData.php
@@ -0,0 +1,14 @@
+message = $message;
+ }
+
+ public function getMessage():?string {
+ return $this->message;
+ }
+}
\ No newline at end of file
diff --git a/src/UserData.php b/src/ResponseData/UserData.php
similarity index 74%
rename from src/UserData.php
rename to src/ResponseData/UserData.php
index 6d741c6..01ebd49 100644
--- a/src/UserData.php
+++ b/src/ResponseData/UserData.php
@@ -1,7 +1,7 @@
uuid = $uuid;
$this->email = $email;
$this->fields = $fields;
+
+ parent::__construct($message);
}
public function getUuid():string {
diff --git a/src/SessionData.php b/src/SessionData.php
index 89ae707..dee8c41 100644
--- a/src/SessionData.php
+++ b/src/SessionData.php
@@ -1,16 +1,19 @@
token = $token;
- $this->userData = $userData;
+ $this->data = $data;
}
public function getToken():Token {
@@ -21,11 +24,11 @@ public function getToken():Token {
return $this->token;
}
- public function getUserData():UserData {
- if(!isset($this->userData)) {
+ public function getData():AbstractResponseData {
+ if(!isset($this->data)) {
throw new NotLoggedInException();
}
- return $this->userData;
+ return $this->data;
}
}
\ No newline at end of file
diff --git a/src/Token.php b/src/Token.php
index 1a166f0..223008a 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -1,7 +1,9 @@
expects(self::once())
- ->method("getUserData")
+ ->method("getData")
->willReturn($userData);
$_SESSION = [
@@ -63,7 +64,10 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
self::assertTrue($sut->isLoggedIn());
}
- public function testLogoutClearsSession() {
+ // TODO: Session shouldn't be cleared on call to logout - instead it should
+ // redirect to the provider, and a new test should asset the response data
+ // contains a logout confirmation.
+ public function TODO_UPDATE_testLogoutClearsSession() {
$sessionData = self::createMock(SessionData::class);
$_SESSION = [
Authenticator::SESSION_KEY => $sessionData
@@ -146,7 +150,7 @@ public function testLoginRedirectsWithCorrectQueryString() {
$expectedQueryParts = [
LoginUri::QUERY_STRING_CIPHER => $cipher,
LoginUri::QUERY_STRING_INIT_VECTOR => $ivString,
- LoginUri::QUERY_STRING_CURRENT_PATH => $currentPath,
+ LoginUri::QUERY_STRING_CURRENT_PATH => bin2hex($currentPath),
];
$expectedQuery = http_build_query($expectedQueryParts);
@@ -205,7 +209,7 @@ public function testGetUuid() {
$userData->method("getUuid")
->willReturn($expectedUuid);
$sessionData = self::createMock(SessionData::class);
- $sessionData->method("getUserData")
+ $sessionData->method("getData")
->willReturn($userData);
$_SESSION = [
@@ -235,7 +239,7 @@ public function testGetEmail() {
$userData->method("getEmail")
->willReturn($expectedEmail);
$sessionData = self::createMock(SessionData::class);
- $sessionData->method("getUserData")
+ $sessionData->method("getData")
->willReturn($userData);
$_SESSION = [
@@ -303,8 +307,8 @@ public function testCompleteAuth() {
$newSessionData
);
self::assertInstanceOf(
- UserData::class,
- $newSessionData->getUserData()
+ AbstractResponseData::class,
+ $newSessionData->getData()
);
}
diff --git a/test/phpunit/ProviderUri/LoginUriTest.php b/test/phpunit/ProviderUri/LoginUriTest.php
index 4b59ba2..794c754 100644
--- a/test/phpunit/ProviderUri/LoginUriTest.php
+++ b/test/phpunit/ProviderUri/LoginUriTest.php
@@ -41,7 +41,7 @@ public function testQueryString() {
);
self::assertEquals(
- $returnPath,
+ bin2hex($returnPath),
$queryParts[LoginUri::QUERY_STRING_CURRENT_PATH]
);
}
diff --git a/test/phpunit/SessionDataTest.php b/test/phpunit/SessionDataTest.php
index 5e54c88..8b8d07b 100644
--- a/test/phpunit/SessionDataTest.php
+++ b/test/phpunit/SessionDataTest.php
@@ -4,7 +4,7 @@
use Authwave\NotLoggedInException;
use Authwave\SessionData;
use Authwave\Token;
-use Authwave\UserData;
+use Authwave\ResponseData\UserData;
use PHPUnit\Framework\TestCase;
class SessionDataTest extends TestCase {
@@ -23,13 +23,13 @@ public function testGetToken() {
public function testGetUserDataNull() {
$sut = new SessionData();
self::expectException(NotLoggedInException::class);
- $sut->getUserData();
+ $sut->getData();
}
public function testGetUserData() {
$token = self::createMock(Token::class);
$userData = self::createMock(UserData::class);
$sut = new SessionData($token, $userData);
- self::assertSame($userData, $sut->getUserData());
+ self::assertSame($userData, $sut->getData());
}
}
\ No newline at end of file
diff --git a/test/phpunit/TokenTest.php b/test/phpunit/TokenTest.php
index b81e46a..d001a7b 100644
--- a/test/phpunit/TokenTest.php
+++ b/test/phpunit/TokenTest.php
@@ -5,7 +5,7 @@
use Authwave\InvalidUserDataSerializationException;
use Authwave\ResponseCipherDecryptionException;
use Authwave\Token;
-use Authwave\UserData;
+use Authwave\ResponseData\UserData;
use PHPUnit\Framework\TestCase;
class TokenTest extends TestCase {
From 77b7d2c6bc515e562cc17a452da0cf4161cc42e5 Mon Sep 17 00:00:00 2001
From: Greg Bowler
Date: Mon, 18 May 2020 23:12:11 +0100
Subject: [PATCH 20/20] Send actions as encrypted messages
---
src/ProviderUri/AbstractProviderUri.php | 4 +-
src/ProviderUri/LogoutUri.php | 7 +++-
test/phpunit/AuthenticatorTest.php | 49 +++++++++++++++++++++++--
3 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/src/ProviderUri/AbstractProviderUri.php b/src/ProviderUri/AbstractProviderUri.php
index 747e795..bdd63f4 100644
--- a/src/ProviderUri/AbstractProviderUri.php
+++ b/src/ProviderUri/AbstractProviderUri.php
@@ -35,10 +35,10 @@ protected function normaliseBaseUri(string $baseUri):Uri {
protected function buildQuery(
Token $token,
string $currentPath,
- string $data = null
+ string $message = null
):string {
return http_build_query([
- self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher($data),
+ self::QUERY_STRING_CIPHER => (string)$token->generateRequestCipher($message),
self::QUERY_STRING_INIT_VECTOR => (string)$token->getIv(),
self::QUERY_STRING_CURRENT_PATH => bin2hex($currentPath),
]);
diff --git a/src/ProviderUri/LogoutUri.php b/src/ProviderUri/LogoutUri.php
index a64f1cd..c2ed192 100644
--- a/src/ProviderUri/LogoutUri.php
+++ b/src/ProviderUri/LogoutUri.php
@@ -10,9 +10,12 @@ public function __construct(
string $baseRemoteUri = self::DEFAULT_BASE_REMOTE_URI
) {
$baseRemoteUri = $this->normaliseBaseUri($baseRemoteUri);
- $baseRemoteUri = $baseRemoteUri->withPath("/logout");
parent::__construct($baseRemoteUri);
- $this->query = $this->buildQuery($token, $currentPath);
+ $this->query = $this->buildQuery(
+ $token,
+ $currentPath,
+ "action=logout"
+ );
}
}
\ No newline at end of file
diff --git a/test/phpunit/AuthenticatorTest.php b/test/phpunit/AuthenticatorTest.php
index 444b3ba..5fba507 100644
--- a/test/phpunit/AuthenticatorTest.php
+++ b/test/phpunit/AuthenticatorTest.php
@@ -64,16 +64,19 @@ public function testIsLoggedInTrueWhenSessionDataSet() {
self::assertTrue($sut->isLoggedIn());
}
- // TODO: Session shouldn't be cleared on call to logout - instead it should
- // redirect to the provider, and a new test should asset the response data
- // contains a logout confirmation.
- public function TODO_UPDATE_testLogoutClearsSession() {
+ public function testLogoutCallsLogoutUri() {
$sessionData = self::createMock(SessionData::class);
$_SESSION = [
Authenticator::SESSION_KEY => $sessionData
];
$redirectHandler = self::createMock(RedirectHandler::class);
+ $redirectHandler->expects(self::once())
+ ->method("redirect")
+ ->with(self::callback(fn(UriInterface $uri) =>
+ $uri->getHost() === "login.authwave.com"
+ && $uri->getPath() === "/logout"
+ ));
$sut = new Authenticator(
"test-key",
@@ -83,6 +86,44 @@ public function TODO_UPDATE_testLogoutClearsSession() {
$redirectHandler
);
$sut->logout();
+ self::assertNotEmpty($_SESSION);
+ }
+
+ public function testCompleteAuthFromLogoutClearsSession() {
+ $token = self::createMock(Token::class);
+
+ $sessionData = self::createMock(SessionData::class);
+ $sessionData->method("getToken")
+ ->willReturn($token);
+
+ $_SESSION = [
+ Authenticator::SESSION_KEY => $sessionData,
+ ];
+
+ $responseCipher = "abcdef";
+
+ $currentUri = "/example-page-" . uniqid();
+ $currentUri .= "?";
+ $currentUri .= http_build_query([
+ Authenticator::RESPONSE_QUERY_PARAMETER => $responseCipher,
+ ]);
+
+ $redirectHandler = self::createMock(RedirectHandler::class);
+ $redirectHandler->expects(self::once())
+ ->method("redirect")
+ ->with(self::callback(fn(UriInterface $uri) =>
+ $uri->getHost() == ""
+ && $uri->getPath() == $currentUri
+ ));
+
+ new Authenticator(
+ "test-key",
+ "/",
+ LoginUri::DEFAULT_BASE_REMOTE_URI,
+ null,
+ $redirectHandler
+ );
+
self::assertEmpty($_SESSION);
}