I am trying to implement user auth using the Shopify Headless customer account API in an Astro app with auth-astro. I have set up my Shopify store with the Headless app properly, I can log in, maintain a session and it all works nicely. What I can’t work out how to do is log out properly. Even if I use the built-in Log out method of AuthJS, the Shopify account remains logged in.
The correct method to log out of Shopify is a GET request to their endpoint with the ID token as a URL parameter as documented here: https://shopify.dev/docs/api/customer#step-logging-out
The AuthJS docs don’t have much on how to edit the logout functions. It simply clears your local session data and redirects you to a local URL. https://authjs.dev/getting-started/session-management/login
My auth.config.mjs file looks like the following and this is where I guess I need to make the change.
import { defineConfig } from 'auth-astro';
const CUSTOMER_ACCOUNT = `#graphql
query {
customer {
id
emailAddress {
emailAddress
}
firstName
lastName
}
}`;
export default defineConfig({
providers: [
{
id: 'shopify',
name: 'Shopify',
type: 'oauth',
clientId: import.meta.env.PUBLIC_SHOPIFY_CUSTOMER_ACCESS_TOKEN,
clientSecret: import.meta.env.PRIVATE_SHOPIFY_CUSTOMER_ACCESS_TOKEN,
issuer: `https://shopify.com/authentication/${import.meta.env.PUBLIC_SHOPIFY_STORE_ID}`,
authorization: {
url: `https://shopify.com/${import.meta.env.PUBLIC_SHOPIFY_STORE_ID}/auth/oauth/authorize`,
params: {
scope: 'openid email https://api.customers.com/auth/customer.graphql',
client_id: import.meta.env.PUBLIC_SHOPIFY_CUSTOMER_ACCESS_TOKEN,
response_type: 'code',
redirect_uri: `${import.meta.env.SITE_URL}/api/auth/callback/shopify`,
},
},
token: {
url: `https://shopify.com/authentication/${import.meta.env.PUBLIC_SHOPIFY_STORE_ID}/oauth/token`,
params: {
client_id: import.meta.env.PUBLIC_SHOPIFY_CUSTOMER_ACCESS_TOKEN,
client_secret: import.meta.env.PRIVATE_SHOPIFY_CUSTOMER_ACCESS_TOKEN,
grant_type: 'authorization_code',
redirect_uri: `${import.meta.env.SITE_URL}/api/auth/callback/shopify`,
},
},
userinfo: {
url: `https://shopify.com/${import.meta.env.PUBLIC_SHOPIFY_STORE_ID}/account/customer/api/${import.meta.env.SHOPIFY_APP_VERSION}/graphql`,
async request(context) {
const response = await fetch(this.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `${context.tokens.access_token}`,
},
body: JSON.stringify({
operationName: 'GetCustomer',
query: CUSTOMER_ACCOUNT,
variables: {},
}),
});
const { data } = await response.json();
const { customer } = data;
customer.id_token = context.tokens.id_token;
return customer;
}
},
profile(data) {
return {
id: data.id,
firstName: data.firstName,
lastName: data.lastName,
email: data.emailAddress.emailAddress,
id_token: data.id_token,
};
}
},
],
callbacks: {
async session({ session, token }) {
if (token) {
session.user = token.user;
}
return session;
},
async jwt({ token, user, profile }) {
if (user) {
token.user = user;
}
if (profile && profile.id) {
token.graphId = profile.id;
}
return token;
},
},
});
I considered using events, but they’re asynchronous and therefore a get request to the Shopify logout URL wouldn’t be appropriate as the users browser has to navigate to the URL.
I tried redirecting back from Shopify to the logout route of AuthJS but because it’s a GET and not a POST request it renders a logout confirmation page.
My best guess is to use the redirect callback in AuthJS somehow https://authjs.dev/reference/core/types#redirect perhaps by inspecting the local URL and redirecting to Shopify as the users session ends. I am not sure how I could retrieve the users id_token from the session in that instance.
Any suggestions would be greatly appreciated.