라이브러리: jsonwebtoken

hwisaac·2023년 3월 15일
0

공식문서

목록 보기
1/1

JSON Web Tokens의 구현입니다.

이는 draft-ietf-oauth-json-web-token-08를 기반으로 개발되었습니다. node-jws를 사용합니다.

설치

$ npm install jsonwebtoken

사용 방법

jwt.sign(payload, secretOrPrivateKey, [options, callback])

(비동기식) 콜백이 제공되면, 콜백은 err 또는 JWT로 호출됩니다.

(동기식) JsonWebToken을 문자열로 반환합니다.

  • payload는 유효한 JSON을 나타내는 객체 리터럴, 버퍼 또는 문자열일 수 있습니다.

참고하세요: exp 또는 기타 클레임은 payload가 객체 리터럴일 때만 설정됩니다. 버퍼나 문자열 페이로드는 JSON 유효성을 검사하지 않습니다.

payload가 버퍼나 문자열이 아닌 경우, JSON.stringify를 사용하여 문자열로 강제 변환됩니다.

secretOrPrivateKeyHMAC 알고리즘의 비밀 또는 RSAECDSAPEM 인코딩된 개인 키를 포함하는 문자열 (utf-8 인코딩), 버퍼, 개체 또는 KeyObject일 수 있습니다. 패스워드가 있는 개인 키의 경우 객체 { key, passphrase }를 사용할 수 있습니다(기반 crypto 문서), 이 경우 algorithm 옵션을 전달해야합니다.
RSA 알고리즘으로 서명할 때 최소 모듈러스 길이는 2048입니다. allowInsecureKeySizes 옵션이 true로 설정되어 있지 않은 경우 이 길이 이하의 개인 키는 오류로 거부됩니다.

options:

  • algorithm (기본값: HS256)
  • expiresIn: 초 단위 또는 시간 간격을 나타내는 문자열 vercel/ms.

예: 60, "2 days", "10h", "7d". 숫자 값은 초를 나타냅니다. 문자열을 사용하는 경우 시간 단위(일, 시간 등)를 반드시 제공해야 합니다. 그렇지 않으면 기본적으로 밀리초 단위가 사용됩니다("120"은 "120ms"와 같습니다).

  • audience
  • issuer
  • jwtid
  • subject
  • noTimestamp
  • header
  • keyid
  • mutatePayload: true로 설정하면, sign 함수는 페이로드 개체를 직접 수정합니다. 이것은 페이로드에 대해 클레임이 적용되지만 토큰으로 인코딩되기 전에 원시 참조가 필요한 경우에 유용합니다.
  • allowInsecureKeySizes: true로 설정하면 RSA에 대해 모듈러스 길이가 2048 미만인 개인 키를 사용할 수 있습니다.
  • allowInvalidAsymmetricKeyTypes: true로 설정하면 지정된 알고리즘과 일치하지 않는 비대칭 키를 허용합니다. 이 옵션은 역호환성을 위해 만들어졌으며 피하는 것이 좋습니다.
    expiresIn, notBefore, audience, subject, issuer에 대한 기본값은 없습니다. 이러한 클레임은 exp, nbf, aud, subiss를 사용하여 페이로드에 직접 제공할 수 있지만, 두 곳에 동시에 포함할 수는 없습니다.

exp, nbf 및 iat는 NumericDate입니다. 관련된 Token Expiration (exp claim)를 참조하세요.

헤더는 options.header 개체를 통해 사용자 정의할 수 있습니다.

생성된 jwtsnoTimestamp가 지정되지 않은 경우 기본적으로 iat(발행 시간) 클레임이 포함됩니다. iat이 페이로드에 삽입된 경우, options.expiresIn의 시간 간격을 주어진 경우 exp를 계산하는 데 실제 타임스탬프 대신에 사용됩니다.

동기적으로 서명 with default (HMAC SHA256)

var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');

동기적으로 서명 with RSA SHA256

// sign with RSA SHA256
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });

비동기적으로 서명

jwt.sign(
  { foo: 'bar' },
  privateKey,
  { algorithm: 'RS256' },
  function (err, token) {
    console.log(token);
  }
);

jwt를 30초 전으로 백데이트하기

var older_token = jwt.sign(
  { foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 },
  'shhhhh'
);

토큰 만료 (exp 클레임)

