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 handling
NOTE In this example rechargeQueryWrapper
can update the session object. Make sure you are committing the session (in case it changes) after calling the rechargeQueryWrapper
function in the response from your loader
/action
.
- 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 });
}
}
}
/app/lib/rechargeUtils.ts
import { loginWithShopifyCustomerAccount } from '@rechargeapps/storefront-client';
import { json } from '@shopify/remix-oxygen';
import type { Session as RechargeSession } from '@rechargeapps/storefront-client';
import type { AppLoadContext } from '@shopify/remix-oxygen';
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: RechargeSession) => 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 });
}
}
}
Clear RechargeSession
If you ever want to remove the Recharge Session you can call destroy
on it. Again make sure you commit
your changes using await context.rechargeSession.commit()
. The Recharge Session cookie will automatically expire after 55 minutes.
- JavaScript
- TypeScript
await context.rechargeSession.destroy();
await context.rechargeSession.destroy();