From 0e4cf53fcb0f3c47a26a5faf5f0f7f41e715df24 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 20 Nov 2022 23:47:29 +0100 Subject: [PATCH] Allow login flows to return Continuation instances These will rewrite the request URI and pass an "auth" value with the response, and then continue processing the request. This can be used e.g. to show a login page --- src/main/php/web/auth/Continuation.class.php | 16 +++++++++++++++ src/main/php/web/auth/SessionBased.class.php | 20 ++++++++++++------- .../auth/unittest/SessionBasedTest.class.php | 13 +++++++++++- 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100755 src/main/php/web/auth/Continuation.class.php diff --git a/src/main/php/web/auth/Continuation.class.php b/src/main/php/web/auth/Continuation.class.php new file mode 100755 index 0000000..47a730f --- /dev/null +++ b/src/main/php/web/auth/Continuation.class.php @@ -0,0 +1,16 @@ +uri= $uri; + $this->value= $value; + } +} \ No newline at end of file diff --git a/src/main/php/web/auth/SessionBased.class.php b/src/main/php/web/auth/SessionBased.class.php index 9af7539..2f3f378 100755 --- a/src/main/php/web/auth/SessionBased.class.php +++ b/src/main/php/web/auth/SessionBased.class.php @@ -86,13 +86,19 @@ public function filter($req, $res, $invocation) { if (null === $user) { - // Authentication may require redirection in order to fulfill its job. - // In this case, return early from this method w/o passing control on. - if (null === ($result= $this->flow->authenticate($req, $res, $session))) return; - - // Otherwise, authorize and transmit session - $user= $this->authorize($session, $result); - $session->transmit($res); + // Authentication may require redirection (indicated by returning NULL) + // or showing a page (indicated by returing a Continuation instance) in + // order to fulfill its job. + $result= $this->flow->authenticate($req, $res, $session); + if (null === $result) { + return; + } else if ($result instanceof Continuation) { + $req->rewrite($result->uri)->pass('auth', $result->value); + $session->transmit($res); + } else { + $user= $this->authorize($session, $result); + $session->transmit($res); + } } return $invocation->proceed($req->pass('user', $user)->pass('token', $token), $res); diff --git a/src/test/php/web/auth/unittest/SessionBasedTest.class.php b/src/test/php/web/auth/unittest/SessionBasedTest.class.php index c6aa183..2ebee82 100755 --- a/src/test/php/web/auth/unittest/SessionBasedTest.class.php +++ b/src/test/php/web/auth/unittest/SessionBasedTest.class.php @@ -2,7 +2,7 @@ use lang\IllegalStateException; use unittest\Assert; -use web\auth\{SessionBased, Flow}; +use web\auth\{Continuation, SessionBased, Flow}; use web\io\{TestInput, TestOutput}; use web\session\{ISession, ForTesting}; use web\{Request, Response}; @@ -155,4 +155,15 @@ public function session_is_attached_after_authentication() { Assert::equals(1, $attached->value('times')); Assert::equals($user, $attached->value('auth')[1]); } + + #[Test] + public function continuation_rewrites_uri_and_passes_value() { + $sessions= new ForTesting(); + $auth= new SessionBased($this->authenticate(new Continuation('/login', 'test')), $sessions); + $this->handle([], $auth->required(function($req, $res) use(&$passed) { + $passed= [$req->uri()->path(), $req->value('auth')]; + })); + + Assert::equals(['/login', 'test'], $passed); + } } \ No newline at end of file