Guardar token en almacenamiento local usando nodo

Estoy usando JWT ("jsonwebtoken": "^5.4.0") con Express 4 y jade. Puedo crear el token correcto, pero ¿cómo puedo pasar este token en cada llamada? ¿Dónde tengo que guardar este token? ¿En encabezados o en localStorage?

Por ahora estoy usando CURL con Postman, y Establecer token en el encabezado en

 x-access-token 

¿He creado un middleware que recupera un token de la base de datos y lo uso en cada llamada?

Gracias

No es necesario guardar y verificar el token de la base de datos. Este token, tal mecanismo se puede descodificar solo con su servidor, y si se hizo, el token es válido. El código que desea hacer debe ser similar.

 var cookieParser = require('cookie-parser') app.use(cookieParser()) app.get('/login', function(req, res, next) { var user = {name:'test'}; //!! find the user and check user from db then var token = jwt.sign(user, 'secret', { expiresInMinutes: 1440 }); res.cookie('auth',token); res.send('ok'); }); app.use(function(req, res, next) { var token = req.cookies.auth; // decode token if (token) { jwt.verify(token, 'secret', function(err, token_data) { if (err) { return res.status(403).send('Error'); } else { req.user_data = token_data; next(); } }); } else { return res.status(403).send('No token'); } }); 

Aquí puede encontrar un artículo muy bueno: https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens

Recomendaría verificar esto si desea almacenamiento local: https://www.npmjs.com/package/node-localstorage

Pero, dicho esto, chicos y chicas no creerían cuánto tiempo me tomó encontrar res.cookie('auth' token) de la respuesta anterior. Recorrí Google durante horas, documentos de Passport, documentos Express, GraphQL y documentos de autenticación / autorización en un esfuerzo por descubrir cómo llevar el token a la API de una manera sin estado .

Ya construí la seguridad de token JWT y aseguré mis resolutores GraphQL con él, pero luego opté por usar EJS junto con graphql-request (aproximadamente igual que el cliente Apollo), así que necesitaba encontrar una manera de pasar el token a mi middleware sin utilizando una sesión del lado del servidor.

El almacenamiento de un token JWT en cookies está bien, especialmente si toma precauciones adicionales, como firmar la cookie, y recuerdo que también hay opciones que puede incluir para mantener la cookie segura, de modo que otros sitios no puedan verla si el “navegador” permite el acceso. a las cookies. Si una cookie está firmada con el secreto de su servidor, los datos dentro de la cookie simplemente no se pueden modificar y seguir siendo válidos. El riesgo siempre sigue siendo alguien que pierde su token / cookie, y si eso te molesta, investiga sobre los tokens de actualización. Sin embargo, los tokens API son generalmente y deben mantenerse muy secretos y seguros. Es probable que su mayor molestia sea el requisito de mantener una lista negra de JWT que expiren dentro de un año si establece el vencimiento en 1 año.

Solo estoy incluyendo mis hallazgos aquí porque esta pregunta es en realidad un recurso raro que parece …

Aquí está mi middleware Express para la autenticación:

  // AUTHENTICATION app.use(async (req) => { try { const token = req.headers.authorization || req.cookies.auth const { person } = await jwt.verify(token, SECRET) req.person = person return req.next() } catch (e) { return req.next() } }) 
  1. Puede ver que estoy configurando el token del encabezado con cookie como alternativa. Esto es compatible con mis necesidades y me permite usar realmente cualquier cliente con seguridad sin estado.
  2. Mi usuario registrado está disponible como persona req.person en mis vistas y resolvedores GraphQL. Si no se establece req.person, se trata al usuario como no registrado.
  3. Estoy usando return req.next() que es importante tener en cuenta porque llamar a next() sin parámetros se trata como “limpiar el middleware siguiente y / o proceder a procesar la solicitud”. Si incluye cualquier cadena o parámetro de objeto, generará un error que puede reducirse a su middleware de manejo de errores. Puedes probarlo tú mismo. Ponga return next('You are not authenticated.') en el bloque catch y verá que detiene la solicitud antes de su ruta.
  4. Uso return next() porque manejo la autorización en las rutas y en mis resolutores. Permite que más usuarios no autenticados accedan a las mutaciones de registro y acceso.

Aquí está mi punto final GraphQL (estoy usando Apollo Server):

  app.use('/graphql', bodyParser.json(), graphqlExpress((req) => { const context = { person: req.person } return { schema, context, rootValue: null } })) 
  1. En mis resolutores GraphQL, el tercer parámetro de cada consulta tiene context.person req.person con req.person que viene del middleware de autenticación anterior.
  2. Eso es realmente todo lo que una persona necesita saber.

Aquí es cómo estoy usando el paquete NPM llamado graphql-request : https://www.npmjs.com/package/graphql-request

  app.get('/allpeople', async (req, res) => { try { const client = new GraphQLClient(GRAPHQL_ENDPOINT, { headers: { Authorization: req.headers.authorization || req.cookies.auth } }) const query = `query allPeople($serialNumber: String!) { allPeople(serialNumber: $serialNumber) { id created status email } }` const variables = { serialNumber: req.person } const response = await client.request(query, variables) res.render('allpeople/list', { people: response.allPeople }) } catch (e) { throw [`allPeople`, `${JSON.stringify(error, null, 2)}`] } }) 
  1. Incluyo este código porque no hay usos de ejemplo “más avanzados” de graphql-request, y me gusta hasta ahora. Es muy conciso y podría ser fácilmente intercambiado por Apollo Client si se aventura en React.js. Mis ejemplos aquí también son muy relevantes para cualquiera que esté investigando createNetworkInterface y el new ApolloClient() .