Created
February 23, 2019 07:35
-
-
Save devdarren7/30430a0e9481ccc858f60c6d4146891d to your computer and use it in GitHub Desktop.
shopify authentication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var express = require('express'); | |
| var router = express.Router(); | |
| var app = express(); | |
| const nonce = require('nonce')(); | |
| const cookie = require('cookie'); | |
| const forwardingAddress = "https://bonitoco.herokuapp.com/"; | |
| var apiSecret = process.env.SHOPIFY_API_SECRET; | |
| var apiKey = process.env.SHOPIFY_API_KEY ; | |
| const scopes = 'read_products'; | |
| router.get('/shopify', function (req, res, next) { | |
| const shop = req.query.shop; | |
| if (shop) { | |
| const state = nonce(); | |
| const redirectUri = forwardingAddress + '/shopify/callback'; | |
| const installUrl = 'https://' + shop + | |
| '/admin/oauth/authorize?client_id=' + apiKey + | |
| '&scope=' + scopes + | |
| '&state=' + state + | |
| '&redirect_uri=' + redirectUri; | |
| res.cookie('state', state); | |
| res.redirect(installUrl); | |
| } else { | |
| return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request'); | |
| } | |
| }); | |
| router.get('/shopify/callback', (req, res) => { | |
| const { shop, hmac, code, state } = req.query; | |
| const stateCookie = cookie.parse(req.headers.cookie).state; | |
| if (state !== stateCookie) { | |
| return res.status(403).send('Request origin cannot be verified'); | |
| } | |
| if (shop && hmac && code) { | |
| // DONE: Validate request is from Shopify | |
| const map = Object.assign({}, req.query); | |
| delete map['signature']; | |
| delete map['hmac']; | |
| const message = querystring.stringify(map); | |
| const providedHmac = Buffer.from(hmac, 'utf-8'); | |
| const generatedHash = Buffer.from( | |
| crypto | |
| .createHmac('sha256', apiSecret) | |
| .update(message) | |
| .digest('hex'), | |
| 'utf-8' | |
| ); | |
| let hashEquals = false; | |
| try { | |
| hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac) | |
| } catch (e) { | |
| hashEquals = false; | |
| }; | |
| if (!hashEquals) { | |
| return res.status(400).send('HMAC validation failed'); | |
| } | |
| // DONE: Exchange temporary code for a permanent access token | |
| const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token'; | |
| const accessTokenPayload = { | |
| client_id: apiKey, | |
| client_secret: apiSecret, | |
| code, | |
| }; | |
| request.post(accessTokenRequestUrl, { json: accessTokenPayload }) | |
| .then((accessTokenResponse) => { | |
| const accessToken = accessTokenResponse.access_token; | |
| // DONE: Use access token to make API call to 'shop' endpoint | |
| const shopRequestUrl = 'https://' + shop + '/admin/shop.json'; | |
| const shopRequestHeaders = { | |
| 'X-Shopify-Access-Token': accessToken, | |
| }; | |
| request.get(shopRequestUrl, { headers: shopRequestHeaders }) | |
| .then((shopResponse) => { | |
| // res.status(200).end(shopResponse); | |
| }) | |
| .catch((error) => { | |
| res.status(error.statusCode).send(error.error.error_description); | |
| }); | |
| }) | |
| .catch((error) => { | |
| res.status(error.statusCode).send(error.error.error_description); | |
| }); | |
| } else { | |
| res.status(400).send('Required parameters missing'); | |
| } | |
| }); | |
| module.exports = router; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment