JWT ์ ๋ํ ์ดํด
์ด์ ๊ธ์์ ์ด์ด์ง๋ ๋ด์ฉ
๋ชจ์ ํดํน ์คํฐ๋ - ๊ธฐ๋ก์ผ์ง 03์ฃผ์ฐจ (๋ก๊ทธ์ธ ๋ก์ง/๋ก๊ทธ์ธ ์ ์ง)
๋ชจ์ ํดํน ์คํฐ๋ - ๊ธฐ๋ก์ผ์ง 03์ฃผ์ฐจ (๋ก๊ทธ์ธ ๋ก์ง/๋ก๊ทธ์ธ ์ ์ง)
๋ก๊ทธ์ธ ๋ก์ง(๋ก๊ทธ์ธ ๊ณผ์ )๊ณผ ๋ก๊ทธ์ธ ์ ์ง ๋ฐฉ๋ฒ์ ๋ํ ์ดํด ๋ก๊ทธ์ธ์ด๋ ๋ฌด์์ธ๊ฐ? ๋ค์ค ์ฌ์ฉ์ ์์คํ ์ ์ฌ์ฉํ๊ธฐ ์ํ์ฌ ์ปดํจํฐ์ ์ฌ์ฉ์์์ ์๋ฆฌ๋์ผ (์ฆ, ์ปดํจํฐ๊ฐ ๊ทธ ์ฌ๋์ด ๋ง๋์ง๋ฅผ ํ์ธ
codegear-archive.tistory.com
์ JWT์ผ๊น?
์์ ๋ณด์๋ฏ์ด ์ธ์ฆ์ ์ํด Cookie์ Session์ ์ฌ์ฉํ๊ณ , ๊ทธ ํ๊ณ์ , ๋ณด์์ฑ์ ๋ฌธ์ ๊ฐ ์กด์ฌ
์ฟ ํค์ ์ธ์ ์ ๋จ์ ์ ๋ํ์ฌ ์ข ๋ ์ดํด ๋ณด์๋ฉด...
์ฟ ํค(Cookie)
๋ก๊ทธ์ธ ํ์ ๋ Set-Cookie์ ํํ๋ก ๋ฐํ์ ๋ฐ์ ์ฟ ํค๋ฅผ ํ ๋๋ก ๋ก๊ทธ์ธ์ด ํ์ํ ์์ฒญ๋ง๋ค ์ฟ ํค๋ฅผ ๋์ ธ ๋์
(์ฟ ํค๋ฅผ ์ฌ์ฉํ ์ด์ ๋ ์ด๋ค ํน์ ์ ๋ณด๋ฅผ ์ ์ฅํด์ผ ํ๊ธฐ ๋๋ฌธ, ๋งค๋ฒ ์์ฒญ๋ง๋ค ์ฌ์ฉ์๊ฐ ํน์ ์ ๋ณด๋ฅผ ๋ ๋ ค์ผํ๋ ๋ฒ๊ฑฐ๋ก์์ ๋ง๊ธฐ ์ํด)
ํ์ง๋ง ๋ง์ ๋จ์ ์ด ์กด์ฌ
- ์ฟ ํค๋ ๋ ธ์ถ๋์์๋ id, pw์ ๊ฐ์ ๋ฏผ๊ฐ ์ ๋ณด๊น์ง ๋ค ๋ ธ์ถ๋์ด ๋ณด์์ด ์ข์ง ๋ชปํจ
- ์กฐ์๋นํด์ ๋ค์ด์ฌ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌ
- ์น ๋ธ๋ผ์ฐ์ ๋ง๋ค ์ฟ ํค์ ๋ํ ์ง์ ํํ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๊ฐ์ ๊ณต์ ๊ฐ ๋ถ๊ฐ๋ฅ
- ์ฟ ํค์ ์ฌ์ด์ฆ๊ฐ ์ ํ(4KB)๋์ด ์์ด ์ํ๋ ๋งํผ์ ์ถฉ๋ถํ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์กด์ฌ
- ์๋ฒ๋ ๋งค๋ฒ id, pw๋ฅผ ๋ฐ์์ ์ธ์ฆํด์ผ ํ๋ ๋ถํธํจ์ด ์กด์ฌ
- (๋ํ ์กฐ์๋ ๋ฐ์ดํฐ๊ฐ ๋์ด์ค๋ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํ ์ ์์)
์์ ๋จ์ ์ ๋ณด์ํ๊ณ ์ ์ฟ ํค(Cookie)์ ํจ๊ป ์ธ์ (Session)์ ์ฌ์ฉ
์ฟ ํค(Cookie) &์ธ์ (Session)
๋ฌด์ธ๊ฐ์ ๋ํ ํน์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ฒ๊ฐ ๊ฐ์ง๊ณ ์๊ณ , ๊ทธ ๊ฐ์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ์ฌ ์ธ์ฆ
(๋ง์น ํค๋ฅผ ์ฃผ๊ณ ์๋ฌผ์ ๋ฅผ ์ฌ๋ ๋ฐฉ์) - ์ธ์ ID๋ฅผ ํน์ ์ ์ฅ์์ ์ ์ฅํ์ฌ ์ฌ์ฉ
- ๊ฐ์ธ ๋ฏผ๊ฐ์ ๋ณด๋ฅผ ๊ทธ๋๋ก ๋ ธ์ถํ์ ๋์ ๋จ์ ์ ๋ง์๋ด๊ธฐ ์ํด ๋์จ ๊ฒ์ด ๋ฐ๋ก ์ธ์ (Session)
- ์ฟ ํค์์ ๋ฃ์ด์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ์ฟ ํค๋ผ๋ ์ ๋ณด ์์ฒด๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ค๋ ์ฌ์ค์ ํฌ๊ฒ ๋ค๋ฅด์ง ์์
- (id, pw์ ๊ฐ์ ๋ฏผ๊ฐ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ ์ํฉ์์์ ๋ณด์์ ์ ์ฐพ๊ธฐ ์ํด ๋์จ ๊ฒ)
- ์ฟ ํค์ ๊ฐ์ ๋งค๊ฐ์ฒด๋ฅผ ์ฃผ๊ณ ๋ฐ์์ผ๋ก์จ ๋งค๋ฒ ๋ก๊ทธ์ธ ์ id, pw๋ฅผ ์์ฑํ์ฌ ์ ๋ฌํด์ผํ๋ ๋ฒ๊ฑฐ๋ก์์ ๋ณด์
- id, pw๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ด ์๋๋ผ, ์ธ์ฆ ์ ๋ณด ์์ฒด๋ฅผ ํน์ ์ธ์ ์ ์ฅ์์ ์ ์ฅํ๊ณ ,
- ์ด ๊ฐ์ ์ฟ ํค์ ๋ด์ ํด๋ผ์ด์ธํธ๊ฐ ์ฟ ํค๋ฅผ ์์ฒญํ ๋๋ง๋ค ์ธ์ ์ ์ฅ์์ ์๋ ์ ๋ณด๋ ๋์ผํ์ง๋ก ๋ก๊ทธ์ธ์ ํ์ธํ์๋ ๊ฒ
์ธ์ ์ ์ด์ฉํ ์ธ์ฆ ์ ์ฐจ
1. ํด๋ผ์ด์ธํธ๊ฐ id / pw๋ก ์๋ฒ์ ๋ก๊ทธ์ธ ์์ฒญ์ ํจ
2. id / pw๋ก ์ธ์ฆ ํ ์ฌ์ฉ์๋ฅผ ์๋ณํ ํน์ ์ ๋ํฌํ ์ธ์ ID๋ฅผ ๋ง๋ค์ด ์๋ฒ์ ์ธ์ ์ ์ฅ์์ ์ ์ฅ
3. ์ธ์ ID๋ฅผ ํน์ ํ ํํ(์ฟ ํค or json)๋ก ํด๋ผ์ด์ธํธ์ ๋ค์ ๋ฐํ
4. ์ฌ์ฉ์ ์ธ์ฆ์ด ํ์ํ ์ ๋ณด๋ฅผ ์์ฒญํ ๋๋ง๋ค ์ด ์ธ์ ID๋ฅผ ์ฟ ํค์ ๋ด์ ์๋ฒ์ ํจ๊ป ์ ๋ฌ
5. ์ธ์ฆ์ด ํ์ํ api์ ๊ฒฝ์ฐ, ์๋ฒ๋ ์ธ์ ID๊ฐ ์ธ์ ์ ์ฅ์์ ์๋์ง ํ์ธ
6. ์๋ค๋ฉด ์ธ์ฆ ์๋ฃ ํ api ์ฒ๋ฆฌ, ์๋ค๋ฉด 401 ์๋ฌ๋ฅผ ๋ฐํ
- ์ฟ ํค๋ง์ ์ ์กํ ๋์๋ ๋ค๋ฅด๊ฒ ์ธ์ ์ ์ฅ์์ ์๋ณ ๊ฐ๋ฅํ ๊ฐ์ ๋ฃ์ด๋๊ณ ๊ทธ ๊ฐ์ด ์ผ์นํ๋์ง๋ง ๋ณด๋ฉด ์ธ์ฆ์ด ๋๋ ๋ณด์์ด ์กฐ๊ธ์ ์ฌ๋ผ๊ฐ๋ค๊ณ ๋ณผ ์ ์์
- ๋ง์ฝ ๋ณด์ ๋ฌธ์ ๊ฐ ๋ฐ์(ํ์ทจ ๋นํ ์ธ์ ID) ํ๋ค๋ฉด, ๊ทธ๋ฅ ์ธ์ ์ ์ฅ์๋ฅผ ์ ๋ถ ์ง์๋ฒ๋ฆฌ๋ฉด ๋จ.
- (์ธ์ ID๊ฐ ํ์ทจ๋นํ์ด๋ ์ธ์ ์ ์ฅ์๋ฅผ ์ ๋ถ ๋น์ฐ๋ฉด, ํด๋น ์ธ์ ID๋ก ์๋ฒ์ ์ ๊ทผํด๋ ์ธ์ฆ๋ ์๋จ์ด ์์)
- BUT ๋ค๋ฅธ ๊ด์ ์์ ๋ณธ๋ค๋ฉด, ์ธ์ ์ ์ฅ์๊ฐ ๋ชจ์ข ์ ์ด์ ๋ก ์ฅ์ ๊ฐ ๋๋ค๋ฉด ์ธ์ฆ ์ ์ฒด์ ๋ฌธ์ ๊ฐ ์๊ฒจ ์ ์์ ์ธ ์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ํ์ง ๋ชปํ๊ฒ๋๋ค๊ณ ๋ณผ ์๋ ์์
- ๋ํ HTTP์ ์ฅ์ ์ด๋ผ ํ ์ ์๋ ๋ฌด์ํ์ฑ(stateless)์ ์ํด ์๋ฒ์ ์ธ์ ์ ์ฅ์์ ์ธ์ ID, ์ฆ ์ํ๋ฅผ ์ ์ฅํ๋ ์ํฉ์ด๊ธฐ ๋๋ฌธ์ stateful ํ๊ฒ ๋๋ ๊ฒ
ํ์ฌ ์ฟ ํค์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ ๋จ์ ์ด ์กด์ฌ
- ์ธ์ ์ ์ฅ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ธ์ฆ ์ฒด๊ณ๊ฐ ๋ฌด๋์ ธ ์ด์ ์ ์ธ์ฆ๋ ๋ค๋ฅธ ์ ์ ๋ํ ์ธ์ฆ์ด ๋ถ๊ฐํด ์ง
- stateful ํ๊ธฐ ๋๋ฌธ์ http์ ์ฅ์ ์ ๋ฐํ ํ์ง ๋ชปํจ scale out์ ๊ฑธ๋ฆผ๋์ด ๋จ
- (์์ ํ ๋ฌด์ํ์ฑ(stateless)์ด๋ผ๊ณ ๋ณผ ์ ์์)
- ์ธ์ ์ ์ฅ์๊ฐ ํ์์ ์ผ๋ก ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์์์ด ์๋ชจ๋จ
- ์ธ์ ID๊ฐ ํ์ทจ๋์์ ๊ฒฝ์ฐ ๋์ฒ๋ ๊ฐ๋ฅํ์ง๋ง, ํด๋ผ์ด์ธํธ ์ธ์ฒ ์์ฅํ๋ ๋ณด์ ์ทจ์ฝ์ ์ด ์กด์ฌ
- ์ฌ์ฉ์๊ฐ ๋ง์์ง์๋ก ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์ง(๋ง์ ์์์ ์๋ชจ)
- ๋งค๋ฒ ์์ฒญ์ ์ธ์ ์ ์ฅ์๋ฅผ ์กฐํํด์ผ ํ๋ค๋ ๋จ์
- (์์ฒญ์ ์งํํ ๋๋ง๋ค DB ์ ๊ทผ์ด๋ผ๋ ๋ก์ง์ด ํ๋ฒ ๋ ์ํ๋๋ค๋ ๊ฒ)
์์ ๊ฐ์ ์ผ๋ จ์ ๊ณผ์ (์ฟ ํค์ ์ธ์ ์ ํ๊ณ์ ) ์์์ ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก JWT
JWT ๋? - JSON ์น ํ ํฐ(JSON Web Token)
JSON Web Token (JWT) ์ ์นํ์ค (RFC 7519) ์ผ๋ก์, ๋ ๊ฐ์ฒด์์ JSON ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ณ๊ณ ์๊ฐ์์ฉ์ ์ธ (self-contained) ๋ฐฉ์์ผ๋ก ์ ๋ณด๋ฅผ ์์ ์ฑ ์๊ฒ ์ ๋ฌ
- (์ ํ์ ์๋ช ๋ฐ ์ ํ์ ์ํธํ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ธํฐ๋ท ํ์ค ์ธ์ฆ ๋ฐฉ์)
- C, Java, Python, C++, R, C#, PHP, JavaScript, Ruby, Go, Swift ๋ฑ ๋๋ถ๋ถ์ ์ฃผ๋ฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ์ง์
- JWT ๋ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ์์ฒด์ ์ผ๋ก ์ง๋๊ณ ์์ (= Self-contained)
- JWT ์์คํ ์์ ๋ฐ๊ธ๋ ํ ํฐ์, ํ ํฐ์ ๋ํ ๊ธฐ๋ณธ์ ๋ณด, ์ ๋ฌ ํ ์ ๋ณด, ๊ทธ๋ฆฌ๊ณ ํ ํฐ์ด ๊ฒ์ฆ๋๋ค๋๊ฒ์ ์ฆ๋ช ํด์ฃผ๋ signature ๋ฅผ ํฌํจ
- JWT ๋ ์๊ฐ์์ฉ์ ์ด๋ฏ๋ก, ๋ ๊ฐ์ฒด ์ฌ์ด์์ ์์ฝ๊ฒ ์ ๋ฌ ๊ฐ๋ฅ
- ์น์๋ฒ์ ๊ฒฝ์ฐ HTTP์ ํค๋์ ๋ฃ์ด์ ์ ๋ฌ ํ ์๋ ์๊ณ , URL ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ ํ ์๋ ์์
- ํ ํฐ์ ๋น๊ณต๊ฐ ์ํฌ๋ฆฟ ํค ๋๋ ๊ณต๊ฐ/๋น๊ณต๊ฐ ํค๋ฅผ ์ฌ์ฉํ์ฌ ์๋ช
๋จ
- ์ด ํ ํฐ๋ค์ ํ์ชฝ ๋น์ฌ์์ ๋น๊ณต๊ฐ ํค(์ผ๋ฐ์ ์ผ๋ก ์๋ฒ์ ๋น๊ณต๊ฐ ํค)์ ์ํด ์๋ช ์ด ๊ฐ๋ฅํ๋ฉฐ ์ด๋ก์จ ํด๋น ๋น์ฌ์๋ ์ต์ข ์ ์ผ๋ก ํ ํฐ์ด ์ ๋ฒํ์ง๋ฅผ ํ์ธํ ์ ์์
๊ธฐ๋ณธ์ ์ธ ์ธ์ฆ์ ์งํํ๋ ๊ตฌ์กฐ๋ Cookie ๋์ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ง๋ง,
๊ฐ์กฐ๋๋ ์ ์ JWT๋ ์๋ช ๋ ํ ํฐ์ด๋ผ๋ ์
JWT์ ์ฌ์ฉ
- ํ์์ธ์ฆ : JWT๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์ฅ ํํ ์๋๋ฆฌ์ค
- ์ ์ ๊ฐ ๋ก๊ทธ์ธ ํ๋ฉด, ์๋ฒ๋ ์ ์ ์ ์ ๋ณด์ ๊ธฐ๋ฐํ ํ ํฐ์ ๋ฐ๊ธํ์ฌ ์ ์ ์๊ฒ ์ ๋ฌ
- ๊ทธ ํ, ์ ์ ๊ฐ ์์ฒญ์ ํ ๋๋ง๋ค JWT๋ฅผ ํฌํจํ์ฌ ์ ๋ฌ
- ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ์ ์์ฒญ์ ๋ฐ์๋ ๋ง๋ค, ํด๋น ํ ํฐ์ด ์ ํจํ๊ณ ์ธ์ฆ๋์ด์๋์ง ๊ฒ์ฆ
- ์ ์ ๊ฐ ์์ฒญํ ์์ ์ ๊ถํ์ด ์๋์ง ํ์ธํ์ฌ ์์ ์ ์ฒ๋ฆฌ
- ์๋ฒ์ธก์์๋ ์ ์ ์ ์ธ์ ์ ์ ์งํ ํ์๊ฐ ์์ด์ง
- (์ฆ, ์ ์ ๊ฐ ๋ก๊ทธ์ธ ๋์ด์๋์ง ์๋์ด์๋์ง๋ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๊ณ , ์ ์ ๊ฐ ์์ฒญ ํ์๋๋ง ํ ํฐ์ ํ์ธํ๋ฉด๋๊ธฐ ๋๋ฌธ์ ์ธ์ ๊ด๋ฆฌ๊ฐ ํ์ ์์ด ์๋ฒ์์์ ๋ง์ด ์๋ ์ ์์)
- ์ ๋ณด ๊ต๋ฅ : JWT๋ ๋ ๊ฐ์ฒด ์ฌ์ด์์ ์์ ์ฑ ์๊ฒ ์ ๋ณด๋ฅผ ๊ตํํ๊ธฐ์ ์ข์ ๋ฐฉ๋ฒ
- ๊ทธ ์ด์ ๋ ์ ๋ณด๊ฐ sign์ด ๋์ด์๊ธฐ ๋๋ฌธ์ ์ ๋ณด๋ฅผ ๋ณด๋ธ์ด๊ฐ ๋ฐ๋์ง ์์๋์ง, ๋ ์ ๋ณด๊ฐ ๋์ค์ ์กฐ์๋์ง๋ ์์๋์ง ๊ฒ์ฆ ๊ฐ๋ฅ
JWT์ ๊ตฌ์กฐ
JWT๋ Header . PayLoad . Signature์ ์ธ ๋ฉ์ด๋ฆฌ๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, ๊ฐ ๋ถ๋ถ์ ์ (.)์ผ๋ก ์ฐ๊ฒฐ
ํ๋จ์ ํ ์คํธ๊ฐ ํ๋์์ผ๋ก Signature Verified ๋ผ๊ณ ๋จ๋ฉด JWT ํ ํฐ์ด ๊ฒ์ฆ๋์๋ค๋ ๊ฒ !
ํค๋(header)
์๊ณ ๋ฆฌ์ฆ์ ํ์์ ๊ธฐ์ ํ๋ ๋ถ๋ถ
{
"alg" : "HS256",
"typ" : "JWT"
}
- alg : ํด์ฑ ์๊ณ ๋ฆฌ์ฆ ์ง์ (์๋ช
์์ฑ์ ์ํด ์ด๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ์ง๋ฅผ ์๋ณ)
- HS256๋ ์ด ํ ํฐ์ด HMAC-SHA256๋ฅผ ์ฌ์ฉํ์ฌ ์๋ช ๋จ์ ์๋ฏธ
- ์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฐ์ด๋ ์ํธํ ์๊ณ ๋ฆฌ์ฆ
- SHA-2(HS256) ๋ฐฉ์์ HMAC์ SHA-256(RS256) ๋ฐฉ์์ RSA ์๋ช
- (์ด ์๊ณ ๋ฆฌ์ฆ์ ํ ํฐ์ ๊ฒ์ฆํ ๋ ์ฌ์ฉ๋๋ signature ๋ถ๋ถ์์ ์ฌ์ฉ๋จ)
- typ : ํ ํฐ์ ํ์ ์ ์ง์ - JWT
์ฐธ๊ณ : JSON ํํ์ ๊ฐ์ฒด๊ฐ base64๋ก ์ธ์ฝ๋ฉ ๋๋ ๊ณผ์ ์์ ๊ณต๋ฐฑ/์ํฐ ๋ค์ ์ฌ๋ผ์ง
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์์ด์ ์ธ์ฝ๋ฉ ํ๊ฒ ๋จ
{"alg":"HS256","typ":"JWT"}
ํ์ด๋ก๋(payload) - ์ ๋ณด
{
"sub": "1234567890",
"name": "admin",
"iat": 1516239022
}
- sub ํ ํฐ์ ๋ชฉ
- name ์ฌ์ฉ์ ์ง์ ํด๋ ์
- iat ํ ํฐ ๋ฐ๊ธ์๊ฐ
- ํ์ด๋ก๋๋ ํ ํฐ์ ๋ด์ ์ ๋ณด๋ก์ ํด๋ ์(claim) ํ๋ช
(assert)์ ์ฒ๋ฆฌ ํ๋ JSON์ ๋ณด๊ดํ๊ณ ์์
- (ํ์ด๋ก๋. payload ๋ ์ ์ก๋๋ '์์ํ ๋ฐ์ดํฐ'๋ฅผ ์๋ฏธ)
- ํด๋ ์(claim) : ๋ด๋ ์ ๋ณด์ ํ '์กฐ๊ฐ'์ ์๋ฏธ
- name/value์ ํ ์์ผ๋ก ๊ตฌ์ฑ(key-value์ ํํ๋ก ์ ์ฅ)
- (ํ ํฐ์๋ ์ฌ๋ฌ๊ฐ์ ํด๋ ์์ ๋ฃ์ ์ ์์)
- ํด๋ ์์ ์ข
๋ฅ๋ ํฌ๊ฒ ์ธ ๋ถ๋ฅ๋ก ๋๋์ด์ง
- ๋ฑ๋ก๋(registered) ํด๋ ์
- ๊ณต๊ฐ(public) ํด๋ ์
- ๋น๊ณต๊ฐ(private) ํด๋ ์
๋ฑ๋ก๋(registered) ํด๋ ์
์๋น์ค์์ ํ์ํ ์ ๋ณด๋ค์ด ์๋, ํ ํฐ์ ๋ํ ์ ๋ณด๋ค์ ๋ด๊ธฐ ์ํ์ฌ ์ด๋ฆ์ด ์ด๋ฏธ ์ ํด์ง ํด๋ ์๋ค
ํ์ค ์คํ์ key์ ์ด๋ฆ์ 3๊ธ์๋ก ๋์ด ์์
(JWT์ ํต์ฌ ๋ชฉํ๋ ์ฌ์ฉ์์ ๋ํ, ํ ํฐ์ ๋ํ ํํ์ ์์ถํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ)
ํ ํฐ์ ์ผ๋ฐ์ ์ผ๋ก ํฌํจ๋๋ ํ์ค ํ๋์ธ 7๊ฐ์ ๋ฑ๋ก ํด๋ ์ ์ด๋ฆ(Registered Claim Names)์ ์ ์
- iss (Issuer) : ํ ํฐ ๋ฐ๊ธ์
- sub (Subject) : ํ ํฐ ์ ๋ชฉ - ํ ํฐ์์ ์ฌ์ฉ์์ ๋ํ ์๋ณ ๊ฐ
- aud (Audience) : ํ ํฐ ๋์์
- exp (Expiration Time) : ํ ํฐ ๋ง๋ฃ ์๊ฐ - ์๊ฐ์ NumericDate ํ์
- nbf (Not Before) : ํ ํฐ ํ์ฑ ๋ ์ง (์ด ๋ ์ง ์ด์ ์ ํ ํฐ์ ํ์ฑํ๋์ง ์์์ ๋ณด์ฅ)
- NumericDate ํ์
- ์ด ๋ ์ง๊ฐ ์ง๋๊ธฐ ์ ๊น์ง ํ ํฐ์ด ์ฒ๋ฆฌ๋์ง ์์
- iat (Issued At (Time)) : ํ ํฐ ๋ฐ๊ธ ์๊ฐ - ์ด ๊ฐ์ ์ฌ์ฉํ์ฌ ํ ํฐ์ 'age'๊ฐ ์ผ๋ง๋ ๋์๋์ง ํ๋จ ๊ฐ๋ฅ
- jti (JWT Id) : JWT ํ ํฐ ์๋ณ์ (issuer๊ฐ ์ฌ๋ฌ ๋ช
์ผ ๋ ์ด๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํ ๊ฐ)
- JWT์ ๊ณ ์ ์๋ณ์
- ์ฃผ๋ก ์ค๋ณต์ ์ธ ์ฒ๋ฆฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํ์ฌ ์ฌ์ฉ
- ์ผํ์ฉ ํ ํฐ์ ์ฌ์ฉํ๋ฉด ์ ์ฉํจ
์ด๋ฌํ ํ์ค ์คํ์ผ๋ก ์ ์๋์ด ์๋ค๋ ๊ฒ์ด์ง, ๊ผญ ์ด 7๊ฐ์ง๋ฅผ ๋ชจ๋ ํฌํจํด์ผ ํ๋ ๊ฒ๋ ์๋๊ณ (๋ชจ๋ ์ ํ์ (optional)), ํ์ค ์คํ ์ธ์๋ ํ์ํ๋ค ์ถ์ผ๋ฉด ์ถ๊ฐํด๋ ์ ํ ๋ฌธ์ ๊ฐ ์์ (๊ฐ๋ฐ์์ ์์ )
๊ณต๊ฐ(public) ํด๋ ์
๊ณต๊ฐ ํด๋ ์๋ค์ ์ถฉ๋์ด ๋ฐฉ์ง๋(collision-resistant)์ด๋ฆ์ ๊ฐ๊ณ ์์ด์ผ ํจ
์ถฉ๋์ ๋ฐฉ์งํ๊ธฐ ์ํด ํด๋ ์ ์ด๋ฆ์ URL ํ์์ผ๋ก ์ง์
{
url : (bool type)
}
์ฃผ์: base64 ๋ก ์ธ์ฝ๋ฉ์ ํ ๋, ๋ค์ = ๋ฌธ์๊ฐ ํ๋๊ฐ ๋ถ์ ๋๊ฐ ์์.
์ด ๋ฌธ์๋ base64 ์ธ์ฝ๋ฉ์ padding ๋ฌธ์๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ, URL ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋๋ ๊ฒฝ์ฐ๋ ์กด์ฌ
๋ฐ๋ผ์ = ๋ฌธ์๋, url-safe ํ์ง ์์ผ๋ฏ๋ก, ์ ๊ฑฐ๋์ด์ผ ํจ.
(ํจ๋ฉ์ด ํ๊ฐ ์๊ธธ ๋๋ ์๊ณ , ๋๊ฐ ์๊ธธ ๋๋ ์๋๋ฐ, ์ ๋ถ ์ง์๋ (์ ๊ฑฐํด์ค๋) ๋์ฝ๋ฉ ํ ๋ ์ ํ ๋ฌธ์ X)
๋น๊ณต๊ฐ(private) ํด๋ ์
๋ฑ๋ก๋ ํด๋ ์๋ ์๋๊ณ , ๊ณต๊ฐ๋ ํฌ๋ ์๋ค๋ ์๋ ๊ฒ
์ ์ธก๊ฐ์ (๋ณดํต ํด๋ผ์ด์ธํธ - ์๋ฒ) ํฉ์ ํ์ ์ฌ์ฉ๋๋ ํด๋ ์ ์ด๋ฆ
(๊ณต๊ฐ ํด๋ ์๊ณผ ๋ฌ๋ฆฌ ์ด๋ฆ์ด ์ค๋ณต๋์ด ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ ์ฌ์ฉํ ๋ ์ ์ํด์ผ ํจ)
๋ค๋ง ๊ฐ์ฅ ์ค์ํ ๊ฒ์ payload์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋ด์ง ์๋ ๊ฒ
header์ payload๋ json์ด ๋์ฝ๋ฉ๋์ด์์ ๋ฟ์ด์ง ํน๋ณํ ์ํธํ๊ฐ ๊ฑธ๋ ค์๋ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ ๋๊ตฌ๋ jwt๋ฅผ ๊ฐ์ง๊ณ ๋์ฝ๋ฉ์ ํ๋ค๋ฉด ๋ด๊ฒจ์๋ ๊ฐ์ ์ ์ ์๊ธฐ ๋๋ฌธ
๊ทธ๋ฌ๋ฏ๋ก JWT์๋ ๋จ์ํ "์๋ณ์ ํ๊ธฐ ์ํ" ์ ๋ณด๋ง์ ๋ด์๋์ด์ผ ํ๋ ๊ฒ
์๋ช (signature)
ํค๋์ ์ธ์ฝ๋ฉ ๊ฐ๊ณผ, ์ ๋ณด์ ์ธ์ฝ๋ฉ ๊ฐ์ ํฉ์น ํ ์ฃผ์ด์ง ๋น๋ฐํค๋ก ํด์๋ฅผ ํ์ฌ ์์ฑ
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
) //secret base64 encoded
- ์์ ๊ณผ์ ์ผ๋ก ๋ง๋ ํด์๋ฅผ, base64 ํํ๋ก ๋ํ๋ด๋ฉด ๋จ
- (๋ฌธ์์ด์ ์ธ์ฝ๋ฉ ํ๋๊ฒ ์๋ hex → base64 ์ธ์ฝ๋ฉ์ ํด์ผ ํจ)
- ์์์ header ์ payload๋ฅผ ๋ณด์ฌ์ค ๋๋ ์ธ์ฝ๋ฉ ๋์ด ์๋ ๊ฐ๋ค์ JWT์ ๋ด๊ฒจ์๋ ๊ฒ์ฒ๋ผ ๋์ฝ๋ฉ๋ ์ํ๋ฅผ ์ฌ์ฉ
- heder๋ฅผ ๋์ฝ๋ฉํ ๊ฐ, payload๋ฅผ ๋์ฝ๋ฉํ ๊ฐ์ ์์ฒ๋ผ ํฉ์น๊ณ
- ์ด๋ฅผ your-256-bit-secret ์ฆ, ์๋ฒ๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ธํค๋ฅผ ๊ฐ์ง๊ณ ์ํธํ๋์ด์๋ ์ํ
- ๋ฐ๋ผ์ signature๋ ์๋ฒ์ ์๋ ๊ฐ์ธํค๋ก๋ง ์ํธํ๋ฅผ ํ ์ ์์ผ๋ฏ๋ก ๋ค๋ฅธ ํด๋ผ์ด์ธํธ๋ ์์๋ก ๋ณตํธํ ๋ถ๊ฐ๋ฅ
๋ณตํธํ ์ธ์ฆ ์ ์ฐจ
1. JWT ํ ํฐ์ ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ๋ก ์์ฒญ๊ณผ ๋์์ ์ ๋ฌ
2. ์๋ฒ๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ธํค๋ฅผ ๊ฐ์ง๊ณ signature๋ฅผ ๋ณตํธํ
3. base64UrlEncode(header)๊ฐ JWT์ header ๊ฐ๊ณผ ์ผ์นํ๋์ง ํ์ธ
4. base64UrlEncode(payload)์ ์ผ์นํ๋์ง ํ์ธ
5. ์ผ์นํ๋ค๋ฉด ์ธ์ฆ์ ํ์ฉ
๋ง์ฝ ํด๋ผ์ด์ธํธ๊ฐ payload์ ๋ด๊ธด ์๋ณ์๊ฐ ๋ณ์กฐ๋ JWT๋ก ์์ฒญํ๋ค๋ฉด, ์๋ฒ๊ฐ ์ ์ด์ ๋ฐ๊ธํ๋ signature ์์ payload์ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ธ์ฆ์ด ๋ถ๊ฐ๋ฅ
JWT์ ์ฅ์
- ์ง๊ธ๊น์ง ์ฟ ํค์ ์ธ์ ์ ๋์ด์ค๋ฉด์ ๊ฒช์๋ ๋ชจ๋ ๋จ์ ์ ํด๊ฒฐํ๋ ๊ฒ์ด JWT (๊ฐ๊ฐ์ ๋จ์ ์ ๋ค์ง์ผ๋ฉด ์ฅ์ )
- ์ด๋ฏธ ํ ํฐ ์์ฒด๊ฐ ์ธ์ฆ๋ ์ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์ธ์ ์ ์ฅ์์ ๊ฐ์ ๋ณ๋์ ์ธ์ฆ ์ ์ฅ์๊ฐ 'ํ์์ '์ผ๋ก ํ์ํ์ง ์์
- ์ธ์ ๊ณผ๋ ๋ค๋ฅด๊ฒ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์๋ฒ๊ฐ ์ ์ฅํด ๋์ง ์์๋ ๋จ
- signature๋ฅผ ๊ณตํตํค / ๊ฐ์ธํค ์ํธํ๋ฅผ ํตํด ๋ง์๋์๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ์ ๋ํ ๋ณด์์ฑ์ด ๋์
- ๋ค๋ฅธ ์๋น์ค์ ์ด์ฉ ๊ฐ๋ฅํ ๊ณตํต์ ์ธ ์คํ์ผ๋ก์จ ์ฌ์ฉ ๊ฐ๋ฅ
์ฆ, stateful ํด์ผ ํ๋ ์ธ์ ์ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด ๋ง๋ค์ด์ง JWT๋ ๋ณ๋์ ์ธ์ ์ ์ฅ์๋ฅผ ๊ฐ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ stateless(๋ฌด์ํ์ฑ์ ์ถ๊ตฌ)ํ์ฌ ํ์ฅ์ฑ์ด ๋ฐ์ด๋๊ณ , signature๋ฅผ ํตํ ๋ณด์์ฑ๊น์ง ๊ฐ์ถค
JWT์ ์ทจ์ฝ์ฑ
JWT์ ์ทจ์ฝ์ฑ
JSON ์น ํ ํฐ์ ์ธ์ ์ํ๋ฅผ ํฌํจํ ์ ์์
๊ทธ๋ฌ๋ ํ๋ก์ ํธ ์๊ฑด์ด JWT ๊ธฐ๊ฐ ๋ง๋ฃ ์ด์ ์ ์ธ์ ๋ฌดํจํ๋ฅผ ํ์ฉํ๋ ๊ฒฝ์ฐ
-> ์๋น์ค๋ ๋ ์ด์ ํ ํฐ๋ง์ผ๋ก ํ ํฐ ํ๋ช (token assertion)์ ์ ๋ขฐํ ์ ์๊ฒ ๋จ
-> ํ ํฐ์ ์ ์ฅ๋ ์ธ์ ์ด ํ์ง๋์ง ์์์ ํ์ธํ๊ธฐ ์ํด ํ ํฐ ํ๋ช ์ ๋ฐ์ดํฐ ์คํ ์ด์ ๋ํด ๊ฒ์ฌ๋์ด์ผ ํจ
-> ์ด๋ ๊ฒ ํ๋ฉด ํ ํฐ์ด ๋ ์ด์ ๋ฌด์ํ๊ฐ ์๋๊ฒ ๋จ์ผ๋ก์จ JWT์ ์ฃผ๋ ์ด์ ์ด ์ฝํ๋๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณ์
- ์ ์ ํ ์ค๊ณํ ๊ฒฝ์ฐ ๊ฐ๋ฐ์๋ ์ผ๋ถ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด๋ฉด ์๊ณ ๋ฆฌ์ฆ ์ทจ์ฝ์ฑ์ ํด๊ฒฐ ๊ฐ๋ฅ
- JWT ํค๋๋ง์ผ๋ก ์ ํจ์ฑ์ ํ์ธํ์ง ์์ ๊ฒ
- ์๊ณ ๋ฆฌ์ฆ์ ์ธ์งํ ๊ฒ
- ์ ์ ํ ํค ํฌ๊ธฐ๋ฅผ ์ฌ์ฉํ ๊ฒ
์งง์ JWT ์ ํจ์๊ฐ์ ๋ณด์ํ๋ ๋ฐฉ๋ฒ
JWT๊ฐ ๋ง๋ฃ๋๊ธฐ ์ง์ ์ ์ ํจ์๊ฐ์ ๋ณด๊ณ ์ฌ๋ฐ๊ธ ๋ฐฉ์์ ์ด๋ค์์ผ๋ก ํ๋๋?
- Sliding Session
- ํน์ ํ ์๋น์ค๋ฅผ ๊ณ์ ์ฌ์ฉํ๊ณ ์๋ ํน์ ์ ์ ์ ๋ํ์ฌ ๋ง๋ฃ์๊ฐ์ ์ฐ์ฅ์์ผ์ฃผ๋ ๋ฐฉ๋ฒ
- ex) ์ด๋ค ๊ธ์ ์ง์์ ์ผ๋ก ์ฐ๊ณ ์๋ ์ ์ ๊ฐ ์งง์ ๋ง๋ฃ์๊ฐ ๋๋ฌธ์ ๊ธ์ ์ฐ๋ค๊ฐ ์ธ์ฆ ์ทจ์๋ก ์ธํด ์ฐ๋ ๊ธ์ด ๋ ์๊ฐ๋ค๋ฉด?
- Sliding Session์ ์ฌ์ฉํ๋ฉด, ์ฌ์ฉ์๊ฐ ํน์ action์ ์ทจํ์ ๋, ์๋กญ๊ฒ ๋ง๋ฃ์๊ฐ์ด ๋์ด๋ JWT๋ฅผ ๋ค์ ์ ๊ณตํจ์ผ๋ก์จ ๋ง๋ฃ์๊ฐ์ ์ฐ์ฅํ์ฌ ๋ณด์ํ๋ ๋ฐฉ๋ฒ
- ๋ค๋ง, ์ ์์ด ๋จ๋ฐ์ฑ์ผ๋ก ๋ฐ์ํ๋ค๋ฉด Sliding Session์ผ๋ก ์ฐ์ฅ์์ผ์ค ์ ์๋ ์ํฉ์ด ์๊น
- ๋๋ฌด ๊ธด JWT(Acess Token)์ ๋ฐ๊ธ์์ผ์ค ์ํฉ์ด๋ผ๋ฉด, Sliding Session์ ์ํด ๋ฌดํ์ ์ฌ์ฉ ๊ฐ๋ฅํด์ง๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์
- Refresh Token
- ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
- JWT๋ฅผ ์ฒ์ ๋ฐ๊ธํ ๋ Acess Token๊ณผ ํจ๊ป Refresh Token์ด๋ผ๋ ํ ํฐ์ ๋ฐ๊ธํ์ฌ ์งง์ ๋ง๋ฃ์๊ฐ์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ
- ์งง์ ์๊ฐ์ด ์๋ ๋น๊ต์ ๊ธด ์๊ฐ์ ๋ง๋ฃ์๊ฐ(7์ผ, 30์ผ etc.)์ ๊ฐ์ง Refresh Token์ ๋ง ๊ทธ๋๋ก Acess Token์ Refresh ํด์ฃผ๋ ๊ฒ์ ๋ณด์ฅํ๋ ํ ํฐ
- 7์ผ, 30์ผ, 60์ผ, 90์ผ, ๋ง๋ฃ์์(No Expiration), ์ฌ์ฉ์ ์ค์ (Custom)
- ๋ง์ฝ ํด๋ผ์ด์ธํธ๊ฐ Acess Token์ด ๋ง๋ฃ๋จ์ ์ธ์งํ๊ฑฐ๋, ์๋ฒ๋ก๋ถํฐ ๋ง๋ฃ๋จ์ ํ์ธ ๋ฐ๋๋ค๋ฉด Refresh Token์ผ๋ก ์๋ฒ์๊ฒ ์๋ก์ด Acess Token์ ๋ฐ๊ธํ๋๋ก ์์ฒญํ๋ ๋ฐฉ์
Refresh ๋์ ๊ณผ์
1. ํด๋ผ์ด์ธํธ๊ฐ ID, PW๋ก ์๋ฒ์๊ฒ ์ธ์ฆ์ ์์ฒญ
2. ์๋ฒ๋ ์ด๋ฅผ ํ์ธํ์ฌ Access Token๊ณผ Refresh Token์ ๋ฐ๊ธ
3. ํด๋ผ์ด์ธํธ๋ ์ด๋ฅผ ๋ฐ์ Refresh Token์ ๋ณธ์ธ์ด ์ ์ ์ฅํ๊ณ , Access Token์ ๊ฐ์ง๊ณ ์๋ฒ์ ์์ ๋กญ๊ฒ ์์ฒญ
4. ์์ฒญ ๋์ค Access Token์ด ๋ง๋ฃ๋์ด ๋ ์ด์ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ๋ค๋ ์ค๋ฅ๋ฅผ ์๋ฒ๋ก ๋ถํฐ ์ ๋ฌ ๋ฐ์
5. ํด๋ผ์ด์ธํธ๋ ๋ณธ์ธ์ด ์ฌ์ฉํ๋ Access Token์ด ๋ง๋ฃ๋์์์ ์ธ์ง
6. ๋ณธ์ธ์ด ๊ฐ์ง๊ณ ์๋ Refresh Token์ ์๋ฒ๋ก ์ ๋ฌํ์ฌ ์๋ก์ด Access Token ๋ฐ๊ธ์ ์์ฒญ
7. ์๋ฒ๋ Refresh Token์ ๋ฐ์ ์๋ฒ์ Refresh Token Storage์ ํด๋น ํ ํฐ์ด ์๋์ง ํ์ธ
8. ํด๋น ํ ํฐ์ด ํ์ธ๋๋ฉด Access Token์ ์์ฑํ์ฌ ์ ๋ฌ
9. (2)๋ก ๋์๊ฐ์ ๊ณ์ํด์ ๋์ผํ ์์ ์งํ
- Refresh Token Storage ๋ ์๋ฒ์์ Refresh Token์ ์ ์ฅํ๋ ์ ์ฅ์
- ์ด๋ป๊ฒ ๋ณด๋ฉด ์ธ์ ์ ์ฅ์์ ๊ฐ์ ์ญํ ์ ์ํ
- ๋ง๋ฃ๋ Access Token์ด ๋ ์ด์ ์ธ์ฆ์ ์ญํ ์ ์ํํ์ง ๋ชปํ๋ฏ๋ก, Refresh Token์ ์๋ฒ๋ก ์ ๋ฌํ๊ณ , ์ด Refresh Token์ด ์๋ฒ์ Token ์ ์ฅ์์ ์๋์ง ํ์ธ ํ Access Token์ ๋ฐ๊ธํ๋ ํํ
- ์ฌ์ค์ ์ธ์
๊ณผ ๋ณ๋ฐ ์ฐจ์ด ์์ด ์ ์ฅ์(Storage)์ I/O ์์
์ด ๋ฐ์ํ๋ ๊ผด
- Access Token์ด ์ง์๋๋ ์งง์ ์๊ฐ๋์ ์ด์ธ์ ๊ฐฑ์ ์ ๋ง๋ค
- ๊ฒฐ๊ตญ ์ธ์
๊ณผ ๋๊ฐ์ ๋จ์ ํ๋๊ฐ ์๊ธฐ๊ฒ๋๋ ์
- ๋ฌผ๋ก ์ธ์ ์ ๊ฒฝ์ฐ ์ธ์ฆ์ ์์ฒญํ ๋๋ง๋ค I/O
- ํ์ง๋ง Refresh Token์ ๊ฒฝ์ฐ, Access Token์ด ๋ง๋ฃ๋์์ ๋๋ง
- ์ฃผ๊ธฐ๊ฐ ๋ค๋ฅด๊ธดํ์ง๋ง I/O๊ฐ ๋ฐ์ํ๋ค๋ ์ฌ์ค๋ง ๊ฐ์
- ๋ค๋ง ์ธ์ ์ฒ๋ผ ํ ํฐ ์์ฒด๊ฐ ํ์ทจ๋์๋ค๊ณ ํ๋จ๋๋ฉด, Refresh Token Storage๋ฅผ ์ด๊ธฐํํจ์ผ๋ก์จ ํ์ทจ๋ ํ ํฐ์ด ๋์ด์ Refresh ๋์ง ๋ชปํ๋๋ก ๋ง๋ ๊ฒ์ด ๊ฐ๋ฅ
JWT๋ฅผ ํ์ฉํ ๋ก๊ทธ์ธ ์ ์ง
๋ชจ์ ํดํน ์คํฐ๋ - 3์ฃผ์ฐจ ๊ณผ์ (3-2) JWT ๊ตฌํ(๋ก๊ทธ์ธ ์ ์ง)
Reference
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
์ง๋ฌธ ํ์, ์์ ๋ฐ ๋ณด์์ ๋ํ ์ง์ ํ์