docusign_signature-1.0.x-dev/src/DocuSignAuth/CodeGrant.php
src/DocuSignAuth/CodeGrant.php
<?php
declare(strict_types=1);
namespace Drupal\docusign_signature\DocuSignAuth;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Url;
use Drupal\docusign_signature\Auth\DocuSign;
use Drupal\docusign_signature\AuthBase;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* DocuSign authentication with code grant.
*
* @package Drupal\docusign_signature\DocuSignAuth
*
* @DocuSignAuth(
* id = "code_grant",
* label = @Translation("Code Grant")
* )
*/
class CodeGrant extends AuthBase {
/**
* {@inheritdoc}
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \OAuthException
*/
public function authCallback(string $redirectUrl = NULL): RedirectResponse {
$provider = $this->getOauthProvider();
$request = \Drupal::requestStack()->getCurrentRequest();
$state = $request->query->get('state');
// Check given state against previously stored one to mitigate CSRF attack.
if (
empty($state) ||
(
!empty($this->tempStore->get('oauth2state')) &&
$state !== $this->tempStore->get('oauth2state')
)
) {
$this->tempStore->delete('oauth2state');
$this->tempStore->delete('oauth2redirect');
throw new \OAuthException(sprintf(
'Invalid OAuth state. Current state: %s ; Expected state: %s.',
$state,
$this->tempStore->get('oauth2state')
));
}
try {
// Try to get an access token using the authorization code grant.
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $request->query->get('code'),
]);
// We have an access token, which we may use in authenticated
// requests against the service provider's API.
$this->tempStore->set('access_token', $accessToken->getToken());
$this->tempStore->set('refresh_token', $accessToken->getRefreshToken());
$this->tempStore->set('expiration', $accessToken->getExpires());
// Using the access token,
// we may look up details about the resource owner.
/** @var \Drupal\docusign_signature\Auth\DocuSignResourceOwner $user */
$user = $provider->getResourceOwner($accessToken);
$accountInfo = $user->getAccountInfo();
$this->tempStore->set('user', $user);
$this->tempStore->set('account_id', $accountInfo['account_id']);
$this->tempStore->set('base_path', $accountInfo['base_uri'] . self::BASE_URI_SUFFIX);
}
catch (IdentityProviderException $e) {
// Failed to get the access token or user details.
\Drupal::messenger()->addError($e->getMessage());
}
// Redirect user to original page.
if (!isset($redirectUrl)) {
$redirectUrl = $this->tempStore->get('oauth2redirect');
}
return parent::authCallback($redirectUrl);
}
/**
* Get OAUTH provider.
*
* @return \Drupal\docusign_signature\Auth\DocuSign
* The DocuSign OAuth provider.
*/
private function getOauthProvider(): DocuSign {
return new DocuSign([
'clientId' => $this->config->get('client_id'),
'clientSecret' => $this->config->get('client_secret'),
'redirectUri' => Url::fromRoute('docusign_signature.callback.oauth', [], ['absolute' => TRUE])->toString(TRUE)->getGeneratedUrl(),
'authorizationServer' => $this->getAuthorizationUrl(),
'allowSilentAuth' => $this->config->get('allow_silent_authentication'),
]);
}
/**
* {@inheritdoc}
*/
public function login(): RedirectResponse {
$provider = $this->getOauthProvider();
$authorizationUrl = $provider->getAuthorizationUrl();
// Get the state generated for you and store it to the session.
$this->tempStore->set('oauth2state', $provider->getState());
$this->tempStore->set(
'oauth2redirect',
Url::fromRoute('<current>')
->toString(TRUE)
->getGeneratedUrl()
);
// Redirect the user to the authorization URL.
return new TrustedRedirectResponse($authorizationUrl);
}
}
