gatsby-uc / gatsby-source-strapi

Gatsby source plugin for building websites using Strapi as a data source
MIT License
354 stars 182 forks source link

API token needs to be reset on each build on Heroku #298

Closed mark-tanser closed 2 years ago

mark-tanser commented 2 years ago

I have strapi (v4) deployed to heroku (postgres), but found that I need to create a new API token in the strapi admin panel each time I build a local gatsby (v4) frontend.

If this expected behavior?

backend packages: "@strapi/plugin-graphql": "^4.1.2", "@strapi/plugin-i18n": "4.1.2", "@strapi/plugin-users-permissions": "4.1.2", "@strapi/provider-upload-aws-s3": "^4.1.2", "@strapi/strapi": "4.1.2", "pg": "^8.7.3", "pg-connection-string": "^2.5.0", "sqlite3": "5.0.2"

frontend packages: "dotenv": "^16.0.0", "gatsby": "^4.9.1", "gatsby-plugin-gatsby-cloud": "^4.9.0", "gatsby-plugin-image": "^2.9.0", "gatsby-plugin-manifest": "^4.9.0", "gatsby-plugin-material-ui": "^4.0.2", "gatsby-plugin-offline": "^5.9.0", "gatsby-plugin-react-helmet": "^5.9.0", "gatsby-plugin-sharp": "^4.9.0", "gatsby-plugin-web-font-loader": "^1.0.4", "gatsby-source-filesystem": "^4.9.0", "gatsby-source-strapi": "^2.0.0-beta.0", "gatsby-transformer-remark": "^5.9.0", "gatsby-transformer-sharp": "^4.9.0", "prop-types": "^15.8.0", "react": "^17.0.1", "react-dom": "^17.0.1", "react-helmet": "^6.1.0"

error encountered on rebuild without creating new token is:

ERROR #11321 PLUGIN

"gatsby-source-strapi" threw an error while running the sourceNodes lifecycle:

Request failed with status code 401

Error: Request failed with status code 401

If I create a new token, update .env, and run with npm run develop, it all works again.

in my gatsby-config.js I have:

{ resolve: gatsby-source-strapi, options: { apiURL: process.env.STRAPI_API_URL, accessToken: process.env.STRAPI_TOKEN, collectionTypes: ['category', 'product', ....., 'user'], singleTypes: [], inlineImages: { typesToParse: { Article: ['body'], ComponentBlockBody: ['text'], }, }, queryLimit: 10000, locale: 'en', preview: false, headers: {}, cache: false, } },

I have Public User permissions activated for find and findOne in all collectionTypes (including 'user')

I have run gatsby clean prior to npm run develop

remidej commented 2 years ago

The problem is that SQLite stores your database as a file on your server's disk. But Heroku doesn't persist the filesystem, so every new build will delete your database (including your API token). You can read their docs about this.

The solution is to use a non-SQL database. For Heroku, the easiest way is to use their Postgres addon. We have some docs about this

mark-tanser commented 2 years ago

Thanks, but I am using postgresql on heroku.

I followed the official docs for this when setting up.

All my saved data persists across builds, and I can see the token that was previously saved also.

Why close this so quickly?

mark-tanser commented 2 years ago

ok I'll just post this again then

remidej commented 2 years ago

Sorry I closed the issue too quickly, but the SQLite issue is one that comes up often, I assumed it was it.

It's not obvious to me what the problem is then. It could come from the environment variable setup. Are you using a .env file to set your env variables? Or are you using Heroku config vars?

mark-tanser commented 2 years ago

Thanks, no worries!

I set these in .env for local build of my frontend with the graphql query:

STRAPI_API_URL STRAPI_TOKEN

I also deployed my frontend on netlify, setting these as environment variables, but saw the same errors after pushing changes to collection types, or after subsequent manual rebuild

So the first time I set all this up, deploy my strapi server to heroku or digital ocean, create an admin, create an API token, and save to my .env or netlify environment variables, it all works. My frontend queries are successful and no errors in runtime logs.

But then if I make a change to collection types in my localhost:1337 strapi, push changes to my repo and auto-deploy to my strapi server, the frontend queries no longer work and I see the errors ai first mentioned. This also happens if I redeploy my frontend after committing and pushing changes, which is the real pain here.

The only way I seem able to make it work again is by deleting the existing api token on my deployed strapi-server, creating a new one and changing my frontend environment variables ( both local and netlify ).

It seems strange to me, but maybe it's meant to be this way?

Thanks again

remidej commented 2 years ago

Thanks for the details. No, it's not supposed to be this way, normally your API token should keep working after redeploying.

I think it's possible this could be a Strapi issue more than a gatsby-source-strapi issue. We can find out if that's the case by trying to make normal API calls outside of Gatbsy. So when you redeploy Strapi and your access token seems to be broken, can you try using it by making requests with Postman or curl? You can use the token via an Authorization token.

I also notice this in the API token docs:

Changing the salt invalidates all the existing API tokens.

So maybe try to check if the apiToken.salt from the ./config/admin.js file is properly set. If you try to reference an API_TOKEN_SALT environment variable that doesn't exist, it could explain the problem.

mark-tanser commented 2 years ago

ok, so before changing anything, I can query my database using Postman GET request with the API token. I get my data returned as expected.

When I make some change on local strapi and push to Digital Ocean and rebuild, the same Postman GET request returns this error:

{"data":null,"error":{"status":401,"name":"UnauthorizedError","message":"Missing or invalid credentials","details":{}}}

I can't see how to check if the apiToken.salt is set in ./config/admin.js. I don't seem to have any way to drill into the actual build / public folder using Digital Ocean. All I can see is a build log.

I don't have any API_TOKEN_SALT environment variable set. That wasn't mentioned in the 'how to' deployment guide for Strapi.

Anyway, I'm puzzled how creating the API token on the deployed strapi app can then make a change to the ./config/admin.js file ? Surely that can only be created at build-time?

My local version of that file which was pushed to Digital Ocean does not contain any salt. It only has this:

module.exports = ({ env }) => ({ auth: { secret: env('ADMIN_JWT_SECRET', 'some-random-alpha-numeric-sequence-I-dont-remember-setting'), }, });

So far it's only the strapiV4 compatible beta version of gatsby-source-strapi plugin that seems to use this API TOKEN.

Anything else I can look at? Thanks!

remidej commented 2 years ago

Please try to set your config/admin.js like this:

module.exports = ({ env }) => ({
  auth: {
    secret: env('ADMIN_JWT_SECRET', 'some-random-alpha-numeric-sequence-I-dont-remember-setting'),
  },
  apiToken: {
    salt: 'some-random-alhpa-numeric-sequence', // replace this string with what you want
  },
});

Then redeploy, create a new API token, and see if this ones persists after new redeploys.

Then please let me know if it works

soupette commented 2 years ago

@mark-tanser you will also need to add ADMIN_JWT_SECRET and the salt env variable (if configured with env variable) in your heroku dashboard.

mark-tanser commented 2 years ago

Thanks very much - this worked. Perhaps it should be added to the deployment and/or plugin guides/readme?

remidej commented 2 years ago

Yes maybe you can open a documentation on the docs repo then