Skip to content

Commit

Permalink
feat(gatsby-source-wordpress): allow users to obtain JWT Token to mak…
Browse files Browse the repository at this point in the history
…e authenticated requests (#9509)

This fixes #6879.
  • Loading branch information
Martin Hähnel authored and pieh committed Nov 4, 2018
1 parent a2d0eb6 commit 9177fc6
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 33 deletions.
5 changes: 5 additions & 0 deletions packages/gatsby-source-wordpress/README.md
Expand Up @@ -87,6 +87,11 @@ module.exports = {
wpcom_app_clientId: "54793",
wpcom_user: "gatsbyjswpexample@gmail.com",
wpcom_pass: process.env.WORDPRESS_PASSWORD,

// If you use "JWT Authentication for WP REST API" (https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/)
// plugin, you can specify user and password to obtain access token and use authenticated requests against wordpress REST API.
jwt_user: process.env.JWT_USER,
jwt_pass: process.env.JWT_PASSWORD,
},
// Set verboseOutput to true to display a verbose output on `npm run develop` or `npm run build`
// It can help you debug specific API Endpoints problems.
Expand Down
116 changes: 83 additions & 33 deletions packages/gatsby-source-wordpress/src/fetch.js
Expand Up @@ -6,6 +6,35 @@ const colorized = require(`./output-color`)
const httpExceptionHandler = require(`./http-exception-handler`)
const requestInQueue = require(`./request-in-queue`)

/**
* Check auth object to see if we should fetch JWT access token
*/
const shouldUseJwt = auth => auth && (auth.jwt_user || auth.jwt_pass)

/**
* Check auth object to see if we should use HTTP Basic Auth
*/
const shouldUseHtaccess = auth =>
auth && (auth.htaccess_user || auth.htaccess_pass)

/**
* Format Auth settings for verbose output
*/
const formatAuthSettings = auth => {
let authOutputLines = []
if (shouldUseJwt(auth)) {
authOutputLines.push(` JWT Auth: ${auth.jwt_user}:${auth.jwt_pass}`)
}

if (shouldUseHtaccess(auth)) {
authOutputLines.push(
` HTTP Basic Auth: ${auth.htaccess_user}:${auth.htaccess_pass}`
)
}

return authOutputLines.join(`\n`)
}

/**
* High-level function to coordinate fetching data from a WordPress
* site.
Expand Down Expand Up @@ -35,11 +64,16 @@ async function fetch({
_accessToken = await getWPCOMAccessToken(_auth)
} else {
url = `${_siteURL}/wp-json`
if (shouldUseJwt(_auth)) {
_accessToken = await getJWToken(_auth, url)
}
}

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

const authOutput = formatAuthSettings(_auth)

console.log(
colorized.out(
`
Expand All @@ -48,7 +82,7 @@ async function fetch({
Site URL: ${_siteURL}
Site hosted on Wordpress.com: ${_hostingWPCOM}
Using ACF: ${_useACF}
Using Auth: ${_auth.htaccess_user} ${_auth.htaccess_pass}
Auth: ${authOutput ? `\n${authOutput}` : `false`}
Verbose output: ${_verbose}
Mama Route URL: ${url}
Expand All @@ -65,14 +99,14 @@ Mama Route URL: ${url}
method: `get`,
url: url,
}
if (_auth && (_auth.htaccess_user || _auth.htaccess_pass)) {
if (shouldUseHtaccess(_auth)) {
options.auth = {
username: _auth.htaccess_user,
password: _auth.htaccess_pass,
}
}

if (_hostingWPCOM && _accessToken) {
if (_accessToken) {
options.headers = {
Authorization: `Bearer ${_accessToken}`,
}
Expand Down Expand Up @@ -100,7 +134,6 @@ Mama Route URL: ${url}
_verbose,
_useACF,
_acfOptionPageIds,
_hostingWPCOM,
_includedRoutes,
_excludedRoutes,
typePrefix,
Expand All @@ -124,7 +157,6 @@ Fetching the JSON data from ${validRoutes.length} valid API Routes...
route,
_verbose,
_perPage,
_hostingWPCOM,
_auth,
_accessToken,
_concurrentRequests,
Expand Down Expand Up @@ -173,6 +205,32 @@ async function getWPCOMAccessToken(_auth) {
return result
}

/**
* Gets JSON Web Token so it can fetch private data
*
* @returns
*/
async function getJWToken(_auth, url) {
let result
let authUrl = `${url}/jwt-auth/v1/token`
try {
const options = {
url: authUrl,
method: `post`,
data: {
username: _auth.jwt_user,
password: _auth.jwt_pass,
},
}
result = await axios(options)
result = result.data.token
} catch (e) {
httpExceptionHandler(e)
}

return result
}

/**
* Fetch the data from specified route url, using the auth provided.
*
Expand All @@ -183,7 +241,6 @@ async function fetchData({
route,
_verbose,
_perPage,
_hostingWPCOM,
_auth,
_accessToken,
_concurrentRequests,
Expand All @@ -202,18 +259,14 @@ async function fetchData({
console.time(`Fetching the ${type} took`)
}

let routeResponse = await getPages(
{
url,
_perPage,
_hostingWPCOM,
_auth,
_accessToken,
_verbose,
_concurrentRequests,
},
1
)
let routeResponse = await getPages({
url,
_perPage,
_auth,
_accessToken,
_verbose,
_concurrentRequests,
})

let entities = []
if (routeResponse) {
Expand Down Expand Up @@ -244,7 +297,6 @@ async function fetchData({
route: { url: menu.meta.links.self, type: `${type}_items` },
_verbose,
_perPage,
_hostingWPCOM,
_auth,
_accessToken,
})
Expand Down Expand Up @@ -282,15 +334,7 @@ async function fetchData({
* @returns
*/
async function getPages(
{
url,
_perPage,
_hostingWPCOM,
_auth,
_accessToken,
_concurrentRequests,
_verbose,
},
{ url, _perPage, _auth, _accessToken, _concurrentRequests, _verbose },
page = 1
) {
try {
Expand All @@ -304,15 +348,20 @@ async function getPages(
page: page,
})}`,
}
if (_hostingWPCOM) {

if (_accessToken) {
o.headers = {
Authorization: `Bearer ${_accessToken}`,
}
} else {
o.auth = _auth
? { username: _auth.htaccess_user, password: _auth.htaccess_pass }
: null
}

if (shouldUseHtaccess(_auth)) {
o.auth = {
username: _auth.htaccess_user,
password: _auth.htaccess_pass,
}
}

return o
}

Expand Down Expand Up @@ -465,6 +514,7 @@ function getValidRoutes({
`**/embed`,
`**/proxy`,
`/`,
`/jwt-auth/**`,
]

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

0 comments on commit 9177fc6

Please sign in to comment.