You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
title: "Configuring GraphQL Client for User Session"
3
+
description: "A step-by-step guide on how to configure your GraphQL client to handle user sessions, authentication, and more when working with WooGraphQL and WPGraphQL."
4
+
keywords: "WooGraphQL, WPGraphQL, WooCommerce, GraphQL, user session, authentication, configuration, client"
5
+
author: "Geoff Taylor"
6
+
---
7
+
1
8
# Configuring a GraphQL Client for WooCommerce User Session Management
2
9
3
10
In this comprehensive guide, we'll walk you through the process of configuring a GraphQL client to manage user sessions and credentials when working with WooGraphQL. By following the steps outlined in this tutorial, you'll learn how to create a GraphQL client that maintains a valid WooCommerce session in the `woocommerce_sessions` DB table. This knowledge will enable you to build robust applications that interact smoothly with WooCommerce while providing a seamless experience for your users and shortening development time.
4
11
5
12
By properly handling the session token, you can implement session pass-off functionality, allowing you to fallback on the cart page, my-account page, or any other page living in WordPress that relies on user sessions. Note that implementing the session pass-off functionality is out of the scope of this guide. So, let's dive in and explore the intricacies of setting up a GraphQL client that effectively manages user sessions for your e-commerce store!
6
13
7
-
When using WooGraphQL cart and customer functionality, there are certain prerequisites. A WooGraphQL session token, distributed by the QL Session Handler, must be passed as an HTTP header with the name `woocommerce-session`, prefixed with `Session`. This header should be included in all session data-altering mutations. Note that the required name `woocommerce-session` can be changed using WordPress filters.
14
+
## Sending the `woocommerce-session` HTTP request header
15
+
16
+
When using WooGraphQL cart and customer functionality, there are certain prerequisites. A WooGraphQL session token, distributed by the QL Session Handler, must be passed as an HTTP header with the name `woocommerce-session`, prefixed with `Session `. This header should be included in all session data-altering mutations. Note that the required name `woocommerce-session` can be changed using WordPress filters.
8
17
9
18
For simple requests using `fetch`, this is quite easy to implement. Here's an example of a WooGraphQL request executed with `fetch`, performing a cart query and passing the woocommerce-session header with a value of `Session ${sessionToken}`. The `sessionToken` is read from `localStorage`.
10
19
@@ -41,7 +50,9 @@ fetch(endpoint, {
41
50
.then((data) =>console.log(data));
42
51
```
43
52
44
-
However, if you're using a library or framework like Apollo, configuring a middleware layer is required, which can be confusing if not explained or demonstrated effectively. In this guide, we'll walk you through setting up the Apollo Client and its middleware to work with WooGraphQL.
53
+
This works for simple streamlined applications that don't rely heavily on cart functionality. Note that this example also does not retrieve the updated token from the `woocommerce-session` HTTP response header.
54
+
55
+
And if you're using a library or framework like Apollo, configuring middleware and afterware layers are required, which makes things more confusing if not explained or demonstrated effectively. In this guide, we'll walk you through setting up the Apollo Client and its middleware/afterware to work with WooGraphQL.
45
56
46
57
## Creating the Apollo Client instance
47
58
@@ -56,12 +67,15 @@ const client = new ApolloClient({
56
67
link:from([
57
68
createSessionLink(),
58
69
createErrorLink(),
70
+
createUpdateLink(),
59
71
newHttpLink({ uri: endpoint }),
60
72
]),
61
73
cache:newInMemoryCache(),
62
74
});
63
75
```
64
76
77
+
In the example you see the creation of our `client`. It include middleware/afterware callbacks managed by the `ApolloLink` class. For those not familiar with it, the `ApolloLink` class is allowed you to customize the flow of data by defining you networks behavior as a chain of link object. I'm stating this so you know the order of the callbacks is also important and it will be understood why as we define this callbacks themselves.
78
+
65
79
## Defining the `createSessionLink` function
66
80
67
81
Next, define the `createSessionLink` function as follows:
@@ -83,8 +97,22 @@ function createSessionLink() {
83
97
return {};
84
98
});
85
99
}
100
+
101
+
//...rest of code
86
102
```
87
103
104
+
And that's our callback for applying the our session token to each request made through our client. Note that I am using the shorthand method of importing the `setContext` function, however most examples you will find will use the `ApolloLink` class directly to define the link object.
And this works fine too, but is more verbose and kinda overkill if your just make a stateless link like we are here. `Stateless` links are middleware callbacks that don't care to know anything about the context of the operation and just does it own thing regardless of what operation Apollo is about to execute.
115
+
88
116
## About the environment variables
89
117
90
118
Before we dive into the guide, it's important to note that the `process.env.*` variables used throughout the tutorial are simply string values stored in an `.env` file and loaded using the [**dotenv**](https://www.npmjs.com/package/dotenv) package. As a reader, you can replace these variables with any values that suit your needs.
@@ -99,12 +127,25 @@ AUTH_KEY_TIMEOUT=30000
99
127
GRAPHQL_ENDPOINT=http://woographql.local/graphql
100
128
```
101
129
102
-
## Defining the `getSessionToken`and `fetchSessionToken` functions
130
+
With a .env file created you will be ready to move on to what's next, which is defining the `getSessionToken`function.
103
131
104
-
Here are the `getSessionToken` and `fetchSessionToken` functions:
let sessionToken =localStorage.getItem(process.env.SESSION_TOKEN_LS_KEY as string);
137
+
if (!sessionToken || forceFetch) {
138
+
sessionToken =awaitfetchSessionToken();
139
+
}
140
+
return sessionToken;
141
+
}
142
+
```
143
+
144
+
The function is rather simple. It attempt to retrieve the `sessionToken` from `localStorage`, and if that fails or `forceFetch` is passed it fetches a new one using `fetchSessionToken()`. And `fetchSessionToken` is defined.
105
145
106
146
```javascript
107
147
import { GraphQLClient } from'graphql-request';
148
+
import { GetCartDocument } from'./graphql'
108
149
109
150
// Session Token Management.
110
151
asyncfunctionfetchSessionToken() {
@@ -127,18 +168,11 @@ async function fetchSessionToken() {
let sessionToken =localStorage.getItem(process.env.SESSION_TOKEN_LS_KEY as string);
132
-
if (!sessionToken || forceFetch) {
133
-
sessionToken =awaitfetchSessionToken();
134
-
}
135
-
return sessionToken;
136
-
}
137
-
```
171
+
// ...rest of code
138
172
139
-
Defining the `GetCartDocument`
173
+
```
140
174
141
-
Here's the `GetCartDocument`:
175
+
For this example this works for most case but typically you want the obscure the retrieval of the token and the endpoint from the end-user, especially if dealing with authenticated users. There are a number of a ways to do this like serverless functions or Next.js API routes and they should be doing exactly what is done here retrieve the sessionToken and/or user authentication tokens and nothing else. See the `GetCartDocument` below in `./graphql`.
It's highly recommended to retrieve the session token outside of the Apollo Client for better control of its value. To ensure no request gets sent without a session token, we must define an error link to capture failed queries caused by an invalid or expired session token, delete the current session, and retrieve a new one. Here's the `createErrorLink` function:
190
+
By separating retrieval of the `sessionToken` it also enables better control of its value. We can take this further by ensuring no request gets sent without a session token or with an invalid session token. This is where our `createErrorLink`error handling middleware and `createUpdateLink` token updating afterware come into play. First `createErrorLink`, to capture failed queries caused by an invalid or expired session tokens, deleting the currently stored session token, and retrieve a new one.
@@ -202,14 +236,93 @@ function createErrorLink() {
202
236
});
203
237
});
204
238
}
205
-
return message;
206
239
});
207
240
}
208
241
return observable;
209
242
});
210
243
}
211
244
```
212
245
213
-
With the creation of the error link, we now have an Apollo Client that completely manages the WooCommerce session. Note that this doesn't account for all use cases, specifically dealing with registered WooCommerce customers. In such cases, you'll need to use a second JWT for identifying their WordPress account, called an Authentication Token or auth token for short. For handling user authentication, auth tokens, and refresh tokens, refer to the next guide.
246
+
There is a lot going on here but is not very complex once broken down.
This is the scary looking part if you are not familar with observables, but don't be. Observables are similar to Promises, but instead of handling a single asynchronous event, they handle multiple events over time. While Promises resolve only once and return a single value, Observables emit multiple values and can be canceled, providing greater control over asynchronous data streams.
285
+
Our usage here is to tell Apollo to retry the last operation after we have retrieved a new token with `getSessionToken` if the current `graphQLError` matches any of our targetted errors, otherwise `observable` is left as a `undefined` value and Apollo continues as normal.
286
+
287
+
Next is the `createUpdateLink` callback, responsible for retrieving an updated `sessionToken` from the `woocommerce-session` HTTP response token. The reason for this is the session token generated by WooGraphQL is self-managing and a new token with an updated expiration time of 14 days from the last action is generated on each request that a `woocommerce-session` HTTP request header is sent. To retrieve a store this updated token we use Apollo afterware.
288
+
289
+
## Defining the `createUpdateLink` function
290
+
291
+
Next, define the `createUpdateLink` function as follows:
localStorage.setItem(process.env.SESSION_TOKEN_LS_KEY as string, sessionToken);
308
+
}
309
+
}
310
+
311
+
return response;
312
+
});
313
+
}
314
+
```
315
+
316
+
This is an our Apollo afterware callback, and if you are wondering how does this differ from Apollo middleware look at the following.
317
+
318
+
```javascript
319
+
returnforward(operation).map((response) => {
320
+
```
321
+
322
+
By calling `.map()` on the result of `forward()`, we're telling Apollo to execute this after operation completion, you can even take it a further by modifying the `response` object if necessary. It is not here, but I figured I should at least state that fact.
323
+
324
+
We also put after the `createErrorLink` callback in our `from()` call when defining the `ApolloClient` to ensure it's never executed on a request failed due to an invalid token.
325
+
326
+
And with the creation of the `createUpdateLink` link, we now have an Apollo Client that completely manages the WooCommerce session. Note that this doesn't account for all use cases, specifically dealing with registered WooCommerce customers. In such cases, you'll need to use a second JWT for identifying their WordPress account, called an Authentication Token or auth token for short. For handling user authentication, auth tokens, and refresh tokens, refer to the next guide.
214
327
215
328
This should provide you with a solid foundation for setting up a GraphQL client that effectively manages user sessions in your e-commerce application. By following the steps outlined, you'll be able to create a seamless experience for your users when interacting with both WooCommerce, ultimately saving development time and effort.
0 commit comments