Skip to content

Commit

Permalink
Merge pull request #31 from xp-forge/feature/cas-session-namespace
Browse files Browse the repository at this point in the history
Make it possible to change the session namespace (CAS)
  • Loading branch information
thekid authored Jul 17, 2024
2 parents 1ce8c99 + 5c88986 commit 207adaa
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 20 deletions.
13 changes: 13 additions & 0 deletions src/main/php/web/auth/Flow.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions src/main/php/web/auth/cas/CasFlow.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
use web\{Cookie, Error, Filter};

class CasFlow extends Flow {
const SESSION_KEY = 'cas::flow';

private $sso;

/**
Expand All @@ -19,6 +17,7 @@ class CasFlow extends Flow {
*/
public function __construct($sso) {
$this->sso= rtrim($sso, '/');
$this->namespace= 'cas::flow';
}

/**
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 1 addition & 13 deletions src/main/php/web/auth/oauth/OAuthFlow.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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
Expand Down
29 changes: 26 additions & 3 deletions src/test/php/web/auth/unittest/CasFlowTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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('
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>test</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
');
}
};
$session= (new ForTesting())->create();

$this->authenticate($fixture->namespaced($namespace), '/?ticket='.self::TICKET, $session);
Assert::equals(
['username' => 'test'],
$session->value($namespace)
);
}

Expand All @@ -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)
);
}

Expand All @@ -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());
Expand Down

0 comments on commit 207adaa

Please sign in to comment.