Magento 2 API Authentication: Token, OAuth, Session Authentication
In Magento, developers are allowed to define web API resources and their permissions in a configuration file which is webapi.xml
.
Before web API calls can be made, you have to authenticate your identity and obtain all the necessary permissions also called authorization to access the API resource. With authentication, Magento will be able to identify the user type of caller. And based on the user’s access rights, the resource accessibility of API calls is determined.
Besides, the resources list that you can access will depend on your user type. Because all customers have the same permissions, the same resources accessible. The preceding statement is also correct with guest users. A unique set of permissions that are configured in the Magento Admin can be provided to each administrator or integration user. All the permissions which are required to access a particular resource are configured in the webapi.xml
file. The below table will list all the resources that can be accessed by each user type:
User type | Accessible resources |
---|---|
Administrator or Integration | Resources for which administrators or integrators are authorized. |
Customer | Resources which have anonymous or self permission |
Guest user | Resources that have anonymous permission |
In today post, I’m going to provide you the basic information about three Magento 2 API Authentications which are Token, OAuth and Session Authentication.
Magento 2 API Authentication
Token authentication
In order to make a web API call from a client, for example, mobile application, an access token need to be supplied on the call. The token acts as an electronic key which allows you to access the API.
The table below describes all the types of access tokens which Magento issues:
Token type | Description | Default lifetime |
---|---|---|
Integration | The merchant will determine the Magento resources that the integration can access. | Until it is manually revoked. |
Admin | The merchant will determine the Magento resources that an admin user can access. | 4 hours |
Customer | Resources with anonymous or self permission are accessible. These settings cannot be edited by Merchants. |
1 hour |
Integration tokens
When integration is created and activated, a consumer key, consumer secret, access token, and access token secret are generated by Magento. However, the token-based authentication only requires the access token.
To generate an access token, following the below steps:
- Step 1: Firstly, log in to your Admin, then go to
System > Extensions > Integrations
to open the Integrations page. - Step 2: Next, to display the New Integration page, click
Add New Integration
- Step 3: In the
Name
field, enter a unique name for the integration. Then, in theYour Password field
, enter your admin password. With the remaining fields, you can leave it blanks. - Step 4: Click the API tab. And choose the Magento resources which the integration can access. You are allowed to choose all resources or a custom list.
- Step 5: To save your changes and return to the Integrations page, click on the
Save
button. - Step 6: In the next step, click on the
Activate link
in the grid which corresponds to the integration that has just been created. - Step 7: Finally, click on the
Allow
button. After you have clicked the button, a dialog which is similar to the following one will be displayed.
!
You can use the access token in all calls which is made on behalf of the integration.
Admin and customer access tokens
A separate token service is provided for both administrators and customers by Magento. When a token is requested from one of these services, a unique access token will be returned in exchange for the username and password for a Magento account.
Guest user are allowed to access resources that are configured with the anonymous permission level. The framework of these users can not authenticate via existing authentication mechanisms. A guest user can specify a token in a web API call for a resource with anonymous permission.
Here are some calls that can be used to get an authentication token:
Request | REST | SOAP |
---|---|---|
Get admin token | POST /V1/integration/admin/token |
integrationAdminTokenServiceV1 |
Get customer token | POST /V1/integration/customer/token |
integrationCustomerTokenServiceV1 |
With the majority of web API calls, to prove your identity, this token is supplied in the Authorization
request header with the Bearer
HTTP authorization scheme. By default, 4 hours is the valid time of an admin token, while a customer token is only valid for 1 hour. These values can be changed by choosing Stores > Settings > Configuration > Services > OAuth > Access Token Expiration
.
All the tokens which are expired will be removed by a cron job that runs on an hourly basis.
Request a token
An access token request includes three elements:
Component | Specifies |
---|---|
Endpoint | It is a combination of the server which meets the request, the service, and the resource against. For instance, in the endpoint: POST <host>/rest/<store_code>/V1/integration/customer/token . magento.host/index.php/ is the server, rest is the web service, /V1/integration/customer/token is the resource |
Content type | It is the content type of the request body. You can set this value to Content-Type:application/json or Content-Type:application/xml . |
Credentials | The username and password for an account on Magento. For these credentials to be specified in a JSON request body, add the code which is similar to the following in the call: {"username":"<USER-NAME>;", "password":"<PASSWORD>"} . And for these credentials to be specified in XML, add the code which is similar to the following in the call: <login><username>customer1@example.com</username><password>customer1pw</password></login> |
Examples
The image below display a token request for the admin account which uses a REST client:
!
In the example below, the curl
command is used to request a token for a customer account:
curl -X POST "https://magento.host/index.php/rest/V1/integration/customer/token" \
-H "Content-Type:application/json" \
-d "{"username":"customer1@example.com", "password":"customer1pw"}"
And down here is an example which uses XML to makes the same request for a customer account token:
curl -X POST "http://magento.vg/index.php/rest/V1/integration/customer/token" \
-H "Content-Type:application/xml" \
-d "<login><username>customer1@example.com</username><password>customer1pw</password></login>"
Authentication token response
A response body with the token will be returned if the request is successful. And here is how it looks like:
asdf3hjklp5iuytre
Use token in the Web API request
The authentication token in the header has to be included in all the web APIs which call accesses a resource that requires a permission level higher than anonymous. In order for this to be done, an HTTP is specified in the following format:
Authorization: Bearer <authentication token>
Admin access
Any resources for which they are authorized can be accessed by admins.
For instance, here is how you make a web API call with an admin token:
curl -X GET "http://magento.ll/index.php/rest/V1/customers/2" -H "Authorization: Bearer vbnf3hjklp5iuytre"
Customer access
Only resources with self permissions can be accessed by customers.
For instance, here is how you make a web API call with a customer token:
curl -X GET "http://magento.ll/index.php/rest/V1/customers/me" -H "Authorization: Bearer asdf3hjklp5iuytre"
OAuth authentication
The OAuth authentication in Magento is developed based on OAuth 1.0a, which is an open standard for secure API authentication. OAuth is considered as a token-passing mechanism which allows a system to decide which external applications gain access to internal data without any user IDs or passwords be revealed or stored.
In Magento, integration is a third-party extension which uses OAuth for authentication. The resources which the extension can access are defined by the integration. The extension can access all resources or a customized subset of resources.
As the procedure of registering the integration proceeds, tokens which the extension required for authentication are created by Magento. Firstly, a request token will be created. This is a short-lived token and has to be exchanged for access tokens which are long-lived ones and would not expire if the merchant doesn’t revoke access to the extension.
The below diagram will show the process of OAuth authentication:
!
-
Step 1 - Create an integration: This is the step where an integration will be created from Admin. A consumer key and secret are generated by Mageplaza.
-
Step 2 - Activate the integration: The process starts when the integration is activated. The OAuth consumer key, secret, an OAuth verifier, and the store URL are sent to the external application through HTTPS post to the page defined which is in the
Callback Link
field in Admin. You can view Activate integration for more details. -
Step 3 - Process activation information: The activation information which is received in step 2 must be stored in the integrator. These parameters will then be used to ask for tokens.
-
Step 4 - Call the application’s login page: The page defined is called in the
Identity Link
field in Admin. -
Step 5 - Merchant logs in to the external application: Once the login is successful, the application will return to the location which is specified in the call. The login page will be dismissed.
-
Step 6 - Ask for a request token:
POST /oauth/token/request
REST API are used to ask for a request token. The consumer key and other information are included in theAuthorization
header. View Get an access token for more details about this token request. -
Step 7 - Send the request token: A request token and request token secret are returned by Magento.
-
Step 8 - Ask for an access token:
POST /oauth/token/access REST API
are used to asking for an access token. The request token and other information are included in theAuthorization
header. View Get access token for more details about this token request. -
Step 9 - Magento sends the access token: An access token and access token secret are returned if this request is successful.
-
Step 10 - The application can access Magento resources: All the request which are sent to Magento have to use the full set of request parameters that are in
Authorization
header. View Access the web APIs for more information.
Activate integration
The integration has to be configured by selecting System > Extensions > Integrations
. A callback URL and identity link URL are included in the configuration. While the callback URL specifies the place where OAuth credentials can be sent using OAuth for token exchange, the identity link identifies the third-party application’s login page which is integrating with Magento.
A merchant can select Save and Activate
when the integration is created or he/ she can click on the Activate
button against an integration which is previously saved from the Integration grid.
Once the integration is created, a consumer key and a consumer secret will be generated by Magento.
Activating the integration would help submit the credentials to the endpoint specified when the Integration is created.
The following attributes will be included in an HTTP POST from Magento to the Integration endpoint:
store_base_url
For instance,http://my-magento-store.com/
.oauth_verifier
oauth_consumer_key
oauth_consumer_secret
The oauth_consumer_key
key is used to get a request token and the oauth_verifier
is used to get an access token.
OAuth handshake details
Completing the OAuth handshake’s process requires you have to
This procedure is also known as a 2-legged OAuth handshake.
Get request token
A request token is a temporary token which is used to exchange for an access token. To get a request token from Magento, you can use the following API:
POST /oauth/token/request
These request parameters have to be included in the Authorization
header in the call:
Parameter | Description |
---|---|
oauth_consumer_key |
It is generated when the integration is created. |
oauth_signature_method |
It is the signature method’s name which is used to sign the request. It must be the value HMAC-SHA1. |
oauth_signature |
It is a generated value (signature) |
oauth_nonce |
It is a random value which is generated by the application in a unique way. |
oauth_timestamp |
It is a positive integer which is expressed in the number of seconds since January 1, 1970 00:00:00 GMT. |
oauth_version |
It is the version of the OAuth. |
The following fields are contained in the response:
oauth_token
: The token is used when an access token is requested.oauth_token_secret
: A secret value which establishes the token’s ownership.
A response which is valid will look smilar to the following one:
oauth_token=4cqw0r7vo0s5goyyqnjb72sqj3vxwr0h&oauth_token_secret=rig3x3j5a9z5j6d4ubjwyf9f1l21itrr
Get access token
The request token has to be exchanged for an access token. The following API can be used to get an access token from Magento:
POST /oauth/token/access
These request parameters have to be included in the Authorization
header in the call:
Parameter | Description |
---|---|
oauth_consumer_key |
It is the consumer key value which is retrieved after the integration is registered. |
oauth_nonce |
It is a random value which is generated by the application in a unique way. |
oauth_signature_method |
It is the signature method’s name which is used to sign the request. It must be the value HMAC-SHA1. |
oauth_signature |
It is a generated value (signature) |
oauth_timestamp |
It is a positive integer which is expressed in the number of seconds since January 1, 1970 00:00:00 GMT. |
oauth_version |
It is the version of the OAuth. |
oauth_token |
It is the request token which is obtained in Get request token. |
oauth_verifier |
It is the verification code which is tied to the consumer as well as request token. When you activate the integration, this code will be sent as a part of the initial POST operation. |
Here is how a response which is valid look like:
oauth_token=0lnuajnuzeei2o8xcddii5us77xnb6v0&oauth_token_secret=1c6d2hycnir5ygf39fycs6zhtaagx8pd
These two fields will be included in the response:
oauth_token
: The access token which gives access to resources that are protected.oauth_token_secret
: The secret which is associated with the access token.
Access web APIs
After authorizing the Integration to make API calls, third-party extensions which register as Integrations in Magento can invoke Magento web APIs using the access token.
In order for the access token to be used to make web API calls:
GET /rest/V1/products/1234
These request parameters have to be included in the Authorization
request header in the call:
oauth_consumer_key
- The customer key value which is provided after the extension is registered.oauth_nonce
- A random value which is uniquely generated by the application.oauth_signature_method
- The signature method’s name which is used to sign the request.HMAC-SHA1
,RSA-SHA1
, andPLAINTEXT
are the valid values.oauth_signature
- A generated value (signature).oauth_timestamp
- A positive integer which is expressed in the number of seconds since January 1, 1970 00:00:00 GMT.oauth_token
- The access token, value which is obtained in Get access token.
OAuth signature
The signature is included in all OAuth handshake requests and Web API requests as a part of Authorization header. Following are how it’s generated:
A set of URL-encoded attributes and parameters are concatenated to build the signature base string.
These following attributes and parameters are concatenated by using the ampersand and character.
HTTP method
URL
oauth_nonce
oauth_signature_method
oauth_timestamp
oauth_version
oauth_consumer_key
oauth_token
The signature can only be generated by using the HMAC-SHA1 signature method. The signing key is the consumer secret and token secret’s concatenated values which are separated by the ampersand and character (ASCII code 38). Parameter encoding has to be used in order to encode each value.
Example of OAuth token exchange
The scripts which are provided in this post simulate the OAuth 1.0a token exchange flow of Magento 2. These scripts can be dropped under the document root directory of your Magento application. This would help these scripts be exposed as endpoints which the Magento application can interact with to imitate the token exchange.
Below is the OAuth 1.0a token exchange flow:
- Step 1: Login your Magento Admin, then go to
System > Extensions > Integrations
- Step 2: Select
Add New Integration
- Step 3: Fill in all fields which in the Integration Info tab including:
Name
: Enter the name fo the IntegrationCallback URL
: http://your_app_host/endpoint.phpIdentity link URL
: http://your_app_host/login.php- Add permissions as desired on API tab
- Step 4: From the drop-down menu, choose the
Save and Activate
option - Step 5: In this step, a pop-up window will be displayed which confirms the API permissions. Click on the
Allow
button. The credentials will be posted toendpoint.php
. In this step, you should also see a pop-up for identity linking step which opens the script fromlogin.php
. - Step 6: Click on
Login
. Thechecklogin.php
script will be called. The posted credentials are used to complete the token exchange. - Step 7: When the token exchange success, the user will be redirected to the Integrations grid. And the integration which is created recently should be in the Active state.
- Step 8: You can check the Integration Details on the Integration Info tab by clicking the edit icon. All the credentials which can be used to make an authenticated API request using OAuth 1.0 should be shown here.
checklogin.php
<?php
require './vendor/autoload.php';
$consumerKey = $_REQUEST['oauth_consumer_key'];
$callback = $_REQUEST['callback_url'];
session_id('test');
session_start();
/** Use $consumerKey to retrieve the following data in case it was stored in DB when received at "endpoint.php" */
if ($consumerKey !== $_SESSION['oauth_consumer_key']) {
throw new \Exception("Consumer keys received on different requests do not match.");
}
$consumerSecret = $_SESSION['oauth_consumer_secret'];
$magentoBaseUrl = rtrim($_SESSION['store_base_url'], '/');
$oauthVerifier = $_SESSION['oauth_verifier'];
define('TESTS_BASE_URL', $magentoBaseUrl);
$credentials = new \OAuth\Common\Consumer\Credentials($consumerKey, $consumerSecret, $magentoBaseUrl);
$oAuthClient = new OauthClient($credentials);
$requestToken = $oAuthClient->requestRequestToken();
$accessToken = $oAuthClient->requestAccessToken(
$requestToken->getRequestToken(),
$oauthVerifier,
$requestToken->getRequestTokenSecret()
);
header("location: $callback");
endpoint.php
<?php
session_id('test');
session_start();
// If this data is stored in the DB, oauth_consumer_key can be used as ID to retrieve this data later in "checklogin.php"
// For simplicity of this sample, it is stored in session
$_SESSION['oauth_consumer_key'] = $_POST['oauth_consumer_key'];
$_SESSION['oauth_consumer_secret'] = $_POST['oauth_consumer_secret'];
$_SESSION['store_base_url'] = $_POST['store_base_url'];
$_SESSION['oauth_verifier'] = $_POST['oauth_verifier'];
session_write_close();
header("HTTP/1.0 200 OK");
echo "Response";
login.php
<?php
$consumerKey = $_REQUEST['oauth_consumer_key'];
$callbackUrl = urlencode(urldecode($_REQUEST['success_call_back']));
echo <<<HTML
<table width="300" border="0" align="center" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC">
<tr>
<form name="form1" method="post" action="checklogin.php?oauth_consumer_key={$consumerKey}&callback_url={$callbackUrl}">
<td>
<table width="100%" border="0" cellpadding="3" cellspacing="1" bgcolor="#FFFFFF">
<tr>
<td colspan="3"><strong>Integrations Login</strong></td>
</tr>
<tr>
<td width="78">Username</td>
<td width="6">:</td>
<td width="294"><input name="myusername" type="text" id="myusername"></td>
</tr>
<tr>
<td>Password</td>
<td>:</td>
<td><input name="mypassword" type="text" id="mypassword"></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td><input type="submit" name="Submit" value="Login"></td>
</tr>
</table>
</td>
</form>
</tr>
</table>
HTML;
OauthClient.php
In these example, you can change the instances of http://magento.host
to a valid base URL.
<?php
use OAuth\Common\Consumer\Credentials;
use OAuth\Common\Http\Client\ClientInterface;
use OAuth\Common\Http\Exception\TokenResponseException;
use OAuth\Common\Http\Uri\Uri;
use OAuth\Common\Http\Uri\UriInterface;
use OAuth\Common\Storage\TokenStorageInterface;
use OAuth\OAuth1\Service\AbstractService;
use OAuth\OAuth1\Signature\SignatureInterface;
use OAuth\OAuth1\Token\StdOAuth1Token;
use OAuth\OAuth1\Token\TokenInterface;
class OauthClient extends AbstractService
{
/** @var string|null */
protected $_oauthVerifier = null;
public function __construct(
Credentials $credentials,
ClientInterface $httpClient = null,
TokenStorageInterface $storage = null,
SignatureInterface $signature = null,
UriInterface $baseApiUri = null
) {
if (!isset($httpClient)) {
$httpClient = new \OAuth\Common\Http\Client\StreamClient();
}
if (!isset($storage)) {
$storage = new \OAuth\Common\Storage\Session();
}
if (!isset($signature)) {
$signature = new \OAuth\OAuth1\Signature\Signature($credentials);
}
parent::__construct($credentials, $httpClient, $storage, $signature, $baseApiUri);
}
/**
* @return UriInterface
*/
public function getRequestTokenEndpoint()
{
return new Uri('http://magento.host/oauth/token/request');
}
/**
* Returns the authorization API endpoint.
*
* @throws \OAuth\Common\Exception\Exception
*/
public function getAuthorizationEndpoint()
{
throw new \OAuth\Common\Exception\Exception(
'Magento REST API is 2-legged. Current operation is not available.'
);
}
/**
* Returns the access token API endpoint.
*
* @return UriInterface
*/
public function getAccessTokenEndpoint()
{
return new Uri('http://magento.host/oauth/token/access');
}
/**
* Parses the access token response and returns a TokenInterface.
*
* @param string $responseBody
* @return TokenInterface
*/
protected function parseAccessTokenResponse($responseBody)
{
return $this->_parseToken($responseBody);
}
/**
* Parses the request token response and returns a TokenInterface.
*
* @param string $responseBody
* @return TokenInterface
* @throws TokenResponseException
*/
protected function parseRequestTokenResponse($responseBody)
{
$data = $this->_parseResponseBody($responseBody);
if (isset($data['oauth_verifier'])) {
$this->_oauthVerifier = $data['oauth_verifier'];
}
return $this->_parseToken($responseBody);
}
/**
* Parse response body and create oAuth token object based on parameters provided.
*
* @param string $responseBody
* @return StdOAuth1Token
* @throws TokenResponseException
*/
protected function _parseToken($responseBody)
{
$data = $this->_parseResponseBody($responseBody);
$token = new StdOAuth1Token();
$token->setRequestToken($data['oauth_token']);
$token->setRequestTokenSecret($data['oauth_token_secret']);
$token->setAccessToken($data['oauth_token']);
$token->setAccessTokenSecret($data['oauth_token_secret']);
$token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES);
unset($data['oauth_token'], $data['oauth_token_secret']);
$token->setExtraParams($data);
return $token;
}
/**
* Parse response body and return data in array.
*
* @param string $responseBody
* @return array
* @throws \OAuth\Common\Http\Exception\TokenResponseException
*/
protected function _parseResponseBody($responseBody)
{
if (!is_string($responseBody)) {
throw new TokenResponseException("Response body is expected to be a string.");
}
parse_str($responseBody, $data);
if (null === $data || !is_array($data)) {
throw new TokenResponseException('Unable to parse response.');
} elseif (isset($data['error'])) {
throw new TokenResponseException("Error occurred: '{$data['error']}'");
}
return $data;
}
/**
* @override to fix since parent implementation from lib not sending the oauth_verifier when requesting access token
* Builds the authorization header for an authenticated API request
*
* @param string $method
* @param UriInterface $uri the uri the request is headed
* @param \OAuth\OAuth1\Token\TokenInterface $token
* @param $bodyParams array
* @return string
*/
protected function buildAuthorizationHeaderForAPIRequest(
$method,
UriInterface $uri,
TokenInterface $token,
$bodyParams = null
) {
$this->signature->setTokenSecret($token->getAccessTokenSecret());
$parameters = $this->getBasicAuthorizationHeaderInfo();
if (isset($parameters['oauth_callback'])) {
unset($parameters['oauth_callback']);
}
$parameters = array_merge($parameters, ['oauth_token' => $token->getAccessToken()]);
$parameters = array_merge($parameters, $bodyParams);
$parameters['oauth_signature'] = $this->signature->getSignature($uri, $parameters, $method);
$authorizationHeader = 'OAuth ';
$delimiter = '';
foreach ($parameters as $key => $value) {
$authorizationHeader .= $delimiter . rawurlencode($key) . '="' . rawurlencode($value) . '"';
$delimiter = ', ';
}
return $authorizationHeader;
}
}
Session authentication
Similar to customers who login to the Magento storefront with their credentials, admins also need admin credentials to login to their Magento Admin.
With Magento web API framework, your logged-in session information will be used to verify your identity and approve access to the requested resource.
Resources which are configured can be accessed by customers who have anonymous
or self
permission in the webapi.xml
configuration file.
Admin will be able to access resources which are assigned to their Magento Admin profile.
For instance, if a customer login to the Magento storefront and the self
API is invoked by the JavaScript widget, the details for the logged-in customer will be fetched: GET /rest/V1/customers/me
Likewise, if an admin login to the Magento storefront and the JavaScript widget Magento_Customer::group API
, details for the logged-in admin will be fetched. The identity of the admin user will be established according to logged-in session information and authorizes access to the Magento_Customer::group resource
.
Conclusion
Above I have just provided you the information about API Authentication: Token, OAuth, Session Authentication in details. I hope this article is useful. If you have any questions or new ideas, feel free to leave a comment below.
Enjoyed the tutorial? Spread it to your friends!