Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 53 additions & 15 deletions tests/acceptance/TestHelpers/TokenHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,37 @@ class TokenHelper {
private const LOGON_URL = '/signin/v1/identifier/_/logon';
private const REDIRECT_URL = '/oidc-callback.html';
private const TOKEN_URL = '/konnect/v1/token';
private const TRANSPORT_RETRY_LIMIT = 3;

// Static cache [username => token_data]
private static array $tokenCache = [];

/**
* Run a token exchange and retry it if it fails with a transport error. The
* limit counts retries, the exchange runs at most one time more than that.
*
* @param callable $exchange returns the token data array
*
* @return array
* @throws GuzzleException the last error if every attempt fails
*/
private static function retryOnTransportError(callable $exchange): array {
$attempt = 0;
while (true) {
try {
return $exchange();
} catch (GuzzleException $e) {
if ($attempt >= self::TRANSPORT_RETRY_LIMIT) {
throw $e;
}
$attempt++;
echo "[INFO] token exchange failed with '" . $e->getMessage() .
"', retrying ($attempt)...\n";
\sleep(1);
}
}
}

/**
* @return bool
*/
Expand Down Expand Up @@ -80,24 +107,35 @@ public static function getTokens(string $username, string $password, string $url
return $cachedToken;
}

$refreshedToken = self::refreshToken($cachedToken['refresh_token'], $baseUrl);
$tokenData = [
'access_token' => $refreshedToken['access_token'],
'refresh_token' => $refreshedToken['refresh_token'],
// set expiry to 240 (4 minutes) seconds to allow for some buffer
// token actually expires in 300 seconds (5 minutes)
'expires_at' => time() + 240
];
self::$tokenCache[$cacheKey] = $tokenData;
return $tokenData;
try {
$refreshedToken = self::retryOnTransportError(
fn () => self::refreshToken($cachedToken['refresh_token'], $baseUrl)
);
$tokenData = [
'access_token' => $refreshedToken['access_token'],
'refresh_token' => $refreshedToken['refresh_token'],
// set expiry to 240 (4 minutes) seconds to allow for some buffer
// token actually expires in 300 seconds (5 minutes)
'expires_at' => time() + 240
];
self::$tokenCache[$cacheKey] = $tokenData;
return $tokenData;
} catch (\Exception $e) {
echo "[INFO] token refresh failed with '" . $e->getMessage() .
"', falling back to a full login...\n";
unset(self::$tokenCache[$cacheKey]);
}
}

// Get new tokens
$cookieJar = new CookieJar();

$continueUrl = self::getAuthorizedEndPoint($username, $password, $baseUrl, $cookieJar);
$code = self::getCode($continueUrl, $baseUrl, $cookieJar);
$tokens = self::getToken($code, $baseUrl, $cookieJar);
$tokens = self::retryOnTransportError(
function () use ($username, $password, $baseUrl) {
$cookieJar = new CookieJar();
$continueUrl = self::getAuthorizedEndPoint($username, $password, $baseUrl, $cookieJar);
$code = self::getCode($continueUrl, $baseUrl, $cookieJar);
return self::getToken($code, $baseUrl, $cookieJar);
}
);

$tokenData = [
'access_token' => $tokens['access_token'],
Expand Down