Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to serve an already authenticated client to browser? / How to protect api? #4569

Closed
mxhryvo opened this issue Jun 8, 2018 · 7 comments
Closed

Comments

@mxhryvo
Copy link

mxhryvo commented Jun 8, 2018

Hey guys,
thanks for this awesome project - I love to use it.
But now I wanted to make my API (express-server seperated from my custom next js server) more protected - so that its harder so send requests to api that don't come from the next js react-client. I don't want to use client side authentication to api with users - because non-registered users should access some parts of api, too.

How do I do that?

I thought of an "/auth" endpoint on API that can just be accessed from next js server and that gets the cookie with api token. But the next-server needs to pass that cookie or session to rendered client. The api token should be session-based

Or is there a better way? The goal is that you should just use Postman and GET-request to "http://api.com/getData" and use my api for your service or app. Of course its impossible to make it as secure as with user authentication - but I have an app that most people will use without registration.

I hope you could give me some hints and tips.
Thanks!

@vanya2h
Copy link

vanya2h commented Jun 11, 2018

If you want create truly-secured auth for users (unauthed users also can use your api) follow simple steps:

  1. Install jsonwebtoken (JWT) on your API server (https://www.npmjs.com/package/jsonwebtoken)
  2. Create your own auth express middleware with JWT api (parse token from cookies and decode)
  3. (*) If you want to make it accessible by unauthed users just check if request have token for further authentication
  4. Create /register end-point on your server which will accept login & password then add some salt for password (try https://github.com/davidwood/node-password-hash) and store it to your db
  5. On client-side create register form which sends login & password to /register end-point in raw form (use SSL for secured data transfers)
  6. Create authentication form. Using this form user will send login & password then grab with response your unique token (you will generate it on your server with JWT api)
  7. Store this token in cookies or wherever you want
  8. Create auth HOC for pages where you want create user authentication by token (if user have token create async response to your /verifytoken end-point in getInitialProps hook of your HOC)
  9. Deal with your secured data however you want (make a requests to your API with stored token then grab data if token is valid)
  10. Don't forget to use auth middleware on end-points

@mxhryvo
Copy link
Author

mxhryvo commented Jun 11, 2018

Thanks for your help.
Ok, besides I'm not really thinking about users on my app yet - some one could register a user and use the token in the cookies to get data from api forever, right?
But is it enough to just add a auth token for unauthed users? couldn't that be easily copied? I thought of a client token that gets regenerated every hour or at least day and passed to client on load(getInitialProps) and get hashed with a session based salt or something like that?

@josephluck
Copy link

You're right - when the user is given a token, they are able to use that token to retrieve data from your API if you allow them to do so. You can restrict the access level the token grants by encoding data in the JWT that identifies the user. You can use this information to restrict which API endpoints they are able to use.

Also, you can set your JWT token to expire whenever you like - you would also make it expire after every session if you need to, by setting a cookie through the express server.

@mxhryvo
Copy link
Author

mxhryvo commented Jun 13, 2018

Ok, but how can I serve the Next.js app with a periodically changing token, that is used to authenticated for a JWT? Because If its always the same, the "attacker" could just sniff the request and use the same password/token to get himself a JWT every time it expires. Just to make it a little bit harder.

Thanks for your help - I think I'm almost there :)

@vanya2h
Copy link

vanya2h commented Jun 14, 2018

JWT token also have "expired" field, so you can control it. For example, you can generate new token when it expires and send it to client. HOC pattern will be helpful here (every time send request for a new token to API).

@mxhryvo
Copy link
Author

mxhryvo commented Jun 14, 2018

But if I have a registered user I could get me a new JWT every time it expires easily - so that wouldn't protect from using the api from somewhere else than the client. And non registered users should just a have like a hashed secret in their request to get a JWT? I don't understand what would make it hard for others to use my api. thats why I thought of some kind of secret that just the client gets when Its rendered on server (getInitialProps) and which changes periodically. This would make the "attacker" or "sniffer" have to somehow get it out of the client every time. But a "simple" JWT endpoint could be contacted from everywhere especially if there is access for non-registered users(which should always be there).

is there something that I can do so that just the client is able to get a JWT from the api?

@timneutkens
Copy link
Member

There's been a lot of discussion on this in #153

@lock lock bot locked as resolved and limited conversation to collaborators Jan 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants