Skip to content

Commit

Permalink
NEW enhance the OAUTH2 token manager. Can refresh a token from page.
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Aug 1, 2024
1 parent edd56da commit 4a9d039
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 36 deletions.
127 changes: 94 additions & 33 deletions htdocs/admin/oauthlogintokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';

use OAuth\Common\Storage\DoliStorage;
use OAuth\Common\Consumer\Credentials;

$supportedoauth2array = getSupportedOauth2Array();

Expand Down Expand Up @@ -114,6 +115,66 @@
$action = '';
}

// Test a refresh of a token using the refresh token
if ($action == 'refreshtoken' && $user->admin) {
$keyforprovider = GETPOST('keyforprovider');
$OAUTH_SERVICENAME = GETPOST('service');

// Show value of token
$tokenobj = null;
// Load OAUth libraries
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
// Dolibarr storage
$storage = new DoliStorage($db, $conf, $keyforprovider);
try {
// $OAUTH_SERVICENAME is for example 'Google-keyforprovider'
print '<!-- '.$OAUTH_SERVICENAME.' -->'."\n";
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
$expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30));
// We have to save the refresh token because Google give it only once
$refreshtoken = $tokenobj->getRefreshToken();
print '<!-- data stored into field token: '.$storage->token.' - expire '.((string) $expire).' -->';

//print $tokenobj->getExtraParams()['id_token'].'<br>';
//print $tokenobj->getAccessToken().'<br>';
//print $tokenobj->getRefreshToken().'<br>';


//var_dump($expire);

// We do the refresh even if not expired, this is the goal of action.
$credentials = new Credentials(
getDolGlobalString('OAUTH_'.strtoupper($OAUTH_SERVICENAME).'_ID'),
getDolGlobalString('OAUTH_'.strtoupper($OAUTH_SERVICENAME).'_SECRET'),
getDolGlobalString('OAUTH_'.strtoupper($OAUTH_SERVICENAME).'_URLAUTHORIZE')
);
$serviceFactory = new \OAuth\ServiceFactory();
$oauthname = explode('-', $OAUTH_SERVICENAME);
// ex service is Google-Emails we need only the first part Google
$apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array());

if ($apiService instanceof OAuth\OAuth2\Service\AbstractService || $apiService instanceof OAuth\OAuth1\Service\AbstractService) {
// ServiceInterface does not provide refreshAccessToekn, AbstractService does
$tokenobj = $apiService->refreshAccessToken($tokenobj);
$tokenobj->setRefreshToken($refreshtoken); // Restore the refresh token
$storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);

if ($expire) {
setEventMessages($langs->trans("OldTokenWasExpiredItHasBeenRefresh"), null, 'mesgs');
} else {
setEventMessages($langs->trans("OldTokenWasNotExpiredButItHasBeenRefresh"), null, 'mesgs');
}
} else {
dol_print_error($db, 'apiService is not a correct OAUTH2 Abstract service');
}

$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
} catch (Exception $e) {
// Return an error if token not found
print $e->getMessage();
}
}


