|
@ -1,6 +1,7 @@ |
|
|
<?php |
|
|
<?php |
|
|
|
|
|
|
|
|
namespace authkit2\Oidc\Flows; |
|
|
namespace authkit2\Oidc\Flows; |
|
|
|
|
|
use authkit2\Authkit2; |
|
|
use authkit2\Oidc\Client; |
|
|
use authkit2\Oidc\Client; |
|
|
use authkit2\Oidc\Authentication\ClientAuthentication; |
|
|
use authkit2\Oidc\Authentication\ClientAuthentication; |
|
|
use authkit2\Oidc\Token; |
|
|
use authkit2\Oidc\Token; |
|
@ -52,9 +53,10 @@ class UserFlow |
|
|
// We use 30 because that should generate an even number of base64 characters |
|
|
// We use 30 because that should generate an even number of base64 characters |
|
|
// and not require padding. (6 bits / char) |
|
|
// and not require padding. (6 bits / char) |
|
|
$state = base64_encode(random_bytes(30)); |
|
|
$state = base64_encode(random_bytes(30)); |
|
|
$this->prepareSession(); |
|
|
|
|
|
// Keep a list of all valid states we've generated |
|
|
// Keep a list of all valid states we've generated |
|
|
array_push($_SESSION['authkit2.state'], $state); |
|
|
$states = Authkit2::session_get('userflow.state') ?? []; |
|
|
|
|
|
array_push($states, $state); |
|
|
|
|
|
Authkit2::session_set('userflow.state', $states); |
|
|
|
|
|
|
|
|
return $this->client->getEndpointUrl('authorization').'?'.http_build_query([ |
|
|
return $this->client->getEndpointUrl('authorization').'?'.http_build_query([ |
|
|
'client_id' => $this->client_id, |
|
|
'client_id' => $this->client_id, |
|
@ -73,12 +75,13 @@ class UserFlow |
|
|
*/ |
|
|
*/ |
|
|
public function validateState(string $state): void |
|
|
public function validateState(string $state): void |
|
|
{ |
|
|
{ |
|
|
$this->prepareSession(); |
|
|
$states = Authkit2::session_get('userflow.state') ?? []; |
|
|
for ($i=0; $i<sizeof($_SESSION['authkit2.state']); $i++) |
|
|
for ($i=0; $i<sizeof($states); $i++) |
|
|
{ |
|
|
{ |
|
|
if ($_SESSION['authkit2.state'][$i] == $state) |
|
|
if ($states[$i] == $state) |
|
|
{ |
|
|
{ |
|
|
$_SESSION['authkit2.state'] = array_splice($_SESSION['authkit2.state'], $i, 1); |
|
|
$states = array_splice($states, $i, 1); |
|
|
|
|
|
Authkit2::session_set('userflow.state', $states); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -104,21 +107,5 @@ class UserFlow |
|
|
return Token::fromResponse($response); |
|
|
return Token::fromResponse($response); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Ensure that a PHP session exists for storing the state information in |
|
|
|
|
|
* |
|
|
|
|
|
* @return void |
|
|
|
|
|
*/ |
|
|
|
|
|
protected function prepareSession(): void |
|
|
|
|
|
{ |
|
|
|
|
|
// If a session doesn't exist, start one |
|
|
|
|
|
// TODO: PHP_SESSION_DISABLED shouldn't happen in any sane universe, but |
|
|
|
|
|
// throw an exception if that's the case |
|
|
|
|
|
if (session_status() == \PHP_SESSION_NONE) |
|
|
|
|
|
session_start(); |
|
|
|
|
|
if (!isset($_SESSION['authkit2.state'])) |
|
|
|
|
|
$_SESSION['authkit2.state'] = []; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|