Maintaining the Customer Session
Session State
We’ve now seen a clear workflow for authenticating customers with the BigCommerce GraphQL Storefront API, as well as for passing a customer context in subsequent requests. To effectively use these workflows together, however, requires a reliable way to track a customer session within your storefront application.
How you decide to track a logged-in customer’s session is ultimately dependent on the needs of your application and the details of its architecture. But any solution for session state should keep certain key needs in mind:
- Session information should be stored and transmitted securely and should not be exposed to the end user unnecessarily.
- Treat any publicly exposed session identifier - such as a session cookie - as untrusted, just like any other user input. Good customer authentication is not effective if malicious users can circumvent it by manipulating their session information. For example, a session cookie consisting only of the customer ID in plaintext is wholly insufficient, as a user could modify such a cookie to easily impersonate a different customer.
- Make your session state management more secure by expiring sessions after a reasonable period of time and by forcing customers to re-authenticate when initiating sensitive actions.
It’s worth noting that session state is not specific to interacting with BigCommerce but is a topic common to all web applications, and so our discussion of the details will be relatively brief.
Traditional Session Management
Tracking a user’s session is hardly a new consideration for the web, and traditional languages or frameworks for full-stack applications have had built-in mechanisms for session state for decades.
In a traditional web application, all user session details are stored securely on the web server - in a database, in the filesystem, or in an in-memory cache service - and tied to a random session identifier stored in the user’s browser, usually in a cookie. If your storefront application uses such a traditional full-stack architecture, then typical session management is a natural choice. The details of your authenticated BigCommerce customer can be stored using built-in session functions, with no special effort required.
The key to traditional session management, however, is the availability of server storage. The frameworks and toolsets most popular in modern, composable frontends intentionally avoid relying on such architecture. If you’re building your storefront with a “server-less” frontend framework like Next.js, Nuxt or Gatsby, you must implement a solution for session state without a database or a server-side filesystem.
Json Web Tokens
Json Web Tokens (JWTs) are an open industry standard for transmitting claims between two parties, and they essentially answer the question we’ve arrived at: How can information be stored and transmitted in public, but still trusted?
A JWT is an encoded version of information represented in simple Json format. A key defining feature is a digital signature, which a recipient can use to verify the source and integrity of the Json data.
A typical JWT has three parts, as shown in this example string:
{header}is a Base64-encoded object with meta information about the token, including the hashing algorithm used for the signature.{payload}is the Base64-encoded version of the main Json object containing the data or “claims” being transmitted.{signature}is a string resulting from hashing or signing the contents of the header and payload using a secret or key pair. The secret or private key is known only to the source and recipient and is never transmitted publicly.
There is much more to learn about Json Web Tokens, including standard conventions about the types of claims often expressed in them.
In our scenario, JWTs provide a solution for securely tracking a customer’s authenticated status. After initial login, a JWT can be created with the necessary data (the customer access token), then stored in a cookie or browser local storage.
It’s important to understand that a typical JWT is encoded but not encrypted. The information contained in the payload can easily be decoded and read. But while a malicious user can tamper with the payload - for example, decoding a cookie value, changing the customer information, and re-encoding it - the resulting corrupted token will fail verification since the information no longer matches the signature. The signature cannot be reproduced without the secret.
While you can certainly also encrypt the contents of a JWT, consider carefully whether the data is sensitive enough to warrant the computational cost, and whether such sensitive data should be stored at all.
A Note on Logging Out
You’ll observe that the GraphQL Storefront API also includes a logout mutation.
Example Mutation:
This mutation de-authenticates the customer’s BigCommerce storefront session. In a Stencil client-side context, this means actually signing the customer out.
When tracking a customer’s session separately in your own front-end app, you will likely log them out simply by unsetting or destroying the appropriate session token. However, the logout mutation also destroys the session in the BigCommerce back-end, so it’s a best practice to also call this mutation.