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