the pros and cons of storing token in local storage
One of the common ways to store a token on the front end is local-storage with the benefit of larger store sizes than a cookie and operate without a server. But the method also bring XSS an CSRF attack concern, such as
<img src="http://domain.not.exist" onerror=alert(localStorage.getItem.token);>
another token storage possibility
XSS execute by script, CSRF works when the original cookie sent to origin URL from different domains. To add more difficulty to XSS and CSRF is httpOnly and sameSite setting in the cookie. The cookie secure parameter makes data only transfer over the HTTPS protocol, which makes MitM attack not easily execute.
prerequisite
- A React login page with GraphQL client
- ngrok in React root folder
- GraphQL server
conceptual code and setting
A. server side
code ./resolvers/mutation.js
async function login(parent, args, context, info) {
//...user email/password verification
const token = jwt.sign({ userId: user.id }, APP_SECRET)
const options = {
maxAge: 1000 * 60 * 15 , //expires in 15 minutes
httpOnly: true, // client can't get cookie by script
secure: true, // only transfer over https
sameSite: true, // only sent for requests to the same FQDN as the domain in the cookie
}
context.request.res.cookie('token', token, options)
//Can't get token at the first client login request
const returnToken = () => context.request.headers.cookie
let { userId } = jwt.verify(returnToken().replace('token=', ''), APP_SECRET)
if (userId === user.id) {
console.log('ok') //checking result on server console
return {
user, //send user information to client
}
}
throw new Error('Invalid request')
}
module.exports = { login }
please note the code can't get a cookie token at the first client request
B. Client-side
- add to the end of
code package.json
```
...
},
"proxy": "http://localhost:4000"
}
_After adding proxy and run on local, there will be a hosting error, which needs a configuration in .env. Remember to change your server API URL setting accordingly._
* `code .env`
DANGEROUSLY_DISABLE_HOST_CHECK=true
**The setting is dangerous as it named, please don't use it in production**
### C. Start project
* on server
`node index.js`
* on client
`npm start`
`.\ngrok.exe http 3000`
### D. Check result
1. copy the ngrok **https** URL to the browser, then run your login on the client, if setting success, you will see
* the result on the Application field. The httpOnly, secure field should be marked and sameSite field named with strict
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w5w5xwjhnhnuu25ratjq.png)
* an error on your server
`TypeError: Cannot read property 'replace' of undefined`
The reason is the login function can't send and get a cookie in the first client request.
2. send a login request again, there will be an `ok` on the server console, which means the server get token in the cookie.
3. The client will get user information after token verify. In the case is a todo page.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jiqcwk298gzbs6actmkl.png)
### E. test httpOnly/https effect
* httpOnly: you can write a javascript to get the cookie
import Cookies from 'js-cookie'
export const getToken = () => Cookies.get(AUTH_TOKEN);
* https: use localhost:3000 or ngrok Http URL to test
# Issues and [Reference](https://medium.com/@ryanchenkie_40935/react-authentication-how-to-store-jwt-in-a-cookie-346519310e81)
1. Solve cookie token res/req in a more efficient way
2. Set refresh cookie for a smooth user experience
3. how/where to store and transfer user data
Top comments (0)