JWT의 표준은 만료를 나타내는 exp 클레임을 정의합니다. 만료는 NumericDate로 표시됩니다.

UTC 기준 1970-01-01T00:00:00Z부터 지정된 UTC 날짜/시간까지의 초 수를 나타내는 JSON 숫자 값입니다. 윤초를 무시합니다. 이는 IEEE Std 1003.1, 2013 Edition [POSIX.1] 정의인 "Epoch 이후 초 단위"와 동일하며, 각 날은 정확히 86400초로 계산됩니다. 그 외의 경우 비정수 값을 나타낼 수 있습니다. 자세한 내용은 RFC 3339 [RFC3339]를 참조하십시오.

즉, exp 필드는 epoch 이후의 초 수를 포함해야합니다.

1 시간 만료 기간이 있는 토큰 서명:

jwt.sign(
  {
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
    data: 'foobar',
  },
  'secret'
);

이 라이브러리로 이러한 토큰을 생성하는 또 다른 방법은 다음과 같습니다.

jwt.sign(
  {
    data: 'foobar',
  },
  'secret',
  { expiresIn: 60 * 60 }
);

// 또는 더 좋은 방법으로:
jwt.sign(
  {
    data: 'foobar',
  },
  'secret',
  { expiresIn: '1h' }
);

jwt.verify(token, secretOrPublicKey, [options, callback])

(비동기적) 콜백을 제공하면 함수가 비동기적으로 작동합니다. 서명이 유효하고 선택적 만료, 청중 또는 발급자가 유효한 경우 디코딩 된 페이로드로 콜백이 호출됩니다. 그렇지 않으면 오류가 발생합니다.

(동기적) 콜백이 제공되지 않은 경우 함수는 동기적으로 작동합니다. 시그니처가 유효하고 선택적으로 만료, 대상 청중 또는 발급자가 유효한 경우 디코딩된 payload를 반환합니다. 그렇지 않으면 오류를 throw합니다.

경고: 토큰이 믿을 수 없는 소스(예: 사용자 입력 또는 외부 요청)에서 가져온 경우, 반환된 디코딩된 payload는 다른 사용자 입력과 마찬가지로 처리해야합니다. 적절한 값만 필터링하고 작업해야합니다.

tokenJsonWebToken 문자열입니다.

secretOrPublicKeyHMAC 알고리즘의 비밀 또는 RSAECDSA를 위한 PEM으로 인코딩 된 공개 키를 포함하는 문자열(UTF-8 인코딩), 버퍼 또는 KeyObject입니다.
jwt.verify가 비동기식으로 호출되면 secretOrPublicKey은 비밀 또는 공개 키를 가져올 함수가 될 수 있습니다. 자세한 예는 아래를 참조하십시오.

이 댓글에서 언급했듯이, 기타 라이브러리에서는 base64로 인코딩 된 시크릿(랜덤 바이트를 base64로 인코딩한 것)을 요구하는 경우, Buffer.from(secret, 'base64')를 전달할 수 있습니다. 이렇게하면 시크릿은 base64로 디코딩되고 토큰 검증은 원래의 랜덤 바이트를 사용합니다.

options

  • algorithms: 허용된 알고리즘 이름 목록을 나열한 문자열입니다. 예를 들어 ["HS256", "HS384"].

지정하지 않으면 제공된 키 유형에 따라 기본값이 사용됩니다.
secret - ['HS256', 'HS384', 'HS512']
rsa - ['RS256', 'RS384', 'RS512']
ec - ['ES256', 'ES384', 'ES512']
기본값 - ['RS256', 'RS384', 'RS512']

  • audience: 대상 청중 (aud)을 확인하려면 여기에 값을 제공하십시오. 대상 청중은 문자열, 정규 표현식 또는 문자열 및/또는 정규 표현식 목록으로 확인할 수 있습니다.

