diff --git a/src/main/php/web/auth/Flow.class.php b/src/main/php/web/auth/Flow.class.php index 9866823..4d7190e 100755 --- a/src/main/php/web/auth/Flow.class.php +++ b/src/main/php/web/auth/Flow.class.php @@ -6,6 +6,19 @@ abstract class Flow { const FRAGMENT= '_'; private $url= null; + protected $namespace; + + /** + * Sets session namespace for this flow. Used to prevent conflicts + * in session state with multiple OAuth flows in place. + * + * @param string $namespace + * @return self + */ + public function namespaced($namespace) { + $this->namespace= $namespace; + return $this; + } /** * Targets a given URL diff --git a/src/main/php/web/auth/cas/CasFlow.class.php b/src/main/php/web/auth/cas/CasFlow.class.php index 8b0c249..b7007c6 100755 --- a/src/main/php/web/auth/cas/CasFlow.class.php +++ b/src/main/php/web/auth/cas/CasFlow.class.php @@ -8,8 +8,6 @@ use web\{Cookie, Error, Filter}; class CasFlow extends Flow { - const SESSION_KEY = 'cas::flow'; - private $sso; /** @@ -19,6 +17,7 @@ class CasFlow extends Flow { */ public function __construct($sso) { $this->sso= rtrim($sso, '/'); + $this->namespace= 'cas::flow'; } /** @@ -44,7 +43,7 @@ protected function validate($ticket, $service) { * @return var */ public function authenticate($request, $response, $session) { - $state= $session->value(self::SESSION_KEY); + $state= $session->value($this->namespace); if (isset($state['username'])) return $state; // If no ticket is present, redirect to SSO. Otherwise, validate ticket, @@ -104,7 +103,7 @@ public function authenticate($request, $response, $session) { // Success-oriented if ($user= $result['user'] ?? null) { - $session->register(self::SESSION_KEY, $user); + $session->register($this->namespace, $user); $session->transmit($response); $this->finalize($response, $service); return null; diff --git a/src/main/php/web/auth/oauth/OAuthFlow.class.php b/src/main/php/web/auth/oauth/OAuthFlow.class.php index d01d72c..83db688 100755 --- a/src/main/php/web/auth/oauth/OAuthFlow.class.php +++ b/src/main/php/web/auth/oauth/OAuthFlow.class.php @@ -4,7 +4,7 @@ use web\auth\{Flow, UserInfo, AuthenticationError}; abstract class OAuthFlow extends Flow { - protected $callback, $namespace; + protected $callback; /** @return ?util.URI */ public function callback() { return $this->callback; } @@ -15,18 +15,6 @@ public function calling($callback): self { return $this; } - /** - * Sets session namespace for this flow. Used to prevent conflicts - * in session state with multiple OAuth flows in place. - * - * @param string $namespace - * @return self - */ - public function namespaced($namespace) { - $this->namespace= $namespace; - return $this; - } - /** * Returns user info which fetched from the given endpoint using the * authorized OAuth client diff --git a/src/test/php/web/auth/unittest/CasFlowTest.class.php b/src/test/php/web/auth/unittest/CasFlowTest.class.php index 5417de0..0365e93 100755 --- a/src/test/php/web/auth/unittest/CasFlowTest.class.php +++ b/src/test/php/web/auth/unittest/CasFlowTest.class.php @@ -11,6 +11,7 @@ use web\{Error, Request, Response}; class CasFlowTest extends FlowTest { + const SNS = 'cas::flow'; const SSO = 'https://example.com/sso'; const SERVICE = 'https://service.example.com'; const TICKET = 'ST-1856339-aA5Yuvrxzpv8Tau1cYQ7'; @@ -147,7 +148,29 @@ public function validate($ticket, $service) { $this->authenticate($fixture, '/?ticket='.self::TICKET, $session); Assert::equals( ['username' => 'test'], - $session->value(CasFlow::SESSION_KEY) + $session->value(self::SNS) + ); + } + + #[Test, Values(['cas::flow', 'flow'])] + public function session_namespace($namespace) { + $fixture= new class(self::SSO) extends CasFlow { + public function validate($ticket, $service) { + return CasFlowTest::response(' + + + test + + + '); + } + }; + $session= (new ForTesting())->create(); + + $this->authenticate($fixture->namespaced($namespace), '/?ticket='.self::TICKET, $session); + Assert::equals( + ['username' => 'test'], + $session->value($namespace) ); } @@ -173,7 +196,7 @@ public function validate($ticket, $service) { $this->authenticate($fixture, '/?ticket='.self::TICKET, $session); Assert::equals( ['username' => 'test', 'givenName' => 'John Doe', 'email' => 'jdoe@example.org'], - $session->value(CasFlow::SESSION_KEY) + $session->value(self::SNS) ); } @@ -183,7 +206,7 @@ public function returns_user_in_final_step() { $fixture= new CasFlow(self::SSO); $session= (new ForTesting())->create(); - $session->register(CasFlow::SESSION_KEY, $user); + $session->register(self::SNS, $user); $req= new Request(new TestInput('GET', '/')); $res= new Response(new TestOutput());