Post

JWT

JWT

๐Ÿ“Œ JWT๋ž€?

JSON Web Token(JWT) ๋Š” ๋‘ ๊ฐœ์ฒด ๊ฐ„ JSON ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ์ •๋ณด๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์ด๋‹ค.

โ€˜์ธ์ฆโ€™ ๊ณผ์ •์—์„œ JWT๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•˜๋ฉด, ์„œ๋ฒ„๋Š” ์‚ฌ์šฉ์ž์˜ ์ •๋ณด์™€ ๊ถŒํ•œ์„ ๋‹ด์€ JWT๋ฅผ ๋ฐœ๊ธ‰ํ•œ๋‹ค. ์ดํ›„ ์‚ฌ์šฉ์ž๋Š” JWT๋ฅผ ํ†ตํ•ด ์ž์‹ ์„ ์ฆ๋ช…ํ•˜๊ณ , ์„œ๋ฒ„๋Š” JWT์˜ ์œ ํšจ์„ฑ๋งŒ ๊ฒ€์ฆํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“Œ ๊ตฌ์กฐ

image.png

JWT๋Š” โ€˜.โ€™์œผ๋กœ ๊ตฌ๋ถ„๋œ ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ๊ฐ ๋ถ€๋ถ„์€ Base64URL ๋กœ ์ธ์ฝ”๋”ฉ๋˜์–ด ์žˆ๋‹ค.

1
2
3
4
{
  "alg": "HS256", // ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜
  "typ": "JWT"    // ํ† ํฐ ํƒ€์ž…
}

ํ—ค๋”์—๋Š” ํ† ํฐ์˜ ์ข…๋ฅ˜์™€ ์„œ๋ช…์— ์‚ฌ์šฉ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ณด๋ฅผ ๋‹ด๋Š”๋‹ค.

Payload

1
2
3
4
5
6
{
  "sub": "user123",
  "username": "senior.dev",
  "role": "ADMIN",
  "exp": 1672531199
}

ํŽ˜์ด๋กœ๋“œ์—๋Š” ํ† ํฐ์— ๋‹ด์„ ์‹ค์ œ ์ •๋ณด์ธ claim ์„ ํฌํ•จํ•œ๋‹ค. ํด๋ ˆ์ž„์ด๋ž€ ํŽ˜์ด๋กœ๋“œ์— ๋‹ด๋Š” ๊ฐ ์ •๋ณด๋ฅผ ๋งํ•œ๋‹ค.

ํด๋ ˆ์ž„์—๋Š” ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์กด์žฌํ•œ๋‹ค.

Registered Claim ์€ ํ‘œ์ค€์œผ๋กœ ์ •์˜๋œ ํด๋ ˆ์ž„์ด๋‹ค. ํ•„์ˆ˜๋Š” ์•„๋‹ˆ๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

ํด๋ ˆ์ž„์„ค๋ช…
issํ† ํฐ ๋ฐœ๊ธ‰์ž
subํ† ํฐ์˜ ์ฃผ์ฒด
audํ† ํฐ ์ˆ˜์‹ ์ž
expํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„
iatํ† ํฐ ๋ฐœ๊ธ‰ ์‹œ๊ฐ„

Public Claim ์€ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด URI ํ˜•์‹์œผ๋กœ ์ด๋ฆ„์„ ์ง“๋Š” ํด๋ ˆ์ž„์ด๋‹ค.

Private Claim ์€ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ํ˜‘์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ํด๋ ˆ์ž„์ด๋‹ค.

ํŽ˜์ด๋กœ๋“œ๋Š” Base64URL๋กœ ์ธ์ฝ”๋”ฉ๋  ๋ฟ, ์•”ํ˜ธํ™”๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ˆ„๊ตฌ๋‚˜ ๋””์ฝ”๋”ฉํ•˜์—ฌ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ๊ฐ™์€ ๋ฏผ๊ฐ ์ •๋ณด๋Š” ๋‹ด์œผ๋ฉด ์•ˆ ๋œ๋‹ค.

signature

์„œ๋ช…์„ ํ†ตํ•ด ํ† ํฐ์˜ ์œ„์กฐ ์—ฌ๋ถ€, ๋ฐœ๊ธ‰์ž๊ฐ€ ์‹ ๋ขฐ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํ† ํฐ์˜ ๋ฌด๊ฒฐ์„ฑ๊ณผ ์ธ์ฆ์„ ๋ณด์žฅํ•œ๋‹ค.