예: "urn:foo", /urn:f[o]{2}/, [/urn:f[o]{2}/, "urn:bar"]

  • complete: 페이로드, 헤더 및 서명의 디코딩 된 { payload, header, signature } 객체를 반환하려면 일반적인 페이로드 내용만 반환하는 대신 여기에 값을 제공하십시오.
    issuer(선택 사항) : iss 필드의 유효한 값의 문자열 또는 문자열 배열입니다.
    jwtid(선택 사항): JWT ID (jti)를 확인하려면 여기에 문자열 값을 제공하십시오.
    ignoreExpiration: true이면 토큰의 만료를 검증하지 않습니다.
    ignoreNotBefore...
    subject: 여기서 주제 (sub)를 확인하려면 값을 제공하십시오.
    clockTolerance: 서로 다른 서버 간의 작은 시계 차이를 처리하기 위해 nbf 및 exp 클레임을 확인할 때 허용되는 초 수입니다.
    maxAge: 토큰이 여전히 유효한 최대 허용 연령입니다. 초 또는 시간 간격을 나타내는 문자열로 표시됩니다. vercel/ms을 참조하십시오.
    예: 1000, "2 days", "10h", "7d". 숫자 값은 초 카운트로 해석됩니다. 문자열을 사용하는 경우 시간 단위(일, 시간 등)를 반드시 제공해야 합니다. 그렇지 않으면 기본적으로 밀리초 단위가 사용됩니다 ("120""120ms"와 동일합니다).

clockTimestamp: 필요한 모든 비교에 대해 현재 시간으로 사용해야 하는 초 단위의 시간입니다.
nonce: 여기서 nonce 클레임을 확인하려면 문자열 값을 제공하십시오. Open ID에서 ID 토큰에 사용됩니다. (Open ID implementation notes)
-allowInvalidAsymmetricKeyTypes: true이면 지정된 알고리즘과 일치하지 않는 비대칭 키가 허용됩니다. 이 옵션은 역 호환성을 위해 사용됩니다. 지양하는 것이 좋습니다.

// 대칭 토큰 확인 - 동기식
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo); // bar

// 대칭 토큰 확인
jwt.verify(token, 'shhhhh', function (err, decoded) {
  console.log(decoded.foo); // bar
});

// 유효하지 않은 토큰 - 동기식
try {
  var decoded = jwt.verify(token, 'wrong-secret');
} catch (err) {
  // err
}

// 유효하지 않은 토큰
jwt.verify(token, 'wrong-secret', function (err, decoded) {
  // err
  // decoded undefined
});

// 비대칭 토큰 확인
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(token, cert, function (err, decoded) {
  console.log(decoded.foo); // bar
});

// 청중 확인
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(token, cert, { audience: 'urn:foo' }, function (err, decoded) {
  // 청중 불일치, err == invalid audience
});

// 발행자 확인
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(
  token,
  cert,
  { audience: 'urn:foo', issuer: 'urn:issuer' },
  function (err, decoded) {
    // 발행자 불일치, err == invalid issuer
  }
);

// jwt id 확인
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(
  token,
  cert,
  { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' },
  function (err, decoded) {
    // jwt id 불일치, err == invalid jwt id
  }
);

// 주제 확인
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(
  token,
  cert,
  {
    audience: 'urn:foo',
    issuer: 'urn:issuer',
    jwtid: 'jwtid',
    subject: 'subject',
  },
  function (err, decoded) {
    // 주제 불일치, err == invalid subject
  }
);

// 알고리즘 불일치
var cert = fs.readFileSync('public.pem'); // 공개 키 가져오기
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
  // 토큰 알고리즘이 RS256이 아닌 경우, err == invalid signature
});

