-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2-legged OAuth2 using the client_credentials #257
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -25,8 +25,7 @@ then copy the Client ID and Client Secret to the application that will be using | |||
## Authorization | ||||
|
||||
### Obtaining an access token | ||||
The first step is to obtain authorization. Mautic supports OAuth 1.0a and OAuth 2 however it is up to the administrator | ||||
to decide which is enabled. Thus it is best to have a configuration option within your project for the administrator | ||||
The first step is to obtain authorization. Mautic supports OAuth 2. Thus it is best to have a configuration option within your project for the administrator | ||||
to choose what method should be used by your code. | ||||
|
||||
```php | ||||
|
@@ -46,7 +45,6 @@ $callback = ''; | |||
// ApiAuth->newAuth() will accept an array of Auth settings | ||||
$settings = [ | ||||
'baseUrl' => '', // Base URL of the Mautic instance | ||||
'version' => 'OAuth2', // Version of the OAuth can be OAuth2 or OAuth1a. OAuth2 is the default value. | ||||
'clientKey' => '', // Client/Consumer key from Mautic | ||||
'clientSecret' => '', // Client/Consumer secret key from Mautic | ||||
'callback' => '', // Redirect URI/Callback URI for this script | ||||
|
@@ -55,7 +53,6 @@ $settings = [ | |||
/* | ||||
// If you already have the access token, et al, pass them in as well to prevent the need for reauthorization | ||||
$settings['accessToken'] = $accessToken; | ||||
$settings['accessTokenSecret'] = $accessTokenSecret; //for OAuth1.0a | ||||
$settings['accessTokenExpires'] = $accessTokenExpires; //UNIX timestamp | ||||
$settings['refreshToken'] = $refreshToken; | ||||
*/ | ||||
|
@@ -76,7 +73,6 @@ try { | |||
// refresh token | ||||
|
||||
// $accessTokenData will have the following keys: | ||||
// For OAuth1.0a: access_token, access_token_secret, expires | ||||
// For OAuth2: access_token, expires, token_type, refresh_token | ||||
|
||||
if ($auth->accessTokenUpdated()) { | ||||
|
@@ -90,6 +86,41 @@ try { | |||
} | ||||
``` | ||||
|
||||
|
||||
### Using 2-legged OAuth2 using Client Credentials | ||||
|
||||
The Client Credentials grant is used when applications request an access token to access their own resources, not on behalf of a user. | ||||
|
||||
```php | ||||
<?php | ||||
|
||||
// Bootup the Composer autoloader | ||||
include __DIR__ . '/vendor/autoload.php'; | ||||
|
||||
use Mautic\Auth\ApiAuth; | ||||
|
||||
$settings = [ | ||||
'AuthMethod' => 'TwoLeggedOAuth2', | ||||
'clientKey' => '', | ||||
'clientSecret' => '', | ||||
'baseUrl' => '', | ||||
]; | ||||
|
||||
// $settings['accessToken'] = 'your stored access token'; | ||||
|
||||
|
||||
$initAuth = new ApiAuth(); | ||||
$auth = $initAuth->newAuth($settings, $settings['AuthMethod']); | ||||
|
||||
if (!isset($settings['accessToken'])) { | ||||
// store it for one hour and use it in $settings above | ||||
$accessToken = $auth->getAccessToken(); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the regular Could we have the same method for You could store the expiration time just like it was done in api-library/lib/Auth/OAuth.php Line 679 in 9087dde
|
||||
} | ||||
|
||||
// Nothing else to do ... It's ready to use. | ||||
// Just pass the auth object to the API context you are creating. | ||||
``` | ||||
|
||||
### Using Basic Authentication Instead | ||||
Instead of messing around with OAuth, you may simply elect to use BasicAuth instead. | ||||
|
||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?php | ||
|
||
/* | ||
* @copyright 2021 Mautic Contributors. All rights reserved | ||
* @author Mautic, Inc. | ||
* | ||
* @link https://mautic.org | ||
* | ||
* @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html | ||
*/ | ||
|
||
namespace Mautic\Auth; | ||
|
||
use Mautic\Exception\RequiredParameterMissingException; | ||
|
||
class TwoLeggedOAuth2 extends AbstractAuth | ||
{ | ||
/** | ||
* Password associated with Username. | ||
* | ||
* @var string | ||
*/ | ||
private $clientSecret; | ||
|
||
/** | ||
* Username or email, basically the Login Identifier. | ||
* | ||
* @var string | ||
*/ | ||
private $clientKey; | ||
|
||
/** | ||
* Access token returned by OAuth server. | ||
* | ||
* @var string | ||
*/ | ||
protected $_access_token; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $baseurl; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $_access_token_url; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function isAuthorized() | ||
{ | ||
return !empty($this->clientKey) && !empty($this->clientSecret); | ||
} | ||
|
||
/** | ||
* @param string $baseUrl | ||
* @param string $clientKey The username to use for Authentication *Required* | ||
* @param string $clientSecret The Password to use *Required* | ||
* | ||
* @throws RequiredParameterMissingException | ||
*/ | ||
public function setup($baseUrl, $clientKey, $clientSecret, $accessToken = null) | ||
{ | ||
// we MUST have the username and password. No Blanks allowed! | ||
// | ||
// remove blanks else Empty doesn't work | ||
$clientKey = trim($clientKey); | ||
$clientSecret = trim($clientSecret); | ||
|
||
if (empty($clientKey) || empty($clientSecret)) { | ||
//Throw exception if the required parameters were not found | ||
$this->log('parameters did not include clientkey and/or clientSecret'); | ||
throw new RequiredParameterMissingException('One or more required parameters was not supplied. Both clientKey and clientSecret required!'); | ||
} | ||
|
||
$this->baseurl = $baseUrl; | ||
$this->clientKey = $clientKey; | ||
$this->clientSecret = $clientSecret; | ||
$this->_access_token = $accessToken; | ||
|
||
if (!$this->_access_token_url) { | ||
$this->_access_token_url = $baseUrl.'/oauth/v2/token'; | ||
} | ||
} | ||
|
||
/** | ||
* @param $url | ||
* @param $method | ||
* | ||
* @return array | ||
*/ | ||
protected function prepareRequest($url, array $headers, array $parameters, $method, array $settings) | ||
{ | ||
if (null !== $this->_access_token) { | ||
$headers = array_merge($headers, ['Authorization: Bearer '.$this->_access_token]); | ||
} | ||
|
||
return [$headers, $parameters]; | ||
} | ||
|
||
public function getAccessToken(): string | ||
{ | ||
$parameters = [ | ||
'client_id' => $this->clientKey, | ||
'client_secret' => $this->clientSecret, | ||
'grant_type' => 'client_credentials', | ||
]; | ||
$accessTokenData = $this->makeRequest($this->_access_token_url, $parameters, 'POST'); | ||
//store access token data however you want | ||
$this->_access_token = $accessTokenData['access_token'] ?? null; | ||
|
||
return $this->_access_token; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The token isn't always valid for one hour. Mautic users can set the access token lifetime under API settings:
... in which case
/oauth/v2/token
will return anexpires_in
of, for example, 7200 seconds (2 hrs) instead of 3600 seconds (1 hr):