I have a custom service and in the custom service, I want to generate a new Bearer token for the current user ( it's logged in) with simple_oauth module. in its documentation is has not mentioned how can I generate new a new token for current logged in user. So, how can I generate a new Bearer token for current logged in user?
2 Answers
I assume you need an access token for some API call, so to have it generated automatically when you call some API method in your service.
I usually go with the following set up:
- Install kamermans/guzzle-oauth2-subscriber with composer
- Define config
my_module.auth.yml
and import it
client_id: test
client_secret: test
base_uri: 'https://some-external-service/auth/token'
- Create the following services/factories
my_module.services.yml
services:
my_module.handler_stack:
class: GuzzleHttp\HandlerStack
factory: ['GuzzleHttp\HandlerStack', 'create']
calls:
- [push, ['@my_module.oauth2_middleware']]
my_module.client_factory:
class: Drupal\my_module\Client\ClientFactory
arguments: ['@config.factory']
my_module.oauth2_middleware_factory:
class: Drupal\my_module\Auth\OAuth2MiddlewareFactory
arguments: ['@config.factory']
my_module.oauth2_middleware.client:
class: GuzzleHttp\Client
factory: 'my_module.client_factory:createClient'
arguments:
- 'my_module.auth'
my_module.oauth2_middleware:
class: kamermans\OAuth2\OAuth2Middleware
factory: 'my_module.oauth2_middleware_factory:createMiddleware'
arguments:
- '@my_module.oauth2_middleware.client'
- 'my_module.auth'
- Define your middleware factory
OAuth2MiddlewareFactory.php
<?php
namespace Drupal\my_module\Auth;
use Drupal\Core\Config\ConfigFactoryInterface;
use GuzzleHttp\ClientInterface;
use kamermans\OAuth2\GrantType\ClientCredentials;
use kamermans\OAuth2\OAuth2Middleware;
/**
* Factory for OAuth2 Guzzle middleware, configured from configuration objects.
*
* @package Drupal\my_module\Auth
*/
class OAuth2MiddlewareFactory {
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
private $configFactory;
/**
* OAuth2MiddlewareFactory constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration factory to use.
*/
public function __construct(ConfigFactoryInterface $configFactory) {
$this->configFactory = $configFactory;
}
/**
* Creates an OAuth2 Guzzle Middleware.
*
* @param \GuzzleHttp\ClientInterface $client
* The guzzle HTTP client to use for obtaining client credentials.
* @param string $configName
* Name of the configuration object to use.
*
* @return \kamermans\OAuth2\OAuth2Middleware
* The Guzzle Oauth2 middleware.
*/
public function createMiddleware(ClientInterface $client, string $configName): OAuth2Middleware {
$configuration = $this->configFactory->get($configName);
$reauth_config = [
'client_id' => $configuration->get('client_id'),
'client_secret' => $configuration->get('client_secret'),
'state' => time(),
];
if ($configuration->get('scope')) {
$reauth_config['scope'] = $configuration->get('scope');
}
$grant_type = new ClientCredentials($client, $reauth_config);
return new OAuth2Middleware($grant_type);
}
}
- Define client factory
ClientFactory.php
<?php
namespace Drupal\my_module\Client;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
/**
* Factory for Guzzle HTTP clients, configured from configuration objects.
*
* @package Drupal\my_module\Client
*/
class ClientFactory {
/**
* The configuration object factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* ClientFactory constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration object factory.
*/
public function __construct(ConfigFactoryInterface $configFactory) {
$this->configFactory = $configFactory;
}
/**
* Creates a Guzzle HTTP client.
*
* @param string $configName
* Name of the configuration object to use.
* @param array $clientConfig
* Additional configuration settings for the Guzzle HTTP client.
*
* @return \GuzzleHttp\Client
* A configured Guzzle HTTP client.
*/
public function createClient(string $configName, array $clientConfig = []): Client {
$config = $this->configFactory->get($configName);
$prepared_config = $this->prepareClientConfig($config, $clientConfig);
return new Client(
$prepared_config
);
}
/**
* Prepares the configuration of the Guzzle HTTP client.
*
* Priority of the configuration:
* 1. configuration in $config, limited to certain common settings
* 2. configuration in $clientConfig passed in via the service container
* 3. defaults set in this method.
*
* @param \Drupal\Core\Config\ImmutableConfig $config
* The configuration object to use.
* @param array $clientConfig
* Additional configuration settings for the Guzzle HTTP client.
*
* @return array
* The client configuration.
*/
protected function prepareClientConfig(ImmutableConfig $config, array $clientConfig = []): array {
$prepared_config = $clientConfig;
$prepared_config['base_uri'] = $config->get('base_uri');
$defaults = [
RequestOptions::TIMEOUT => $clientConfig[RequestOptions::TIMEOUT] ?? 10,
RequestOptions::CONNECT_TIMEOUT => $clientConfig[RequestOptions::TIMEOUT] ?? 10,
];
foreach (array_keys($defaults) as $option) {
$prepared_config[$option] = $config->get($option) ?? $defaults[$option];
}
return $prepared_config;
}
}
- Define your client by using the factory in
my_module.services.yml
my_module.my_service.client:
class: GuzzleHttp\Client
factory: 'my_module.client_factory:createClient'
arguments:
- 'my_module.my_service'
- auth: oauth
handler: '@my_module.handler_stack'
where my_module.my_service.yml
is
base_uri: 'https://some-external-service/a-service-namespace/'
- Create your service that will trigger API by using the client you created by the factory earlier
my_module.service.region:
class: Drupal\my_module\Service\MyService
arguments: ['@my_module.my_service.client']
and this is MyService.php
<?php
namespace Drupal\my_module\Service\Region;
use GuzzleHttp\ClientInterface;
/**
* API client for my service.
*
* @package Drupal\my_module\Service
*/
class MyService {
/**
* A guzzle HTTP client.
*
* @var \GuzzleHttp\ClientInterface
*/
private $client;
/**
* MyService constructor.
*
* @param \GuzzleHttp\ClientInterface $client
* A Guzzle HTTP client.
*/
public function __construct(ClientInterface $client) {
$this->client = $client;
}
/**
* Finds something from the my service.
*
* @param string $langCode
* The language code.
* @param string $postalCode
* The postal code.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function findSomething(string $langCode, string $value): Region {
$response = $this->client->request('GET', 'my-service-uri/find',
[
'headers' => [
'Accept' => 'application/json',
'Accept-Language' => $langCode,
],
'query' => [
'value' => $value,
],
]
);
$json = $response->getBody()->getContents();
// Do something here, you may use serializer to deserialize the content
// here with the custom defined model or some other fancy stuff.
}
}
This might too much, but you may find some useful code
POST request to /oauth/token generates a new token (don't forget to add proper body params)
You can also use a refresh token to generate a new access token by using grant_type 'refresh_token'
-
thanks for you attention. yes, I knew this solution but I'm looking for a better solution. :)– YuseferiCommented May 12, 2020 at 17:40
-
additionally, the grant_type is password and I don't have all users' passwords. so it's better to use another solution.– YuseferiCommented May 12, 2020 at 18:10
-
password grant type is now deprecated in the latest version of the module and is no longer available to generate tokens Commented Nov 21, 2023 at 23:49