ํ—ค๋”์™€ ํŽ˜์ด๋กœ๋“œ๋Š” Base64URL๋กœ ์ธ์ฝ”๋”ฉํ•œ ํ›„, ๋‘ ๋ฌธ์ž์—ด์„ โ€˜.โ€™์œผ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค. ์—ฐ๊ฒฐ๋œ ๋ฌธ์ž์—ด์„ ํ—ค๋”์— ๋ช…์‹œ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜(alg)์™€ ์„œ๋ฒ„์˜ ๋น„๋ฐ€ ํ‚ค๋ฅผ ํ†ตํ•ด ์•”ํ˜ธํ™”ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตฌํ•œ ๊ฐ’์ด ์„œ๋ช…์ด ๋œ๋‹ค.

๐Ÿ“Œ ๋™์ž‘ ๊ณผ์ •

  1. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
  2. ์„œ๋ฒ„๋Š” ์‚ฌ์šฉ์ž์˜ ์ž๊ฒฉ ์ฆ๋ช…์„ ํ™•์ธํ•˜๊ณ , ์„ฑ๊ณต ์‹œ ํ•„์š”ํ•œ ํด๋ ˆ์ž„์„ ๋‹ด์€ JWT๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์„œ๋ช…ํ•œ๋‹ค.
  3. ์ƒ์„ฑ๋œ JWT๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•œ๋‹ค.
  4. ํด๋ผ์ด์–ธํŠธ๋Š” JWT๋ฅผ ์•ˆ์ „ํ•œ ๊ณณ์— ์ €์žฅํ•œ๋‹ค.
  5. ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณดํ˜ธ๋œ API์— ์ ‘๊ทผํ•  ๋•Œ๋งˆ๋‹ค HTTP Authorization ํ—ค๋”์— Bearer ์Šคํ‚ด๊ณผ ํ•จ๊ป˜ JWT๋ฅผ ๋‹ด์•„ ๋ณด๋‚ธ๋‹ค.
  6. ์„œ๋ฒ„๋Š” ํ—ค๋”์—์„œ JWT๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๊ฒ€์ฆํ•œ๋‹ค.
  7. ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๋ฉด JWT์˜ ํŽ˜์ด๋กœ๋“œ์— ๋‹ด๊ธด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์‹ ๋ขฐํ•˜๊ณ  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๐Ÿ“Œ ์žฅ๋‹จ์ 

๊ฐ€์žฅ ํฐ ์žฅ์ ์€ ์„œ๋ฒ„๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋ฏ€๋กœ ์ˆ˜ํ‰์  ํ™•์žฅ์— ์œ ๋ฆฌํ•ด์ง„๋‹ค. ๋ถˆํ•„์š”ํ•œ DB ์กฐํšŒ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์–‘ํ•œ ๋„๋ฉ”์ธ ๊ฐ„ ์•ˆ์ „ํ•˜๊ฒŒ ์ •๋ณด๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ JWT๋Š” ์œ ํšจ๊ธฐ๊ฐ„ ๋™์•ˆ ์œ ํšจํ•˜๋ฉฐ, ๋งŒ์•ฝ ํƒˆ์ทจ๋˜๋ฉด ๋งŒ๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ณต๊ฒฉ์ž๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ฒŒ ์œ„ํ•ด Access Token์˜ ์œ ํšจ๊ธฐ๊ฐ„์„ ์งง๊ฒŒ ์„ค์ •ํ•˜๊ณ  Refresh Token์œผ๋กœ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰ํ•˜๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค.

๋˜ํ•œ ๋กœ๊ทธ์•„์›ƒ ๋“ฑ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ฐœ๊ธ‰๋œ ํ† ํฐ์„ ๋ฌดํšจํ™”ํ•ด์•ผ ํ•˜๋Š”๋ฐ, JWT๋Š” stateless์ด๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ํ† ํฐ์„ ๊ฐ•์ œ๋กœ ๋ฌดํšจํ™”ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ Blacklist๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋กœ๊ทธ์•„์›ƒ๋œ ํ† ํฐ์„ Redis ๋“ฑ์— ์ €์žฅํ•˜์—ฌ ํ™•์ธํ•˜๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค.

๐Ÿ“Œ ์ฐธ๊ณ 

https://ivory-room.tistory.com/88

This post is licensed under CC BY 4.0 by the author.