class SalesforceJWTPlugin in Salesforce Suite 8.4
Same name and namespace in other branches
- 5.0.x modules/salesforce_jwt/src/Plugin/SalesforceAuthProvider/SalesforceJWTPlugin.php \Drupal\salesforce_jwt\Plugin\SalesforceAuthProvider\SalesforceJWTPlugin
JWT Oauth plugin.
Plugin annotation
@Plugin(
id = "jwt",
label = @Translation("Salesforce JWT OAuth"),
credentials_class = "\Drupal\salesforce_jwt\Consumer\JWTCredentials"
)
Hierarchy
- class \Drupal\salesforce\SalesforceAuthProviderPluginBase extends \OAuth\OAuth2\Service\Salesforce implements SalesforceAuthProviderInterface uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\salesforce_jwt\Plugin\SalesforceAuthProvider\SalesforceJWTPlugin
Expanded class hierarchy of SalesforceJWTPlugin
File
- modules/
salesforce_jwt/ src/ Plugin/ SalesforceAuthProvider/ SalesforceJWTPlugin.php, line 25
Namespace
Drupal\salesforce_jwt\Plugin\SalesforceAuthProviderView source
class SalesforceJWTPlugin extends SalesforceAuthProviderPluginBase {
/**
* The credentials for this auth plugin.
*
* @var \Drupal\salesforce_jwt\Consumer\JWTCredentials
*/
protected $credentials;
/**
* Key repository service.
*
* @var \Drupal\key\KeyRepositoryInterface
*/
protected $keyRepository;
/**
* SalesforceAuthServiceBase constructor.
*
* @param array $configuration
* Configuration.
* @param string $plugin_id
* Plugin id.
* @param mixed $plugin_definition
* Plugin definition.
* @param \OAuth\Common\Http\Client\ClientInterface $httpClient
* Http client wrapper.
* @param \Drupal\salesforce\Storage\SalesforceAuthTokenStorageInterface $storage
* Token storage.
* @param \Drupal\key\KeyRepositoryInterface $keyRepository
* Key repository.
*
* @throws \OAuth\OAuth2\Service\Exception\InvalidScopeException
* On error.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $httpClient, SalesforceAuthTokenStorageInterface $storage, KeyRepositoryInterface $keyRepository) {
$this->keyRepository = $keyRepository;
parent::__construct($configuration, $plugin_id, $plugin_definition, $httpClient, $storage);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$configuration = array_merge(self::defaultConfiguration(), $configuration);
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('salesforce.http_client_wrapper'), $container
->get('salesforce.auth_token_storage'), $container
->get('key.repository'));
}
/**
* {@inheritdoc}
*/
public static function defaultConfiguration() {
$defaults = parent::defaultConfiguration();
return array_merge($defaults, [
'login_user' => '',
'encrypt_key' => '',
]);
}
/**
* {@inheritdoc}
*/
public function getLoginUrl() {
return $this
->getCredentials()
->getLoginUrl();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
if (!$this->keyRepository
->getKeyNamesAsOptions([
'type' => 'authentication',
])) {
$this
->messenger()
->addError($this
->t('Please <a href="@href">add an authentication key</a> before creating a JWT Auth provider.', [
'@href' => Url::fromRoute('entity.key.add_form')
->toString(),
]));
return $form;
}
$form['consumer_key'] = [
'#title' => $this
->t('Salesforce consumer key'),
'#type' => 'textfield',
'#description' => $this
->t('Consumer key of the Salesforce remote application you want to grant access to'),
'#required' => TRUE,
'#default_value' => $this
->getCredentials()
->getConsumerKey(),
];
$form['login_user'] = [
'#title' => $this
->t('Salesforce login user'),
'#type' => 'textfield',
'#description' => $this
->t('User account to issue token to'),
'#required' => TRUE,
'#default_value' => $this
->getCredentials()
->getLoginUser(),
];
$form['login_url'] = [
'#title' => $this
->t('Login URL'),
'#type' => 'textfield',
'#default_value' => $this
->getCredentials()
->getLoginUrl(),
'#description' => $this
->t('Enter a login URL, either https://login.salesforce.com or https://test.salesforce.com.'),
'#required' => TRUE,
];
// Can't use key-select input type here because its #process method doesn't
// fire on ajax, so the list is empty. DERP.
$form['encrypt_key'] = [
'#title' => 'Private Key',
'#type' => 'select',
'#empty_option' => $this
->t('- Select -'),
'#options' => $this->keyRepository
->getKeyNamesAsOptions([
'type' => 'authentication',
]),
'#required' => TRUE,
'#default_value' => $this
->getCredentials()
->getKeyId(),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::validateConfigurationForm($form, $form_state);
if (empty($form_state
->getValue('provider_settings')) && $form_state
->getValue('provider_settings') == self::defaultConfiguration()) {
$form_state
->setError($form, $this
->t('Please fill in JWT provider settings.'));
return;
}
$this
->setConfiguration($form_state
->getValue('provider_settings'));
// Force new credentials from form input, rather than storage.
unset($this->credentials);
try {
// Bootstrap here by setting ID to provide a key to token storage.
$this->id = $form_state
->getValue('id');
$this
->requestAccessToken($this
->generateAssertion());
} catch (\Exception $e) {
$form_state
->setError($form, $e
->getMessage());
}
}
/**
* Overrides AbstractService::requestAccessToken for jwt-bearer flow.
*
* @param string $assertion
* The JWT assertion.
* @param string $state
* Not used.
*
* @return \OAuth\Common\Token\TokenInterface
* Access Token.
*
* @throws \OAuth\Common\Http\Exception\TokenResponseException
*/
public function requestAccessToken($assertion, $state = NULL) {
$data = [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $assertion,
];
$response = $this->httpClient
->retrieveResponse(new Uri($this
->getLoginUrl() . static::AUTH_TOKEN_PATH), $data, [
'Content-Type' => 'application/x-www-form-urlencoded',
]);
$token = $this
->parseAccessTokenResponse($response);
$this->storage
->storeAccessToken($this
->service(), $token);
$this
->refreshIdentity($token);
return $token;
}
/**
* {@inheritDoc}
*/
public function refreshAccessToken(TokenInterface $token) {
$token = $this
->requestAccessToken($this
->generateAssertion());
$this
->refreshIdentity($token);
return $token;
}
/**
* Returns a JWT Assertion to authenticate.
*
* @return string
* JWT Assertion.
*/
protected function generateAssertion() {
$key = $this->keyRepository
->getKey($this
->getCredentials()
->getKeyId())
->getKeyValue();
$token = $this
->generateAssertionClaim();
return JWT::encode($token, $key, 'RS256');
}
/**
* Returns a JSON encoded JWT Claim.
*
* @return array
* The claim array.
*/
protected function generateAssertionClaim() {
$cred = $this
->getCredentials();
return [
'iss' => $cred
->getConsumerKey(),
'sub' => $cred
->getLoginUser(),
'aud' => $cred
->getLoginUrl(),
'exp' => \Drupal::time()
->getCurrentTime() + 60,
];
}
/**
* {@inheritdoc}
*/
public function getPluginDefinition() {
$definition = parent::getPluginDefinition();
if ($this->configuration['encrypt_key'] && ($key = $this->keyRepository
->getKey($this->configuration['encrypt_key']))) {
$definition['config_dependencies']['config'][] = $key
->getConfigDependencyName();
}
return $definition;
}
}