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