async-labs / saas

Build your own SaaS business with SaaS boilerplate. Productive stack: React, Material-UI, Next, MobX, WebSockets, Express, Node, Mongoose, MongoDB. Written with TypeScript.
https://saas-app.async-await.com
MIT License
4.06k stars 675 forks source link

Problem sign in - production with heroku #65

Closed yaniving closed 3 years ago

yaniving commented 4 years ago

I'm using saas repo and trying to upload my code to Heroku, in my local machine everything works fine with google sign in. but I'm having a problem understanding what the PRODUCTION_URL_API env variable should be - my URL is https://[xxx].herokuapp.com and how do I redirect to my API URL localhost:8000 in my dev environment location file - /saas/app/lib/consts.ts

Screen Shot 2020-03-27 at 16 38 48
WaterlessPiano2 commented 4 years ago

I am also struggling with deploying to Heroku. I don't know what values to put into app env variables. I have been putting this in to where appropriate, https://[xxx].herokuapp.com but no luck. I keep getting this error while trying to deploy.

`app/lib/store/index.ts 30:18 Cannot find namespace 'SocketIOClient'. 28 | public isLoggingIn = true; 29 |

30 | public socket: SocketIOClient.Socket; | ^ 31 | 32 | constructor({ 33 | initialState = {},

Build error occurred`

The API deploys fine.

tima101 commented 4 years ago

@yaniving Then your api/.env file should contain:

PRODUCTION_URL_API=https://[xxx].herokuapp.com

Here is an example of values that I have: Screenshot from 2020-03-31 09-41-24

Here is a guide to deploying to Heroku: https://github.com/builderbook/builderbook/blob/master/README.md#deploy-to-heroku

Remember to have PROJECT_PATH env var and buildpack from: https://github.com/timanovsky/subdir-heroku-buildpack

This setup allows you deploy from folder inside your repo.


You can debug by adding logger.info or console.log to your server logs. I have both app and api deployed to Heroku from this repo: https://saas-app.builderbook.org/ https://saas-api.builderbook.org/

So all should work for you after debugging.

WaterlessPiano2 commented 4 years ago

Hello Thanks for your reply @tima101 it works now.

WaterlessPiano2 commented 4 years ago

Actually I hit another roadblock with this.. following the instructions I can get to the login screen and then get the API to send me a signup e-mail but unfortunately clicking the link doesn't sign me in. The reason being Heroku prevents setting cookies on https://[xxx].herokuapp.com

In other words, in browsers that support the functionality, applications in the herokuapp.com domain are prevented from setting cookies for *.herokuapp.com.

So instead I tried to use my own custom domain name, but as it is not possible/easy to have free SSL on Heroku my connections were getting blocked by CORS.

Would you recommend to definitely pay for hobby dynos as suggested on the documentation?

tima101 commented 4 years ago

@WaterlessPiano2 Yeah, why not. You can always downgrade dyno or migrate to AWS if you want more customization. Heroku is perfect for when you starting out.

WaterlessPiano2 commented 4 years ago

I am checking if there was a way to do this with no extra cost that, I didn't realise. Yea you are right, I might use Heroku for the time being. Thanks for your reply @tima101. Looking forward to the book!

stonesthatwhisper commented 4 years ago

@tima101 Does api/.env have to contain PRODUCTION_URL_API settings if this var has already been added in Heroku's "Reveal Config Vars" settings? This code seems to suggest adding it to api/.env is not necessary if the environment variable PRODUCTION_URL_API is already set.

I am having an issue signing in with google after deployed to Heroku, although it works locally. I keep getting a 403 Forbidden after clicking "Log In with Google". The browser made a GET to https://[api].heroku.com/auth/google. Can't figure out why it is happening.

https://[api].herokuapp.com/auth/google
Request Method: GET
Status Code: 403 Forbidden

What am I missing here? Thanks.

I also tried to deploy via docker to a digitalOcean droplet. After clicking "Log In with Google" I got a hang then timed out after 1 min. (turned out there is an error related to CORS, haven't looked into it).

@yaniving Then your api/.env file should contain:

PRODUCTION_URL_API=https://[xxx].herokuapp.com
tima101 commented 4 years ago

@stonesthatwhisper

stonesthatwhisper commented 4 years ago

@tima101

  • for app, if you want some env vars available on both server and browser, add these env vars to app/next.config.js. By default env vars will be available on server only for app, meaning only server-side rendered pages will see env vars but not client-side rendered pages.

Thanks for the pointer. I am not sure I understand this above passage. Do you think it is why I am receiving 403 with /auth/google? I am quite sure I have every env var settings (except STRIPE_xxx), since clicking "login with email" button does send me an email, but then I have the same issue as mentioned here.

BTW, I think all of these env vars are UPPERCASE. Didn't know CamelCase works.

2020-04-21T10:50:14.515796+00:00 heroku[router]: at=info method=GET path="/auth/google" host=api-site.herokuapp.com request_id=597b1631-965d-40b8-ac6b-b99d268b67d6 fwd="<my-external-ip>" dyno=web.1 connect=1ms service=3ms status=403 bytes=542 protocol=https

tima101 commented 4 years ago

Do you think it is why I am receiving 403 with /auth/google?

@stonesthatwhisper Not likely. On app logs, print PRODUCTION_URL_API and URL_API env vars with console.log. See if you get expected values.

403 Forbidden is default response for all routes of api except API endpoints. Because all API endpoints are mounted before Express route that sends 403 Forbidden: https://github.com/async-labs/saas/blob/master/api/server/app.ts

setupGoogle({ server, ROOT_URL });
setupPasswordless({ server, ROOT_URL });

api(server);

const http = new httpModule.Server(server);
realtime({ http, origin: URL_APP, sessionMiddleware });

server.get('/robots.txt', (_, res) => {
  res.sendFile(path.join(__dirname, '../static', 'robots.txt'));
});

server.get('*', (_, res) => {
  res.sendStatus(403);
});

The project in this repo is deployed to https://saas-app.builderbook.org and https://saas-api.builderbook.org/ - Google OAuth works as expected.

You said that Google OAuth works locally but not in production. I would start debugging your code with this fact in mind.


Here is a list of env vars for app: Screenshot from 2020-04-21 08-09-16

WaterlessPiano2 commented 4 years ago

Hey @stonesthatwhisper Out of curiosity can you log in using the email login after deploying to free Heroku Dynos? I could not log in at all using free dynos because Heroku doesn't let you set cookies on these.

stonesthatwhisper commented 4 years ago

@tima101 Thanks for this promising project, and for the great patience with me. Your comments directed me to find out that my GOOGLE_CLIENTID was not set due to a typo, hence the /auth/google route was not added, hence the 403, perhaps the only logical possibility for my error.

403 Forbidden is default response for all routes of api except API endpoints. Because all API endpoints are mounted before Express route that sends 403 Forbidden: https://github.com/async-labs/saas/blob/master/api/server/app.ts

setupGoogle({ server, ROOT_URL });
setupPasswordless({ server, ROOT_URL });

api(server);

const http = new httpModule.Server(server);
realtime({ http, origin: URL_APP, sessionMiddleware });

server.get('/robots.txt', (_, res) => {
  res.sendFile(path.join(__dirname, '../static', 'robots.txt'));
});

server.get('*', (_, res) => {
  res.sendStatus(403);
});
stonesthatwhisper commented 4 years ago

Hey @stonesthatwhisper Out of curiosity can you log in using the email login after deploying to free Heroku Dynos? I could not log in at all using free dynos because Heroku doesn't let you set cookies on these.

No. Quite a few issues here all say we have to use our own domain.