[Go] Package jwt

Package jwt

Jason Web Token

Table of Contents

JWT Basic

JWT 가 유용하게 사용되는 경우는 아래와 같다.

JWT 구조

JWT 는 세 파트로 나뉜다.

  1. Header
  2. Payload
  3. Signature

중요한 정보는 header 와 payload 에 적재해서는 안된다.

반면 Signature(Header + Payload + Signature Key)은 복호화 되어 있기에 Signature Key를 모른다면 해석불가.

JWT Structure

각각의 JSON 형태의 데이터를 base64로 인코딩한 후 합친다(header.payload.signature).

jwt-structure

Encoded JWT

JSON은 개행 문자가 있다. 이는 base64로 인코딩 되면서 사라진다.

jwt-encoded

Decoded JWT

jwt-decoded

토큰의 타입과 사용하는 해싱 알고리즘의 정보가 담겨 있다.

Payload

토큰으로 사용하려는 실질적인 데이터가 담겨 있다.
한 토큰에는 여러개의 Claim들로 이루어져 있다. Claim은 데이터의 조각이라 보면 된다.

Claim 의 세 종류

  1. Reserved Claim
    예약된 클레임
    이름이 이미 예약되어 정해진 클레임들
  2. Public Claim
    공개 클레임
    서버-클라이언트 협의하에 사용되는 공개 클레임
    클레임 이름 충돌 방지를 위해 URI 형식으로 이름을 명명한다.
  3. Private Claim
    비공개 클레임
    서버-클라이언트의 협의하에 사용되는 비공개 클레임

↑ return to TOC

Signature

Header + Payload + Signature Key
토큰의 무결성과 변조를 방지하기 위해 사용되는 서명.

↑ return to TOC

JWT 인증

JWT 발급

JWT 사용

jwt 코드 열어보기

MapClaims

type MapClaims map[string]interface{}

↑ return to TOC

SigningMethodHMAC

HMAC-SHA 알고리즘 구현

이 외의 알고리즘 종류는 에러(signature is invalid)를 리턴한다

↑ return to TOC

Parser

type Parse struct {
    ValidMethods           []string
    UseJSONNumber          bool
    SkipClaimsValidation   bool
}

↑ return to TOC

jwt.New

새 토큰 생성시 사용.
method인자에 암호화 할 알고리즘 종류를 전달해준다.

func New(method SigningMethod) *Token {
  return NewWithClaims(method, MapClaims{})
}

↑ return to TOC

jwt.Parse

func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
  return new(Parser).Parse(tokenString, keyFunc)
}

↑ return to TOC

jwt.Valid

토큰의 유효성을 확인한다.
클레임의 exp, iat, nbf로 토큰의 유효기간을 판별.

if m.VerifyExpiresAt(now, false) == false { vErr.Inner = errors.New(“Token is expired”) vErr.Errors |= ValidationErrorExpired }

if m.VerifyIssuedAt(now, false) == false { vErr.Inner = errors.New(“Token used before issued”) vErr.Errors |= ValidationErrorIssuedAt }

if m.VerifyNotBefore(now, false) == false { vErr.Inner = errors.New(“Token is not valid yet”) vErr.Errors |= ValidationErrorNotValidYet }

if vErr.valid() { return nil }

return vErr }

[↑ return to TOC](#table-of-contents)


### jwt.VerifyExpiresAt
```exp```과 ```cmp``` 의 비교를 통해 유효기간을 판별.  
```go
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
  switch exp := m["exp"].(type) {
  case float64:
     return verifyExp(int64(exp), cmp, req)
  case json.Number:
     v, _ := exp.Int64()
     return verifyExp(v, cmp, req)
  }
  return req == false
}

↑ return to TOC

jwt.VerifyIssuedAt

iatcmp 의 비교를 통해 유효기간을 판별. 와

func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
  switch iat := m["iat"].(type) {
  case float64:
     return verifyIat(int64(iat), cmp, req)
  case json.Number:
     v, _ := iat.Int64()
     return verifyIat(v, cmp, req)
  }
  return req == false
}

↑ return to TOC

jwt.VerifyNotBefore

nbfcmp 의 비교를 통해 유효기간을 판별.

func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
  switch nbf := m["nbf"].(type) {
  case float64:
     return verifyNbf(int64(nbf), cmp, req)
  case json.Number:
     v, _ := nbf.Int64()
     return verifyNbf(v, cmp, req)
  }
  return req == false
}

↑ return to TOC