Authentication & Session
To authenticate customers with the Recharge JavaScript SDK we will create a utility that validates the customer's session and logs into Recharge as needed and stores the Recharge Session via the rechargeSession.server
module we previously setup.
Query & Login Utility Function
Create a rechargeUtil.ts
module where we can add a couple utility functions.
loginRecharge
- function encapsulating logic for logging into Recharge and getting a RechargeSessionrechargeQueryWrapper
to help with data fetching (which is covered in the next section). This helper function handles any needed login retries or/and error handlingclearSession
- function to clear the RechargeSession
- JavaScript
- TypeScript
/app/lib/rechargeUtils.js
import { loginWithShopifyCustomerAccount } from '@rechargeapps/storefront-client';
import { json } from '@shopify/remix-oxygen';
const RECHARGE_SESSION_KEY = 'rechargeSession';
// loginHelper function
async function loginRecharge(context) {
const customerAccessToken = await context.customerAccount.getAccessToken();
const rechargeSession = await loginWithShopifyCustomerAccount(customerAccessToken);
if (rechargeSession) {
context.rechargeSession.set(RECHARGE_SESSION_KEY, rechargeSession);
} else {
// this should match your catch boundary
throw json('No session created', { status: 400 });
}
return rechargeSession;
}
// helper function for data fetching
export async function rechargeQueryWrapper(rechargeFn, context) {
let rechargeSession = context.rechargeSession.get(RECHARGE_SESSION_KEY);
if (!rechargeSession) {
rechargeSession = await loginRecharge(context);
}
try {
return await rechargeFn(rechargeSession);
} catch (e) {
try {
if (e?.status === 401) {
// handle auth error, login again and retry request
rechargeSession = await loginRecharge(context);
return await rechargeFn(rechargeSession);
}
// this should match your catch boundary
throw json(e.message, { status: e?.status });
} catch (error) {
// this should match your catch boundary
throw json(e.message, { status: e?.status });
}
}
}
// helper function to clear session
export function clearSession(session) {
session.unset(RECHARGE_SESSION_KEY);
}
/app/lib/rechargeUtils.ts
import { loginWithShopifyCustomerAccount } from '@rechargeapps/storefront-client';
import { json } from '@shopify/remix-oxygen';
import type { Session } from '@rechargeapps/storefront-client';
import type { AppLoadContext } from '@shopify/remix-oxygen';
import type { RechargeSession } from './rechargeSession.server';
const RECHARGE_SESSION_KEY = 'rechargeSession';
// loginHelper function
async function loginRecharge(context: AppLoadContext) {
const customerAccessToken = await context.customerAccount.getAccessToken();
const rechargeSession = await loginWithShopifyCustomerAccount(customerAccessToken);
if (rechargeSession) {
context.rechargeSession.set(RECHARGE_SESSION_KEY, rechargeSession);
} else {
// this should match your catch boundary
throw json('No session created', { status: 400 });
}
return rechargeSession;
}
// helper function for data fetching
export async function rechargeQueryWrapper<T>(
rechargeFn: (session: Session) => Promise<T>,
context: AppLoadContext
): Promise<T> {
let rechargeSession = context.rechargeSession.get(RECHARGE_SESSION_KEY);
if (!rechargeSession) {
rechargeSession = await loginRecharge(context);
}
try {
return await rechargeFn(rechargeSession);
} catch (e: any) {
try {
if (e?.status === 401) {
// handle auth error, login again and retry request
rechargeSession = await loginRecharge(context);
return await rechargeFn(rechargeSession);
}
// this should match your catch boundary
throw json(e.message, { status: e?.status });
} catch (error) {
// this should match your catch boundary
throw json(e.message, { status: e?.status });
}
}
}
// helper function to clear session
export function clearSession(session: RechargeSession) {
session.unset(RECHARGE_SESSION_KEY);
}
Handle logout
Update logout function to clear the rechargeSession
.
- JavaScript
- TypeScript
/app/routes/account_.logout.jsx
export async function action({ context }) {
clearSession(context.rechargeSession);
return context.customerAccount.logout();
}
/app/routes/account_.logout.tsx
export async function action({ context }: ActionFunctionArgs) {
clearSession(context.rechargeSession);
return context.customerAccount.logout();
}