Let's imagine a client opens your nuxt.js website on the index page. From there, they authenticate (you used #nuxtjs/auth-next for that purpose). Then they move to a secure page that only authenticated users can see. This secure page is a .vue file in your "pages" folder with middleware: ["auth"].
Now, how is this page really secure ?
I mean, couldn't a malicious user temper with the page and access it without being authenticated anyway ? Because the "security" in this scenario is only implemented on the client side right ? [Edit]
Your application being an SPA at the end, if you want to bypass a middleware with it's security checkup, you could disable the JS on the page. But then, since no content is generated directly, you won't see anything because it's not here (as a static file).
If your app is isomorphic (basically has a ssr: true), the auth module will still disable the access to those pages (you can double check).
At the end, the critical info is received when:
you do have a valid JWT token (after some login)
you submit an HTTP query to the backend
the backend acknowledges it and the token is valid
the backend gives you the sensitive info via an HTTP response
At the end, your client side code doesn't need to be secure. If somebody somehow hacks your client side state and reaches the sensitive page, he will still not have a valid JWT token since the verification still happens on the backend.
The one that can be generated only when sending the proper credentials to the backend and having the backend validating those.
Now, how is this page really secure ?
The protected content is served from a request if a valid access token has been provided by the client.
The protected content is provided at runtime.
Because the "security" in this scenario is only implemented on the client side right ?
The security is not only implemented on the client side.
The premise is: The access token has been obtained securely through an authentication flow with an auth-server.
I recommend to read more about auth flows if this sounds unclear.
Auth0 has some good documentation on different flows.
https://auth0.com/docs/authorization/flows
Then, what is the best way to show a complex page to authenticated users only ?
The content is provided at run-time. Server-side or client-side.
There are some setup guides here for Nuxt.
Here is the first (Auth0) I found from the list.
https://auth.nuxtjs.org/providers/auth0
I don't know how updated those guides are, but the auth service providers tend to have updated guides themselves.
Related
I have been reading around CSRF for the past few days and feel like I have a good grasp on what it is and how to prevent it. I am building a small Express/React application that will have a secure admin area for updating the app content and I want it to be protected from CSRF.
I understand that it is common for the server to generate the CSRF token and then send it to the client along with the view (page) that has been requested (the token can then be hidden in a HTML form input tag). However, my Express API does not serve HTML, it is a REST API that only returns JSON data. The UI is built with React, running on a different port from the server.
My question is; Where do I securely store a token generated on the server?
For example, if I log in as admin by hitting '/api/login', generate a token, and send it back to the client in the API response, what should I do with it now?
The original plan was to use Redux to store the token but from reading this post Is Redux secure?, this does not sound ideal.
I considered using React env variables but have also read that these are exposed in the build.
Obviously localStorage is also a bad idea...
I am really struggling to find a solution to this problem using the tools I am implementing i.e. Express/React
Any help, links, advice, criticisms would be appreciate, I want to learn to build apps with security in mind
I understand that it is common for the server to generate the CSRF token
The server needs to generate two CSRF tokens
and then send it to the client along with the view (page) that has been requested (the token can then be hidden in a HTML form input tag).
One token is commonly sent as a cookie, another can be sent as HTTP header. It doesn't need to be sent inside HTML body as a HTML form input tag (or any other part of the body) though it can be sent this way.
My question is; Where do I securely store a token generated on the server?
You don't have to store a token on the server. You can but you don't need to.
The original plan was to use Redux to store the token
The Redux store is on the client, in browser's memory. In theory one React component (that extracts the second CSRF token from server response) can temporarily store the token in the store so that another React component can get it from there and put into the next request before it's sent to the server.
Obviously localStorage is also a bad idea...
Yes
Any help, links, advice, criticisms would be appreciate, I want to learn to build apps with security in mind
Links
With Express is very common to use this middleware. The steps can be found here.
Criticisms
This is strictly speaking off topic in the context of CSRF related Q/A, but ...
The UI is built with React, running on a different port from the server.
That hints to the possibility of using react-scripts which start webpack-dev-server. It's fine for development, not good for deployment in production. However this is a separate topic, serving React app's build artifacts (.html file, script bundles) to webclients has nothing to do with CSRF attack and its mitigation.
I want to learn to build apps with security in mind
Then you might consider using one webserver instead of two (frontend to serve React app and backend to serve API responses). Using one server results in production deployment which is not only less complex and costly, but also more secure because two servers have larger attack surface and with one server you don't need to weaken security by using CORS.
I'm using JWT authentication in my node site with passport and am not sure I am understanding the concepts.
Say I'm an authenticated user with my token saved in local storage. Say I then navigate to a /user page, which will display data about my user. Normally, I would check if the user is logged in, and if they are not, they would get redirected to a login page. But in this case, since I can't send the authentication token from a page request, I have to load my /user page, then the page makes a request for user data, and if the data is not found, I redirect them to the login page via javascript.
Am I correct in how I would handle this? It seems like a bad user experience, having to wait and redirect twice. Is there a way around this? Is JWT just not what I'm looking for my implementation?
If you want to render the page server side, you should set the JWT as a cookie instead of using local storage. You would be able to catch, verify and use it when a user request a page.
But I have to say that modern web applications use client side rendering. So there's no need to store the JWT as a cookie. When requesting a page, you will recieve only the static assets and you will get data by queryng an API that could response with 401 (Invalid or Expired Or Missing Token).
It seems you were using server side rendering before. Now you want to use JWT and you have read somewhere that a common practice is to store it in LocalStorage (that's true). Now you are dealing with a server side rendered application architecture while tryng to mix client side rndered applications concepts.
You are not doing huge errors, but you should consider to fully render your application server or client( I suggest ) side. For the second option, google "Build single page application"
I'm working with auth in Nextjs, I'm wondering what is the best strategy to handle authentication in NextJS ?
Here my services structure :
If I understand well I have to handle the server side rendering in NextJS, so I understand I have to put cookies from my external server to my NextJS client, then handle the server side rendering checkings. To do that I assume I have to create connection between the NextJS server and the other services. Before dive more deeper in the subject I would discuss with you about the possibilities available to me. It seems the NextJS auth is a subject in plain development.
Any hint would be great,
Thanks
I've recently added an example with cookie auth which explains what you are trying to do on the frontend.
For the backend, optimally you'll have your API in an external server, apart from the server you use for rendering your Next.js app. This API will handle the database and the token creation business. Then the basics of the authentication are like this:
The client POST a request with username and password to the server.
The server gets the request and generate a token based on the data received.
If everything went okay validating the data, the server responds with the token, e.g., { token: "secrettoken" }.
The client receives the token and saves it in a cookie. Optionally you redirect the user to the /dashboard or /profile if everything is okay.
The client, on restricted pages, will check if the cookie exists and optionally validate that against the server, you do this last part in getInitialProps. If the cookie validation fails you redirect the user away.
I've created a small library to abstract this logic.
So in the end, your Next.js app shouldn't know what's happening in the server, it only should receive the token, save it, validate it, and redirect the user if something is wrong.
How you want to handle the token creation, on the external server, is up to you.
Check out this thread. There are several examples of how to do Authentication with JWT, OAuth etc throughout the thread. You'll see that the examples are utilizing getInitialProps and there are several examples utilizing cookies throughout to extract the Authentication tokens.
You'll have to write a custom server.js file using express.js to serve the tokens through your route requests. I'm assuming by "external server" you mean some third party Authenticator using OAuth or OpenId protocols to retrieve tokens. If so, you're right to say that you'll need to request the tokens (or Authentication mechanism) from those external services and then decide how you're going to utilize them in your own client. You'll probably be using getInitialProps to do what you need to do with your Authentication tokens in the client once you are rendering to the browser.
More examples of Authentication here -- one for firebase and another for Apollo.
Just to add to the answers if you want to use Auth0 specifically. In the interview on http://www.fullstackradio.com/112 around the 1:06 min mark Guillermo Rauch mentioned that if he were to implement authentication all over again he would use Auth0, so I created a minimal repo using Auth0 and Nextjs with Serverless functions.
Like #jolvera suggested there is an API in an external server, apart from the server used for rendering the Next.js app. This API is located in ./auth/auth.js. It handles the token creation business, and could be extended to handle the database.
The HOC component in ./utils/withAuth.js calls the auth.js lambda for the user information, and is only able to retrieve it if the client side is authorized. Otherwise the user information is undefined. Additionally there is an event listener similar to the one in with-cookie-auth which syncs logouts across tabs.
Also one other note, don't get confused with the Nextjs example on Auth0's blog. That example is extending the Nextjs server, and isn't the solution you want if you are deploying Next to serverless. It doesn't have the separation of concerns with page routing and authentication.
There is a sensitive page in my website, so I want to authenticate visitors before they opening a link like: www.examples.com/builder.
I know if I use cookie based authentication everything will be simple, as the browser will send the credential message in cookies automatically. But in my situation, I have to use token based authentication. Browser don't send token if there is no pre-load script.
So my question is how to achieve token based authentication when someone open a sensitive page directly.
As far as I can understand,
you're looking for a way to avoid double roundtrips to send authentication headers to your web-service.
If I am correct, then this would only be possible via service worker which is a not widely supported feature. https://developers.google.com/web/fundamentals/primers/service-workers/
If, depending on your requirements, you can't go for service workers, then, the only left option is to use cookies.
I normally have a secondary authentication flow which uses cookies allowing a web service to authenticate a user on its first get request (the one made by the browser).
There are also some spa framework which implement routing resolvers but this will require a double roundtrip (1. load javascript, 2. send the token).
I have designed a simple HTML/CSS and JS/jQuery application, and now it's the moment of authentication integration. On the server side, I have done a REST API which allows clients to get some data. But, now I want to authenticate each request with access and/or session token.
I read many websites to find agreements or advice to establish security between the client (JS) and the REST API (PHP), but unfortunately I found nothing or not interesting.
So I ask you to enlighten me (if you want) to know what to do, what to implement, conventions, etc.
What I read:
Designing a Secure REST (Web) API without OAuth
Token Based Authentication for Single Page Apps (SPAs)
I cannot post more links according to my reputation...
Just give me advice, ways how to store private token (RSA) or access/session token for API.
Don't hesitate to give your reaction, and tell me if I'm not exact or something else.
You need to use a token-based authentication for your REST API. JWTs are the best in this particular case.
Why Use JSON Web Tokens?
Tokens are stateless. The token is self-contained and contains all the information it needs for authentication. This is great for scalability as it frees your server from having to store session state.
JWTs can be generated from anywhere. Token generation is decoupled from token verification allowing you the option to handle the signing of tokens on a separate server or even through a different company such us Auth0.
JWTs have fine-grained access control. Within the token payload you can easily specify user roles and permissions as well as resources that the user can access.
This will be your typical authentication flow process:
A user signs up/logs in, during the login process, you generate a JSON web token from the server and return it to the client. Since you are using PHP, you can use this library for the generation and signing of the token.
Store the JWT returned to the client on the browser Web Storage(local/session storage). It can also be stored in a cookie.
For subsequent HTTP requests from the client to the server, you send the token via headers/query, then the server validates the token. If it's valid, the user is authenticated otherwise the user is rejected.
BTW, if you don't want to implement authentication yourself, you can use Auth0, check out VanillaJS SPA and PHP quickstart
I hope this information helps. Cheers!
Authenticating REST API's with JavaScript front-ends is difficult because the JavaScript code is completely readable by anyone visiting the site so storing any kind of login credentials is no good.
With a standard Server to Server set-up simply using basic auth over HTTPS is more than enough but basic auth is no good for JavaScript SPA's as the credentials are in plain view.
For SPA's you need to be looking at JSON WebTokens, as your back end is in PHP you need to be looking at PHP-JWT from firebase. You can get the code here: https://github.com/firebase/php-jwt or recommended using composer:
composer require firebase/php-jwt
The package makes implementing JWT super simple see the docs for a complete code example. Also check out the JWT for a complete break down https://jwt.io/
I suppose Jwt (https://jwt.io/) is good solution for your question.
On the client side you can store the token on the localStorage or some global variable (for SPA).
You can transfer token on the HTTP header or as request parameter. It works.
Also you can see https://auth0.com/blog/angularjs-authentication-with-cookies-vs-token/