JWT with Frontity

Iā€™m not able to find an example on how to do this in the documentation. I need to authenticate in order to see private posts. Iā€™m trying to do a knowledge base with public and private articles and would appreciate any help in a good way to achieve that.

2 Likes

Hi @victorcarvalhosp, below is a function to get the token from the server.
With that token you can do restricted operations, such as viewing private posts.

I hope you find it useful :sunglasses:

fetchToken = () => {
    this.setState({
      isLoading: true,
    })
    fetch(Constants.apiUrl + 'jwt-auth/v1/token', {
      method: 'post',
      headers: new Headers({
        'Content-Type': 'application/json'
      }), 
      body: JSON.stringify({
        username: this.state.username,
        password: this.state.password
      })
    })
    .then(res => res.json())
    .then(data => this.setState({
        token: data.token,
        isLoading: false,
    }))
    .then( console.log('Done!') )
    
    .catch(error => console.log(error))
  }
2 Likes

Can we get the JWT token beforeSSR?

I think the best place to get the token is afterCSR, as @luisherranz says

this code is checked:

...
  actions: {
    theme: {
      afterCSR: async ({ state, libraries, actions }) => {
        if (state.frontity.platform === 'client') {
          if (undefined === state.theme.token) {
            actions.theme.fetchToken();
          }
        }
      },
      fetchToken
    },
  }
..------------------------------------
import { fetch } from 'frontity';

export const fetchToken = async ({ state }) => {
    const res = await fetch(
        `${state.source.api}/jwt-auth/v1/token`, {
            method: 'POST',
            headers: new Headers({
              'Content-Type': 'application/json'
            }),
            body: JSON.stringify({
              "username": state.theme.username,
              "password": state.theme.password
            }),
            redirect: 'follow'
        }
    );
    const body = await res.json();
    state.theme.token = body.token;

}

we can get token in beforeSSR
here is code. how i have done it

fetch(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
           username: this.state.username,
           password: this.state.password
    })
  })
   .then(res => res.json())
  .then(data => console.log(data)
  )
  .catch(error => console.log(error))

I guess it depends on your needs.

What do you want to do with the token?

i have used for fetching menus

Ok. Thanks @mehul. Then you only need that in the server, right?

If you expose the username/password on the state itā€™s going to be sent to the client so thatā€™s not a good idea. It will also be part of your git repository. Even if the repository is not public, thatā€™s also not a good idea.

A common approach to add sensible data to an app is to use environment variables. You have a lot of info about how to do so in this topic: How to read Environment Variables

2 Likes

A post was split to a new topic: Protected routes with Frontity

could you show me how did this please i am trying to get custom post type

HI @hugsaf2132

In order to help with your issue, can you please provide the info suggested here?

The more info you provide the better. Providing a repo or code-sandbox with your code is especially helpful to find solutions of technical issues with specific code

How would I proceed with this? Iā€™d like to try it out.

Here is a very basic implementation:

3 Likes

@vscopise I followed your example and it was very useful, now I have the token in the state variable, but I do not know how to use it, I mean is there a way to inject the token in frontity requests?

Reading JWT plugin documentation:

Once you get the token, you must store it somewhere in your application, ex. in a cookie or using localstorage.

From this point, you should pass this token to every API call

I will appreciate if someone can give me a light for the last steps

Hi @harvey !

you can use the token in all api calls that require authentication

for example:

const resSettings = await fetch( `${state.source.api}/wp/v2/settings`, {
        headers: {
            authorization: 'Bearer ' + state.theme.token
        },
    });
    const bodySettings = await resSettings.json();
    state.theme.state = bodySettings;

Tell me, what are you developing with Frontity?

@vscopise I am working in this website which has multiple custom post statuses like ā€œArchivedā€, ā€œPreviewā€ and so on. Those statuses are successfully created but to be able to render pages under those statuses I need a logged in user.

I tested REST API from postman and it works, but I am trying to use the token properly from frontity

So, for example in this link If I set the status to archived image

I will not be able to render contents and I get 404 page (as it is now) but if I set it to Published I will see everything.

What I am trying to achieve is call that post (or any post) under the archived status with a token and being able to render contents

Let me know if I am clear enough

Hi @harvey,
I think that for a post to be displayed, its status must be ā€œpublishedā€, if the status is another, the content will not be able to be displayed.

I think you could change the state of the post (published, draft, privateā€¦) using a token, knowing the ID of the post

I donā€™t understand the reason to change the status of the post, unless you want to work with private contentā€¦

Yes, I want to render private content in the frontpage and I thought that I can request that content from frontity by adding the token somewhere, is there a way to always send the token if there is one available ?

hI @harvey

To render a private post you must include the token fetched previously in the header.

To get the post you use the same api call: ā€¦/wp/v2/posts/[ID]

1 Like

@vscopise Yes, I tested what you mentioned and it worked from postman, but it is not working from frontity, I mean I have the auth var set in the place I think it should be but still getting the 404 error