Skip to content

Commit 5b40ea3

Browse files
committed
Separate AuthHelper class for authentication purpose
1 parent 3ec576d commit 5b40ea3

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed

lib/AuthHelper.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* @author Tareq Mahmood <tareqtms@yahoo.com>
5+
* Created at: 8/27/16 10:58 AM UTC+06:00
6+
*/
7+
8+
namespace PHPShopify;
9+
10+
11+
use PHPShopify\Exception\SdkException;
12+
13+
class AuthHelper
14+
{
15+
/**
16+
* Return the admin url, based on a given shop url
17+
*
18+
* @param string $shopUrl
19+
* @param string $apiKey
20+
* @param string $apiPassword
21+
* @return string
22+
*/
23+
public static function getAdminUrl($shopUrl, $apiKey = null, $apiPassword = null)
24+
{
25+
//Remove https:// and trailing slash (if provided)
26+
$shopUrl = preg_replace('#^https?://|/$#', '', $shopUrl);
27+
28+
if($apiKey && $apiPassword) {
29+
$adminUrl = "https://$apiKey:$apiPassword@$shopUrl/admin/";
30+
} else {
31+
$adminUrl = "https://$shopUrl/admin/";
32+
}
33+
return $adminUrl;
34+
}
35+
36+
/**
37+
* Get the url of the current page
38+
*
39+
* @return string
40+
*/
41+
public static function getCurrentUrl()
42+
{
43+
if (isset($_SERVER['HTTPS']) &&
44+
($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
45+
isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
46+
$_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
47+
$protocol = 'https';
48+
}
49+
else {
50+
$protocol = 'http';
51+
}
52+
53+
return "$protocol://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
54+
}
55+
56+
/**
57+
* Verify if the request is made from shopify using hmac hash value
58+
*
59+
* @throws SdkException if SharedSecret is not provided or hmac is not found in the url parameters
60+
*
61+
* @return bool
62+
*/
63+
public static function verifyShopifyRequest()
64+
{
65+
$data = $_GET;
66+
67+
if(!isset(ShopifyClient::$config['SharedSecret'])) {
68+
throw new SdkException("Please provide SharedSecret while configuring the SDK client.");
69+
}
70+
71+
$sharedSecret = ShopifyClient::$config['SharedSecret'];
72+
73+
//Get the hmac and remove it from array
74+
if (isset($data['hmac'])) {
75+
$hmac = $data['hmac'];
76+
unset($data['hmac']);
77+
} else {
78+
throw new SdkException("HMAC value not found in url parameters.");
79+
}
80+
//signature validation is deprecated
81+
if (isset($data['signature'])) {
82+
unset($data['signature']);
83+
}
84+
//Create data string for the remaining url parameters
85+
$dataString = http_build_query($data);
86+
87+
$realHmac = hash_hmac('sha256', $dataString, $sharedSecret);
88+
89+
//hash the values before comparing (to prevent time attack)
90+
if(md5($realHmac) === md5($hmac)) {
91+
return true;
92+
} else {
93+
return false;
94+
}
95+
}
96+
97+
/**
98+
* Redirect the user to the authorization page to allow the app access to the shop
99+
*
100+
* @see https://help.shopify.com/api/guides/authentication/oauth#scopes For allowed scopes
101+
*
102+
* @param string|string[] $scopes Scopes required by app
103+
* @param string $redirectUrl
104+
*
105+
* @throws SdkException if required configuration is not provided in $config
106+
*
107+
* @return void
108+
*/
109+
public static function createAuthRequest($scopes, $redirectUrl = null)
110+
{
111+
$config = ShopifyClient::$config;
112+
113+
if(!isset($config['ShopUrl']) || !isset($config['ApiKey'])) {
114+
throw new SdkException("ShopUrl and ApiKey are required for authentication request. Please check SDK configuration!");
115+
}
116+
117+
if (!$redirectUrl) {
118+
if(!isset($config['SharedSecret'])) {
119+
throw new SdkException("SharedSecret is required for getting access token. Please check SDK configuration!");
120+
}
121+
122+
//If redirect url is the same as this url, then need to check for access token when redirected back from shopify
123+
if(isset($_GET['code'])) {
124+
return self::getAccessToken($config);
125+
} else {
126+
$redirectUrl = self::getCurrentUrl();
127+
}
128+
}
129+
130+
if (is_array($scopes)) {
131+
$scopes = join(',', $scopes);
132+
}
133+
$authUrl = $config['ApiUrl'] . 'oauth/authorize?client_id=' . $config['ApiKey'] . '&redirect_uri=' . $redirectUrl . "&scope=$scopes";
134+
135+
header("Location: $authUrl");
136+
}
137+
138+
/**
139+
* Get Access token for the API
140+
* Call this when being redirected from shopify page ( to the $redirectUrl) after authentication
141+
*
142+
* @throws SdkException if SharedSecret or ApiKey is missing in SDK configuration
143+
*
144+
* @return string
145+
*/
146+
public static function getAccessToken()
147+
{
148+
$config = ShopifyClient::$config;
149+
150+
if(!isset($config['SharedSecret']) || !isset($config['ApiKey'])) {
151+
throw new SdkException("SharedSecret and ApiKey are required for getting access token. Please check SDK configuration!");
152+
}
153+
154+
if(self::verifyShopifyRequest()) {
155+
$data = array(
156+
'client_id' => $config['ApiKey'],
157+
'client_secret' => $config['SharedSecret'],
158+
'code' => $_GET['code'],
159+
);
160+
161+
$response = HttpRequestJson::post($config['ApiUrl'] . 'oauth/access_token', $data);
162+
163+
return isset($response['access_token']) ? $response['access_token'] : null;
164+
}
165+
}
166+
}

0 commit comments

Comments
 (0)