Skip to content

Commit

Permalink
Reset state after authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
thekid committed Feb 5, 2021
1 parent c3d5d53 commit c2fb794
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 9 deletions.
6 changes: 6 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Web Authentication change log

## ?.?.? / ????-??-??

## 2.2.1 / 2021-02-05

* Reset state after authentication via OAuth in order to prevent dead
ends with expired tokens - instead, authentication will be retried
(@thekid)

## 2.2.0 / 2021-01-03

* Made it possible to send more than just `GET` requests with `fetch()`
Expand Down
5 changes: 4 additions & 1 deletion src/main/php/web/auth/oauth/OAuth1Flow.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ protected function request($path, $token= null, $params= []) {
public function authenticate($request, $response, $session) {
$state= $session->value(self::SESSION_KEY);

// We have an access token, return an authenticated session
// We have an access token, reset state and return an authenticated session
if (isset($state['access'])) {
$session->remove(self::SESSION_KEY);
$session->transmit($response);

return new BySignedRequests($this->signature->with(new Token($state['oauth_token'], $state['oauth_token_secret'])));
}

Expand Down
21 changes: 13 additions & 8 deletions src/main/php/web/auth/oauth/OAuth2Flow.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,20 @@ protected function token($payload) {
public function authenticate($request, $response, $session) {
$stored= $session->value(self::SESSION_KEY);

// We have an access token, return an authenticated session
// We have an access token, reset state and return an authenticated session
// See https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/
if (isset($stored['access_token'])) return new ByAccessToken(
$stored['access_token'],
$stored['token_type'],
$stored['scope'] ?? null,
$stored['expires_in'] ?? null,
$stored['refresh_token'] ?? null
);
if (isset($stored['access_token'])) {
$session->remove(self::SESSION_KEY);
$session->transmit($response);

return new ByAccessToken(
$stored['access_token'],
$stored['token_type'],
$stored['scope'] ?? null,
$stored['expires_in'] ?? null,
$stored['refresh_token'] ?? null
);
}

$uri= $this->url(true)->resolve($request);
$callback= $this->callback ? $uri->resolve($this->callback) : $this->service($uri);
Expand Down
14 changes: 14 additions & 0 deletions src/test/php/web/auth/unittest/OAuth1FlowTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@ public function returns_client() {
Assert::instance(Client::class, $fixture->authenticate($req, $res, $session));
}

#[Test]
public function resets_state_after_returning_client() {
$access= ['oauth_token' => 'ACCESS-TOKEN', 'oauth_token_secret' => 'XYZ', 'access' => true];
$fixture= new OAuth1Flow(self::AUTH, [self::ID, self::SECRET], self::CALLBACK);

$req= new Request(new TestInput('GET', '/'));
$res= new Response(new TestOutput());
$session= (new ForTesting())->create();
$session->register(OAuth1Flow::SESSION_KEY, $access);
$fixture->authenticate($req, $res, $session);

Assert::null($session->value(OAuth1Flow::SESSION_KEY));
}

#[Test, Values('fragments')]
public function appends_fragment($fragment) {
$fixture= new OAuth1Flow(self::AUTH, [self::ID, self::SECRET], self::CALLBACK);
Expand Down
14 changes: 14 additions & 0 deletions src/test/php/web/auth/unittest/OAuth2FlowTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,20 @@ public function returns_client_in_final_step() {
Assert::instance(Client::class, $fixture->authenticate($req, $res, $session));
}

#[Test]
public function resets_state_after_returning_client() {
$token= ['access_token' => '<TOKEN>', 'token_type' => 'Bearer'];
$fixture= new OAuth2Flow(self::AUTH, self::TOKENS, self::CONSUMER, self::CALLBACK);

$req= new Request(new TestInput('GET', '/'));
$res= new Response(new TestOutput());
$session= (new ForTesting())->create();
$session->register(OAuth2Flow::SESSION_KEY, $token);
$fixture->authenticate($req, $res, $session);

Assert::null($session->value(OAuth2Flow::SESSION_KEY));
}

/** @deprecated */
#[Test, Values('paths')]
public function deprecated_usage_without_callback_uri($path) {
Expand Down

0 comments on commit c2fb794

Please sign in to comment.