UNPKG

3.95 kBJavaScriptView Raw
1/**
2 * Módulo JWT
3 * @module index
4 */
5
6'use strict'
7
8const {jws: {JWS}} = require('jsrsasign')
9const uuidv4 = require('uuid/v4')
10const uuidv5 = require('uuid/v5')
11const debug = require('@tadashi/debug')('tadashi-jwt')
12const {matchClaims, parseJWT} = require('./lib/util')
13
14/**
15 * Environment variables
16 * @constant {string} [TADASHI_ALG='HS512'] - Algoritimo utilizado
17 * @constant {string} [TADASHI_ALG_ACCEPTABLE='HS512 HS256'] - Tipos de algoritimos aceitos na validação do JWT
18 * @constant {string} [TADASHI_SECRET_KEY_JWT='de66bd178d5abc9e848787b678f9b613'] - Segredo utilizado na geração e validação do JWT
19 */
20const {
21 TADASHI_ALG = 'HS512',
22 TADASHI_ALG_ACCEPTABLE = 'HS512 HS256',
23 TADASHI_SECRET_KEY_JWT = 'de66bd178d5abc9e848787b678f9b613'
24} = process.env
25
26const alg = TADASHI_ALG
27const algs = TADASHI_ALG_ACCEPTABLE
28
29/**
30 * Helper para criação de um id único
31 * @private
32 *
33 * @returns {string} UUID V5
34 */
35function _jti() {
36 const NAMESPACE = uuidv4()
37 return uuidv5(`tadashi_${Number(Date.now()).toString(26)}`, NAMESPACE)
38}
39
40/**
41 * Gera uma assinatura JWT (JSON Web Token)
42 *
43 * @param {object} payload - Carga de dados
44 * @param {object} [options={}] - Opções
45 * @param {number} [options.duration=0] - Tempo de vida do JWT (em segundos)
46 * @param {number} [options.useData=true] - Coloca o payload dentro da propriedade data
47 * @param {string} [options.iss] - Identificador do servidor ou sistema que emite o JWT
48 * @param {string} [options.aud] - Identifica os destinatários deste JWT
49 * @param {string} [options.sub] - Identificador do usuário que este JWT representa
50 * @param {string} [options.jti] - JWT ID
51 * @param {string} [secret=TADASHI_SECRET_KEY_JWT] - Segredo para gerar o JWT
52 * @returns {string} JWT
53 */
54function sign(payload, options = {}, secret = TADASHI_SECRET_KEY_JWT) {
55 const {duration = 0, useData = true} = options
56 const _claims = ['jti', 'iss', 'aud', 'sub']
57 const _header = {alg, typ: 'JWT'}
58
59 const tNow = Math.floor(Date.now() / 1000)
60 const tEnd = tNow + duration
61
62 const _payload = Object.create(null)
63
64 if (useData) {
65 _payload.data = payload
66 } else {
67 Object.keys(payload).forEach(k => {
68 _payload[k] = payload[k]
69 })
70 }
71
72 Object.keys(options).forEach(k => {
73 if (_claims.includes(k)) {
74 _payload[k] = options[k]
75 }
76 })
77
78 if (duration > 0) {
79 _payload.exp = tEnd
80 }
81
82 _payload.jti = _payload.jti || _jti()
83 _payload.iat = tNow
84 _payload.nbf = tNow
85
86 const sHeader = JSON.stringify(_header)
87 const sPayload = JSON.stringify(_payload)
88 const sSecret = {utf8: secret}
89 return JWS.sign(alg, sHeader, sPayload, sSecret)
90}
91
92/**
93 * Verifica se o JWT é válido
94 *
95 * @param {string} jwt - JWT (JSON Web Token)
96 * @param {object} [options={}] - Opções (obligatory claims)
97 * @param {string} [secret=TADASHI_SECRET_KEY_JWT] - Segredo para gerar o JWT
98 * @returns {boolean} Retorna true ou false
99 */
100function verify(jwt, options = {}, secret = TADASHI_SECRET_KEY_JWT) {
101 try {
102 const sSecret = {utf8: secret}
103 const fields = Object.keys(options)
104 const claims = Object.create(null)
105 fields.forEach(k => {
106 claims[k] = options[k].split(' ')
107 })
108 claims.alg = algs.split(' ')
109 if (matchClaims(jwt, fields)) {
110 return JWS.verifyJWT(jwt, sSecret, claims)
111 }
112 return false
113 } catch (err) {
114 debug.error('verifyJWT', err.message)
115 return false
116 }
117}
118
119/**
120 * Faz o parse do JWT (JSON Web Token)
121 *
122 * @param {string} jwt - JWT (JSON Web Token)
123 * @returns {?object} O objeto contendo o cabeçalho e carga de dados
124 */
125function parse(jwt) {
126 try {
127 return parseJWT(jwt)
128 } catch (err) {
129 debug.error('parseJWT', err.message)
130 return null
131 }
132}
133
134exports.sign = sign
135exports.verify = verify
136exports.parse = parse