// getKey 콜백을 사용하여 확인
// 예제는 https://github.com/auth0/node-jwks-rsa 를 사용하여 키를 가져오는 방법을 보여줍니다.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
  jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json',
});
function getKey(header, callback) {
  client.getSigningKey(header.kid, function (err, key) {
    var signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

jwt.verify(token, getKey, options, function (err, decoded) {
  console.log(decoded.foo); // bar
})

jwt.decode(token [, options])

(동기적) 시그니처가 유효한지 확인하지 않고 디코딩된 payload를 반환합니다.

경고: 이 함수는 시그니처가 유효한지 검증하지 않습니다. 신뢰할 수 없는 메시지에는 사용하지 마십시오. 대신 jwt.verify를 사용하는 것이 좋습니다.

경고: 토큰이 신뢰할 수 없는 소스(예: 사용자 입력 또는 외부 요청)에서 가져온 경우, 반환된 디코딩된 payload는 다른 사용자 입력과 동일하게 처리되어야 합니다. 예상되는 속성으로만 작업하도록 정리되었는지 확인하십시오.

tokenJsonWebToken 문자열입니다.

options:

  • json: 헤더가 "typ":"JWT"를 포함하지 않아도 페이로드에서 JSON.parse를 강제로 실행합니다.
  • complete: 디코딩된 페이로드와 헤더를 포함한 객체를 반환합니다.

예제

// 시그니처 무시하고 디코딩된 페이로드 가져오기, secretOrPrivateKey가 필요하지 않습니다.
var decoded = jwt.decode(token);

// 디코딩된 페이로드와 헤더 가져오기
var decoded = jwt.decode(token, { complete: true });
console.log(decoded.header);
console.log(decoded.payload);

오류 및 코드

검증 중 발생 가능한 오류입니다. 오류는 검증 콜백의 첫 번째 인수입니다.

TokenExpiredError

토큰이 만료되었을 때 발생하는 오류입니다.

오류 객체:

  • name: 'TokenExpiredError'
  • message: 'jwt expired'
  • expiredAt: [ExpDate]
jwt.verify(token, 'shhhhh', function (err, decoded) {
  if (err) {
    /*
      err = {
        name: 'TokenExpiredError',
        message: 'jwt expired',
        expiredAt: 1408621000
      }
    */
  }
});

JsonWebTokenError

오류 객체:

  • name: 'JsonWebTokenError'
  • message:
    • 'invalid token' - 헤더 또는 payload를 구문 분석 할 수 없음
    • 'jwt malformed' - 토큰에 3개의 구성 요소가 없음(점으로 구분됨)
    • 'jwt signature is required' - JWT에 서명이 필요함
    • 'invalid signature' - JWT 서명이 유효하지 않음
    • 'jwt audience invalid. expected: [OPTIONS AUDIENCE]' - JWT 수신자가 유효하지 않음
    • 'jwt issuer invalid. expected: [OPTIONS ISSUER]' - JWT 발급자가 유효하지 않음
    • 'jwt id invalid. expected: [OPTIONS JWT ID]' - JWT ID가 유효하지 않음
    • 'jwt subject invalid. expected: [OPTIONS SUBJECT]' - JWT 주제가 유효하지 않음
jwt.verify(token, 'shhhhh', function (err, decoded) {
  if (err) {
    /*
      err = {
        name: 'JsonWebTokenError',
        message: 'jwt malformed'
      }
    */
  }
});

NotBeforeError

nbf claim에 지정된 시간 이전에 현재 시간이면 발생합니다.

에러 객체:

  • name: 'NotBeforeError'
  • message: 'jwt not active'
  • date: 2018-10-04T16:10:44.000Z
jwt.verify(token, 'shhhhh', function (err, decoded) {
  if (err) {
    /*
      err = {
        name: 'NotBeforeError',
        message: 'jwt not active',
        date: 2018-10-04T16:10:44.000Z
      }
    */
  }
});

지원하는 알고리즘

지원하는 알고리즘의 배열입니다. 현재 다음 알고리즘이 지원됩니다.

alg Parameter ValueDigital Signature or MAC Algorithm
HS256HMAC using SHA-256 hash algorithm
HS384HMAC using SHA-384 hash algorithm
HS512HMAC using SHA-512 hash algorithm
RS256RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm
RS384RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm
RS512RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm
PS256RSASSA-PSS using SHA-256 hash algorithm (only node ^6.12.0 OR >=8.0.0)
PS384RSASSA-PSS using SHA-384 hash algorithm (only node ^6.12.0 OR >=8.0.0)
PS512RSASSA-PSS using SHA-512 hash algorithm (only node ^6.12.0 OR >=8.0.0)
ES256ECDSA using P-256 curve and SHA-256 hash algorithm
ES384ECDSA using P-384 curve and SHA-384 hash algorithm
ES512ECDSA using P-521 curve and SHA-512 hash algorithm
noneNo digital signature or MAC value included

JWT 재발급

먼저 JWT 자동 재발급이 시스템에 취약점을 도입하지 않는지 신중히 고려하는 것이 좋습니다.

라이브러리의 일부로 이것을 포함하는 것은 편하지 않지만, 이 예제를 살펴보면 이를 어떻게 수행할 수 있는지 알 수 있습니다. 이 외에도 이 주제에 대한 더 많은 지식을 얻을 수 있는 an issuea pull request가 있습니다.

0개의 댓글