/*
* View
Expand Down Expand Up @@ -188,6 +249,8 @@
}
$state = $shortscope; // TODO USe a better state

$urltorefresh = $_SERVER["PHP_SELF"].'?action=refreshtoken&token='.newToken();

// Define $urltorenew, $urltodelete, $urltocheckperms
if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') {
// List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service).
Expand Down Expand Up @@ -217,6 +280,9 @@
if ($urltorenew) {
$urltorenew .= '&keyforprovider='.urlencode($keyforprovider);
}
if ($urltorefresh) {
$urltorefresh .= '&keyforprovider='.urlencode($keyforprovider).'&service='.urlencode($OAUTH_SERVICENAME);
}
if ($urltodelete) {
$urltodelete .= '&keyforprovider='.urlencode($keyforprovider);
}
Expand Down Expand Up @@ -334,50 +400,61 @@
if (is_object($tokenobj)) {
//test on $storage->hasAccessToken($OAUTH_SERVICENAME) ?
if ($urltodelete) {
print '<a class="button smallpaddingimp reposition" href="'.$urltodelete.'">'.$langs->trans('DeleteAccess').'</a><br>';
print '<a class="button button-delete smallpaddingimp reposition marginright" href="'.$urltodelete.'">'.$langs->trans('DeleteAccess').'</a>';
} else {
print '<span class="opacitymedium">'.$langs->trans('GoOnTokenProviderToDeleteToken').'</span><br>';
print '<span class="opacitymedium marginright">'.$langs->trans('GoOnTokenProviderToDeleteToken').'</span>';
}
}
// Request remote token
if ($urltorenew) {
print '<a class="button smallpaddingimp reposition" href="'.$urltorenew.'">'.$langs->trans('GetAccess').'</a>';
print $form->textwithpicto('', $langs->trans('RequestAccess'));
print '<br>';
print '<a class="button smallpaddingimp reposition classfortooltip marginright" href="'.$urltorenew.'" title="'.dolPrintHTMLForAttribute($langs->trans('RequestAccess')).'">'.$langs->trans('GetAccess').'</a>';
}
// Request remote token
if ($urltorefresh && $refreshtoken) {
print '<a class="button smallpaddingimp reposition classfortooltip marginright" href="'.$urltorefresh.'" title="'.dolPrintHTMLForAttribute($langs->trans('RefreshTokenHelp')).'">'.$langs->trans('RefreshToken').'</a>';
}

// Check remote access
if ($urltocheckperms) {
print '<br>'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': <a class="reposition" href="'.$urltocheckperms.'" target="_'.strtolower($OAUTH_SERVICENAME).'">'.$urltocheckperms.'</a>';
print '<br>'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': <a href="'.$urltocheckperms.'" target="_'.strtolower($OAUTH_SERVICENAME).'">'.$urltocheckperms.'</a>';
}
}
print '</td>';
print '</tr>';

print '<tr class="oddeven">';
print '<td>';
//var_dump($key);
print $langs->trans("TokenRawValue").'</td>';
print '<td colspan="2">';
if (is_object($tokenobj)) {
print '<textarea class="quatrevingtpercent small" rows="'.ROWS_5.'">'.var_export($tokenobj, true).'</textarea><br>'."\n";
}
print '</td>';
print '</tr>'."\n";
print '<tr class="oddeven">';
print '<td>';
//var_dump($key);
print $langs->trans("TokenRawValue").'</td>';
print '<td colspan="2">';
if (is_object($tokenobj)) {
print '<textarea class="quatrevingtpercent small" rows="'.ROWS_4.'">'.var_export($tokenobj, true).'</textarea><br>'."\n";
}
print '</td>';
print '</tr>'."\n";

if (is_object($tokenobj)) {
print '<tr class="oddeven">';
print '<td>';
//var_dump($key);
print $langs->trans("AccessToken").'</td>';
print '<td colspan="2">';
$tokentoshow = $tokenobj->getAccessToken();
print '<span class="" title="'.dol_escape_htmltag($tokentoshow).'">'.showValueWithClipboardCPButton($tokentoshow, 1, dol_trunc($tokentoshow, 32)).'</span><br>';
print '<span class="" title="'.dol_escape_htmltag($tokentoshow).'">'.showValueWithClipboardCPButton($tokentoshow, 1, dol_trunc($tokentoshow, 32)).'</span>';
//print 'Refresh: '.$tokenobj->getRefreshToken().'<br>';
//print 'EndOfLife: '.$tokenobj->getEndOfLife().'<br>';
//var_dump($tokenobj->getExtraParams());
/*print '<br>Extra: <br><textarea class="quatrevingtpercent">';
print ''.join(',',$tokenobj->getExtraParams());
print '</textarea>';*/

print '<span class="opacitymedium"> &nbsp; - &nbsp; ';
print $langs->trans("ExpirationDate").': ';
print '</span>';
print $expiredat;

print $expire ? ' ('.$langs->trans("TokenExpired").')' : ' ('.$langs->trans("TokenNotExpired").')';

print '</td>';
print '</tr>'."\n";

Expand All @@ -391,22 +468,6 @@
print '<span class="" title="'.dol_escape_htmltag($refreshtoken).'">'.showValueWithClipboardCPButton($refreshtoken, 1, dol_trunc($refreshtoken, 32)).'</span>';
print '</td>';
print '</tr>';

// Token expired
print '<tr class="oddeven">';
print '<td>';
//var_dump($key);
print $langs->trans("TOKEN_EXPIRED");
print '</td>';
print '<td colspan="2">';
print yn($expire);

print '<span class="opacitymedium"> &nbsp; - &nbsp; ';
print $langs->trans("TOKEN_EXPIRE_AT").': ';
print '</span>';
print $expiredat;
print '</td>';
print '</tr>';
}

print '</table>';
Expand Down
13 changes: 10 additions & 3 deletions htdocs/langs/en_US/oauth.lang
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ HasAccessToken=A token was generated and saved into local database
NewTokenStored=Token received and saved
ToCheckDeleteTokenOnProvider=Click here to check/delete authorization saved by %s OAuth provider
TokenDeleted=Token deleted
GetAccess=Click here to get a token
GetAccess=Get new Token
RequestAccess=Click here to request/renew access and receive a new token
DeleteAccess=Click here to delete the token
DeleteAccess=Delete Token
RedirectURL=Redirect URL
UseTheFollowingUrlAsRedirectURI=Use the following URL as the Redirect URL when creating your credentials with your OAuth provider
ListOfSupportedOauthProviders=Add your OAuth2 token providers. Then, go on your OAuth provider admin page to create/get an OAuth ID and Secret and save them here. Once done, switch on the other tab to generate your token.
Expand Down Expand Up @@ -40,5 +40,12 @@ AOAuthEntryForThisProviderAndLabelAlreadyHasAKey=An OAuth entry for this provide
URLOfServiceForAuthorization=URL provided by OAuth service for authentication
Scopes=Permissions (Scopes)
ScopeUndefined=Permissions (Scopes) undefined (see previous tab)
TokenRawValue=Token (Raw value)
TokenRawValue=Full Token (object)
AccessToken=Access Token
TokenExpired=Expired
TokenNotExpired=Not expired
ExpirationDate=Expiration date
RefreshToken=Refresh token
RefreshTokenHelp=Use the Refresh Token to get a new Access Token
OldTokenWasExpiredItHasBeenRefresh=Old token was expired, it has been refreshed
OldTokenWasNotExpiredButItHasBeenRefresh=Old token was not expired but it has been refreshed

0 comments on commit 4a9d039

Please sign in to comment.