Skip to content

Commit 9177fc6

Browse files
finn-mattipieh
authored andcommitted
feat(gatsby-source-wordpress): allow users to obtain JWT Token to make authenticated requests (#9509)
This fixes #6879.
1 parent a2d0eb6 commit 9177fc6

File tree

2 files changed

+88
-33
lines changed

2 files changed

+88
-33
lines changed

packages/gatsby-source-wordpress/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ module.exports = {
8787
wpcom_app_clientId: "54793",
8888
wpcom_user: "gatsbyjswpexample@gmail.com",
8989
wpcom_pass: process.env.WORDPRESS_PASSWORD,
90+
91+
// If you use "JWT Authentication for WP REST API" (https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/)
92+
// plugin, you can specify user and password to obtain access token and use authenticated requests against wordpress REST API.
93+
jwt_user: process.env.JWT_USER,
94+
jwt_pass: process.env.JWT_PASSWORD,
9095
},
9196
// Set verboseOutput to true to display a verbose output on `npm run develop` or `npm run build`
9297
// It can help you debug specific API Endpoints problems.

packages/gatsby-source-wordpress/src/fetch.js

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,35 @@ const colorized = require(`./output-color`)
66
const httpExceptionHandler = require(`./http-exception-handler`)
77
const requestInQueue = require(`./request-in-queue`)
88

9+
/**
10+
* Check auth object to see if we should fetch JWT access token
11+
*/
12+
const shouldUseJwt = auth => auth && (auth.jwt_user || auth.jwt_pass)
13+
14+
/**
15+
* Check auth object to see if we should use HTTP Basic Auth
16+
*/
17+
const shouldUseHtaccess = auth =>
18+
auth && (auth.htaccess_user || auth.htaccess_pass)
19+
20+
/**
21+
* Format Auth settings for verbose output
22+
*/
23+
const formatAuthSettings = auth => {
24+
let authOutputLines = []
25+
if (shouldUseJwt(auth)) {
26+
authOutputLines.push(` JWT Auth: ${auth.jwt_user}:${auth.jwt_pass}`)
27+
}
28+
29+
if (shouldUseHtaccess(auth)) {
30+
authOutputLines.push(
31+
` HTTP Basic Auth: ${auth.htaccess_user}:${auth.htaccess_pass}`
32+
)
33+
}
34+
35+
return authOutputLines.join(`\n`)
36+
}
37+
938
/**
1039
* High-level function to coordinate fetching data from a WordPress
1140
* site.
@@ -35,11 +64,16 @@ async function fetch({
3564
_accessToken = await getWPCOMAccessToken(_auth)
3665
} else {
3766
url = `${_siteURL}/wp-json`
67+
if (shouldUseJwt(_auth)) {
68+
_accessToken = await getJWToken(_auth, url)
69+
}
3870
}
3971

4072
if (_verbose) {
4173
console.time(`=END PLUGIN=====================================`)
4274

75+
const authOutput = formatAuthSettings(_auth)
76+
4377
console.log(
4478
colorized.out(
4579
`
@@ -48,7 +82,7 @@ async function fetch({
4882
Site URL: ${_siteURL}
4983
Site hosted on Wordpress.com: ${_hostingWPCOM}
5084
Using ACF: ${_useACF}
51-
Using Auth: ${_auth.htaccess_user} ${_auth.htaccess_pass}
85+
Auth: ${authOutput ? `\n${authOutput}` : `false`}
5286
Verbose output: ${_verbose}
5387
5488
Mama Route URL: ${url}
@@ -65,14 +99,14 @@ Mama Route URL: ${url}
6599
method: `get`,
66100
url: url,
67101
}
68-
if (_auth && (_auth.htaccess_user || _auth.htaccess_pass)) {
102+
if (shouldUseHtaccess(_auth)) {
69103
options.auth = {
70104
username: _auth.htaccess_user,
71105
password: _auth.htaccess_pass,
72106
}
73107
}
74108

75-
if (_hostingWPCOM && _accessToken) {
109+
if (_accessToken) {
76110
options.headers = {
77111
Authorization: `Bearer ${_accessToken}`,
78112
}
@@ -100,7 +134,6 @@ Mama Route URL: ${url}
100134
_verbose,
101135
_useACF,
102136
_acfOptionPageIds,
103-
_hostingWPCOM,
104137
_includedRoutes,
105138
_excludedRoutes,
106139
typePrefix,
@@ -124,7 +157,6 @@ Fetching the JSON data from ${validRoutes.length} valid API Routes...
124157
route,
125158
_verbose,
126159
_perPage,
127-
_hostingWPCOM,
128160
_auth,
129161
_accessToken,
130162
_concurrentRequests,
@@ -173,6 +205,32 @@ async function getWPCOMAccessToken(_auth) {
173205
return result
174206
}
175207

208+
/**
209+
* Gets JSON Web Token so it can fetch private data
210+
*
211+
* @returns
212+
*/
213+
async function getJWToken(_auth, url) {
214+
let result
215+
let authUrl = `${url}/jwt-auth/v1/token`
216+
try {
217+
const options = {
218+
url: authUrl,
219+
method: `post`,
220+
data: {
221+
username: _auth.jwt_user,
222+
password: _auth.jwt_pass,
223+
},
224+
}
225+
result = await axios(options)
226+
result = result.data.token
227+
} catch (e) {
228+
httpExceptionHandler(e)
229+
}
230+
231+
return result
232+
}
233+
176234
/**
177235
* Fetch the data from specified route url, using the auth provided.
178236
*
@@ -183,7 +241,6 @@ async function fetchData({
183241
route,
184242
_verbose,
185243
_perPage,
186-
_hostingWPCOM,
187244
_auth,
188245
_accessToken,
189246
_concurrentRequests,
@@ -202,18 +259,14 @@ async function fetchData({
202259
console.time(`Fetching the ${type} took`)
203260
}
204261

205-
let routeResponse = await getPages(
206-
{
207-
url,
208-
_perPage,
209-
_hostingWPCOM,
210-
_auth,
211-
_accessToken,
212-
_verbose,
213-
_concurrentRequests,
214-
},
215-
1
216-
)
262+
let routeResponse = await getPages({
263+
url,
264+
_perPage,
265+
_auth,
266+
_accessToken,
267+
_verbose,
268+
_concurrentRequests,
269+
})
217270

218271
let entities = []
219272
if (routeResponse) {
@@ -244,7 +297,6 @@ async function fetchData({
244297
route: { url: menu.meta.links.self, type: `${type}_items` },
245298
_verbose,
246299
_perPage,
247-
_hostingWPCOM,
248300
_auth,
249301
_accessToken,
250302
})
@@ -282,15 +334,7 @@ async function fetchData({
282334
* @returns
283335
*/
284336
async function getPages(
285-
{
286-
url,
287-
_perPage,
288-
_hostingWPCOM,
289-
_auth,
290-
_accessToken,
291-
_concurrentRequests,
292-
_verbose,
293-
},
337+
{ url, _perPage, _auth, _accessToken, _concurrentRequests, _verbose },
294338
page = 1
295339
) {
296340
try {
@@ -304,15 +348,20 @@ async function getPages(
304348
page: page,
305349
})}`,
306350
}
307-
if (_hostingWPCOM) {
351+
352+
if (_accessToken) {
308353
o.headers = {
309354
Authorization: `Bearer ${_accessToken}`,
310355
}
311-
} else {
312-
o.auth = _auth
313-
? { username: _auth.htaccess_user, password: _auth.htaccess_pass }
314-
: null
315356
}
357+
358+
if (shouldUseHtaccess(_auth)) {
359+
o.auth = {
360+
username: _auth.htaccess_user,
361+
password: _auth.htaccess_pass,
362+
}
363+
}
364+
316365
return o
317366
}
318367

@@ -465,6 +514,7 @@ function getValidRoutes({
465514
`**/embed`,
466515
`**/proxy`,
467516
`/`,
517+
`/jwt-auth/**`,
468518
]
469519

470520
const routePath = getRoutePath(url, route._links.self)

0 commit comments

Comments
 (0)