How to view private pages with JWT, need a walkthrough

Hi everyone,

Junior Front End Developer here and also very new to frontity.

I’m aware that there are some topics discussing this topic, but after looking through these places:

and everything else that turns up on google searching for “frontity jwt auth” and similar. :wink:

We still cannot understand how to make it work.

We use the suggested plugin JWT Authentication for WP REST API – WordPress plugin | WordPress.org
We can with postman and a normal fetch request get a token, validate that token and also view private pages with same token through the REST API.
But when we get to frontity, we get stuck.

With an action, we set state.source.auth to the token ( “Bearer xxxx.xxxx.xxxx”), but we still cannot view the private pages. We only get a 404.

Sadly, since we’re under an NDA, we can’t share a published version of the code or a deployed site.
But I will share with you what I think are the appropriate snippets.

package.json dependencies:

  "dependencies": {
"@frontity/core": "^1.10.1",
"@frontity/html2react": "^1.6.1",
"@frontity/tiny-router": "^1.3.2",
"@frontity/wp-source": "^1.11.1",
"dotenv": "^8.2.0",
"frontity": "^1.14.1",
"gol-theme": "file:packages/gol-theme",
"react-svg": "^11.2.4"
  },

frontity.settings.js:

    const settings = {
  name: 'gol-frontity',
  state: {
    frontity: {
      url: process.env.WP_BACKEND,
      title: 'XX',
      description: 'XX',
    },
  },
  packages: [
    {
      name: 'gol-theme',
      state: {
        theme: {
          featured: {
            showOnList: false,
            showOnPost: false,
          },
        },
      },
    },
    {
      name: '@frontity/wp-source',
      state: {
        source: {
          url: process.env.WP_BACKEND,
          homepage: '/startsida',
          postTypes: [
            {
              type: 'kontaktperson',
              endpoint: 'kontaktperson',
              archive: '/kontaktperson',
            },
          ],
          // USED FOR TESTING ONLY, SHOULD NOT BE USED IN FINAL AS WE WANT USER TO ENTER THEIR TOKEN AND THIS VALUE WILL NOT BE CHANGEABLE
          // auth:
          //   'Bearer xxx.xxx.xxx',
        },
      },
    },
    '@frontity/tiny-router',
    '@frontity/html2react',
  ],
};

export default settings;

src/index.js:

import Root from './components';

export default {
  name: 'gol-theme',
  roots: {
    theme: Root,
  },
  state: {
    theme: {
      user: {
      },
    },
  },
  actions: {
    theme: {
      },
    },
    source: {
      auth: {
        setToken: ({ state }) => value => {
          state.source.auth = `Bearer ${value}`;
        },
      },
    },
  },
};

The form submit handler:

const handleSubmit = async event => {
    event.preventDefault();

    const formdata = new FormData();
    formdata.append('username', username);
    formdata.append('password', password);

    const requestOptions = {
      method: 'POST',
      body: formdata,
      redirect: 'follow',
    };

    let response = await fetch(
      `${state.frontity.url}/wp-json/jwt-auth/v1/token`,
      requestOptions
    );
    response = await response.json();

    if (response.token) {
      // sessionStorage.setItem('gol-token', response.token);
      actions.source.auth.setToken(response.token); // SEE ACTION in components/index.jsx
      actions.router.set('/dashboard/');
    } else {
      // TODO: Proper error handling
      console.log(response);
    }
  };

The corresponding component that should get the data from the private page:

import React, { useEffect } from 'react';
import { connect } from 'frontity';

const Dashboard = ({ state }) => {
  const data = state.source.get(state.router.link);
  const page = state.source.page[data.id];

  console.log(page);

  /* 
  In browser console, frontity.state.source.data should have a "/dashboard/" item, which it has, but it still shows isError = true and contains no data,
  which we think has to do with it not using auth for the request
  */

  return <p>Dashboard</p>;
};

export default connect(Dashboard);

We get a 404 with all the ways we tried.
In the github issue regarding the docs surrounding this, it says that the auth object should disappear clientside, but we can see it in frontity.state.source.auth when we check the console in the browser.

A complete walkthrough of how to, within our form submit handler function, set the state.source.auth to be used in all subsequent requests and make it work, would be what we’re after. :slight_smile:

Best regards,
Daniel

3 Likes

Corrected the formatting of the code blocks. :sweat_smile:

1 Like

Hi! I’m just guessing, but in state->frontity->url, shouldn’t the url be the front-end url?

Hi @daniel

Have you checked out this post which you may find useful?