next-auth
next-auth copied to clipboard
Shopify Provider
Description 📓
I was implementing a Shopify Provider so that customers can sign in/up with their Shopify Store! More on Shopify OAuth flow: https://shopify.dev/apps/auth/oauth/getting-started
Step 1: Authorise a Shop
https://{shop}.myshopify.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}&state={nonce}&grant_options[]={access_mode}
Shopify responds with an URL like this::
https://example.org/some/redirect/uri?code={authorization_code}&hmac=da9d83c171400a41f8db91a950508985&host={base64_encoded_hostname}&shop={shop_origin}&state={nonce}×tamp=1409617544
Step 2: Get an Access Token
POST https://{shop}.myshopify.com/admin/oauth/access_token?client_id={API_KEY}&client_secret={API_SECRET_KEY}&code={authorization_code}
Parameter | Description |
---|---|
client_id | The API key for the app, as defined in the Partner Dashboard. |
client_secret | The API secret key for the app, as defined in the Partner Dashboard. |
code | The authorization code provided in the redirect. (Received in Step 1) |
Step 3: Get Shop Configuration
GET https://${shop}/admin/api/${apiVersion}/shop.json
Headers
X-Shopify-Access-Token
| The access token received in Step 2
More on that mather: https://shopify.dev/api/admin-rest/2022-07/resources/shop
@balazsorban44 I left some comments on the commit I would like some help!
@aimproxy Did you have any luck setting up Shopify as a provider?
Just chiming in to see if any progress was made here. Seems like you can't dynamically setup a subdomain for a given provider's authorizationUrl
.
@jimjeffers I was able to implement this using advanced initialization
[...nextauth].js
:
import NextAuth from 'next-auth';
export default async function auth(req, res) {
const { shopifyShopName } = req.query;
// Do whatever you want here, before the request is passed down to `NextAuth`
return await NextAuth(req, res, {
providers: [
{
id: 'shopify',
name: 'Shopify',
type: 'oauth',
version: '2.0',
clientId: process.env.SHOPIFY_CLIENT_ID,
clientSecret: process.env.SHOPIFY_CLIENT_SECRET,
authorization: {
url: `https://${shopifyShopName}.myshopify.com/admin/oauth/authorize`,
params: {
scope: 'read_orders, read_all_orders',
},
},
}
// ...add more providers here
],
});
}
Calling signIn
:
signIn(
"shopify",
{
redirect: false,
callbackUrl: "...",
},
{ shopifyShopName: "some-cool-shop-name },
);
@foobarnes yeah thats it, will you submit a PR? Have you tested it?
@aimproxy I'm still waiting on approval from Shopify for the permissions, but it does correctly route to the authorization url.
I may be wrong, but I don't think this requires a PR. This is how to address @jimjeffers's comment.
Just adding a iteration to the solution that provides the ability to use the Shopify OAuth along side other providers.
[...nextauth]/route.ts
import { authOptions } from "@/lib/auth";
import NextAuth from "next-auth/next";
import { NextRequest } from "next/server";
const handler = async (req: NextRequest, res: any) => {
const shopifyShopName = req.nextUrl.searchParams.get("shopifyShopName") || "";
authOptions.providers[
authOptions.providers.length - 1
// @ts-ignore
].authorization.url = `https://${shopifyShopName}/admin/oauth/authorize`;
// @ts-ignore
return await NextAuth(req, res, authOptions);
};
export { handler as GET, handler as POST };
lib/auth.ts
export const authOptions = {
providers: [
CredentialsProvider({ ... }),
GoogleProvider({ ... }),
{
id: "shopify",
name: "Shopify",
type: "oauth",
version: "2.0",
clientId: process.env.SHOPIFY_CLIENT_ID,
clientSecret: process.env.SHOPIFY_CLIENT_SECRET,
authorization: {
params: {
scope:
"read_products, read_orders, read_all_orders, read_customers, <or whichever scopes you are interested in>",
redirect_uri: `${process.env.NEXTAUTH_URL}/api/auth/provider/shopify`,
},
},
},
],
callbacks: { ... },
pages: { ... },
};
For context, my solution provides a redirect to an exposed API under /api/auth/provider/shopify
which handles some post processing of the access token after retrieving it from Shopify.