JWT & AccessToken / RefreshToken โ
๐ JWT ํ ์ค ์ ๋ฆฌ
JWT๋ ์ฌ์ฉ์๊ฐ ๋๊ตฌ์ธ์ง(sub), ์ด๋ค ๊ถํ(role)์ ๊ฐ์ก๋์ง ๋ด๊ณ ,
์๋ช
(signature)์ผ๋ก ์์กฐ ์ฌ๋ถ๋ฅผ ๊ฒ์ฆํ ์ ์๋ Stateless ์ธ์ฆ ํ ํฐ์ด๋ค.
๐งฉ Reference
JWT(Json Web Token)= ์ธ์ฆ/์ธ๊ฐ ์ ๋ณด๋ฅผ ๋ด์ ์๋ช ๊ฐ๋ฅํ ํ ํฐ- JWT ๊ตฌ์กฐ:
Header.Payload.Signature(base64url ์ธ์ฝ๋ฉ) - AccessToken = ์งง๊ฒ ์ ์ง๋๋ ์ธ์ฆ ํ ํฐ (Authorization ํค๋๋ก ์ ์ก)
- RefreshToken = ์๋ก์ด AccessToken ๋ฐ๊ธ์ฉ ์ฅ๊ธฐ ํ ํฐ (httpOnly ์ฟ ํค๋ก ์ ์ก)
- ์๋ฒ๋ ํ ํฐ์ ์๋ช
๊ณผ ๋ง๋ฃ ์๊ฐ, ๋ฐ๊ธ์ ๋ฑ์ ๊ฒ์ฆํด์
๋ณ๋์ ์ธ์ ์ ์ฅ์ ์์ด๋ ์ฌ์ฉ์ ์ ์์ ํ์ธํ ์ ์์ โ Stateless ์ธ์ฆ
๐งฉ Point
AccessToken์ ์งง๊ฒ ๋ง๋ฃ๋์ด์ผ ํ์ทจ ํผํด๊ฐ ์ต์ํ๋๋ค.- RefreshToken์ js ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ
httpOnly + Secure ์ฟ ํค๋ก ๋ณดํธํด์ผ ํ๋ค. - 401 Unauthorized๋ ํ์ฌ ์ธ์ฆ ์ ๋ณด(AccessToken ๋ฑ)์ ๋ฌธ์ ๊ฐ ์๋ค๋ ์ ํธ๋ค.
๋ง์ ์๋น์ค์์ AccessToken ๋ง๋ฃ ์ํฉ์ 401๋ก ๋ด๋ ค์ฃผ๊ณ ,
์ด๋ RefreshToken์ผ๋ก ์ฌ๋ฐ๊ธ์ ์๋ํ๋๋ก ์ค๊ณํ๋ค. - ์๋ ๋ก๊ทธ์ธ์
RefreshToken์ด ์ฟ ํค๋ก ์๋ ์ ์ก๋๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ ๊ตฌ์กฐ์ด๋ค. - JWT๋ payload๊ฐ ํด์๋ก ๋คํธ์ํฌ ๋น์ฉ ์ฆ๊ฐ โ ํ์ํ ์ต์ ์ ๋ณด๋ง ๋ฃ์ด์ผ ํ๋ค.
- HTTPS ์์ผ๋ฉด Authorization ํค๋์ JWT๋ ์ฟ ํค์ ๋ด๊ธด RefreshToken์ด ๊ทธ๋๋ก ๋ ธ์ถ๋ ์ ์์ผ๋ฏ๋ก ํ์๋ค.
JWT๋ฅผ ์ดํดํ๊ธฐ ์ ์ ์ค์ํ ์ฌ์ค โ
JWT๋ ๋
๋ฆฝ์ ์ผ๋ก ๋์ํ๋ ๊ธฐ์ ์ด ์๋๋ผ,HTTP + HTTPS + Cookie + Authorization Header ์์์ ๋์๊ฐ๋ ์ธ์ฆ ํ๋กํ ์ฝ์ด๋ค.
์ฆ ์ธ์ฆ์ ๊ตฌํํ ๋,
- ํ ํฐ โ HTTP Authorization ํค๋๋ก ๋ณด๋ด๊ณ
- RefreshToken โ httpOnly ์ฟ ํค๋ก ์๋ ์ ์ก๋๊ณ
- ํ ํฐ ๋ง๋ฃ โ HTTP 401 ์๋ต์ผ๋ก ๊ฐ์ง๋๊ณ
- ์๋ ์ฌ๋ฐ๊ธ โ Axios interceptor๋ก ๊ตฌํ๋๋ ๊ฒ
โ ์ด ๋ชจ๋ ๊ณผ์ ์ด HTTP ๊ท์ฝ ์์์ ์ด๋ฃจ์ด์ง๋ค.
(๊ทธ๋์ HTTP/HTTPS, ์ฟ ํค ๋์์ ๋จผ์ ์ดํดํ๋ฉด JWT๋ฅผ ํจ์ฌ ์ฝ๊ฒ ์ดํดํ ์ ์๋ค.)
๐งฉ Axios๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
๋ณธ๋ฌธ์์ ์ค๋ช
ํ๋ ํ๋ฆ์ Axios ๊ธฐ์ค์ด์ง๋ง, JWT ์ธ์ฆ ์์ฒด๋ Axios ์์กด์ ์ธ ๊ธฐ์ ์ด ์๋๋ผ HTTP ๊ท์ฝ ์์์ ๋์ํ๋ ์ธ์ฆ ๋ฐฉ์์ด๋ค. ํ์ฌ ์งํ ์ค์ธ ํ๋ก์ ํธ๊ฐ Axios๋ฅผ ์ฌ์ฉํ๊ณ ์์ด ์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์๋ค!
- AccessToken โ Authorization ํค๋๋ก ๋ณด๋ด๊ณ
- RefreshToken โ httpOnly ์ฟ ํค๋ก ์๋ ์ ์ก๋๊ณ
- AccessToken ๋ง๋ฃ โ ์๋ฒ๊ฐ 401์ ๋ด๋ ค์ฃผ๊ณ
- RefreshToken ์ฌ๋ฐ๊ธ โ fetch๋ก๋ ๊ฐ๋ฅ
๋ฐ๋ผ์ JWT ์ธ์ฆ์ Axios ๊ธฐ๋ฅ์ด ์๋๋ผ HTTP ๊ท์ฝ ์์์ ๋์ํ๋ ์ธ์ฆ ๋ฐฉ์์ด๋ค. Axios๋ฅผ ์ฐ์ง ์๋๋ค๋ฉด, interceptor ๋ถ๋ถ๋ง ์ง์ ํจ์๋ก ๊ฐ์ธ์ ๊ตฌํํ๋ฉด ๋์ผํ๊ฒ ๋์ํ๋ค!
JWT๋? โ
JWT(Json Web Token)๋ ์ธ์ฆ์ ์ํด ์ฌ์ฉ๋๋ ์๋ช
๋ ํ ํฐ ํฌ๋งท์ด๋ค.
ํ ํฐ ๋ด๋ถ์ ์ ์ ID, ๊ถํ, ๋ง๋ฃ ์๊ฐ ๋ฑ ์ค์ํ ์ ๋ณด๊ฐ ํฌํจ๋๋ฉฐ, ํ ํฐ์ด ๋ณ์กฐ๋์ง ์์๋์ง๋ง ์๋ฒ๊ฐ ๊ฒ์ฆํ๋ฉด ์์ฒญ์ ์ ๋ขฐํ ์ ์๋ค.
JWT ๊ตฌ์กฐ๋ header.payload.signature ํํ์ ์ธ ๋ถ๋ถ์ผ๋ก ๋๋์ด์ง๋ค:
Header.Payload.Signature| ๋ถ๋ถ | ์ค๋ช |
|---|---|
Header | ํ ํฐ ํ์, ์๋ช ์๊ณ ๋ฆฌ์ฆ ์ ๋ณด |
Payload | ์ค์ ๋ฐ์ดํฐ sub: subject (์ฌ์ฉ์ ๊ณ ์ ID) role: ๊ถํ ์ ๋ณด iat: ๋ฐ๊ธ ์๊ฐ (Issued At) exp: ๋ง๋ฃ ์๊ฐ (Expiration) |
Signature | ๋น๋ฐํค๋ก ์๋ช ๋ ๊ฐ โ ์์กฐ ๋ฐฉ์ง |
์๋ฒ๋ Signature๋ฅผ ๊ฒ์ฆํด ์ด ํ ํฐ์ด ์ฐ๋ฆฌ ์๋ฒ์์ ๋ฐ๊ธ๋ ํ ํฐ์ธ์ง?, Payload๊ฐ ์ ํจํ์ง?๋ฅผ ํ๋จํ ์ ์๋ค. ๊ทธ๋์ ์ธ์
์ ์ฅ์ ์์ด๋ ์ธ์ฆ์ด ๊ฐ๋ฅํ๋ค. (stateless)
์ JWT๋ Stateless์ธ๊ฐ?
์ธ์ ์ธ์ฆ๊ณผ ๋ค๋ฅด๊ฒ JWT ์ธ์ฆ์์๋:
- ์๋ฒ๊ฐ ์ฌ์ฉ์ ์ํ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ์ง ์์
- DB์ ์ธ์ ๋ ์ฝ๋๋ ์์
- ์ค์ง ํ ํฐ์ ์๋ช (signature)๋ง ๊ฒ์ฆํ๋ฉด ์ฌ์ฉ์๋ฅผ ์๋ณํ ์ ์์
์ฆ, ์๋ฒ๋ โ์ ์ ์ ๋ณด๋ฅผ ๋ค๊ณ ์์ง ์์๋โ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋ค. โ ํ์ฅ์ฑ์ ํนํ ์ ๋ฆฌํ๋ค.
AccessToken & RefreshToken โ
JWT ์ธ์ฆ์์๋ ๋ณดํต ๋ ์ข ๋ฅ์ ํ ํฐ์ด ํจ๊ป ์ฌ์ฉ๋๋ค.
JWT๋ ์ ํจ๊ธฐ๊ฐ์ด ์๋ ํ ํฐ์ด๊ธฐ ๋๋ฌธ์ ๋ค์ ๋ฌธ์ ๊ฐ ์๊ธด๋ค:
- AccessToken์ ๊ธธ๊ฒ ํ๋ฉด โ ํ์ทจ ์ํ ์ฆ๊ฐ
- AccessToken์ ์งง๊ฒ ํ๋ฉด โ ์ฌ์ฉ์๊ฐ ์์ฃผ ๋ก๊ทธ์์๋จ
๊ทธ๋์ ๋์จ ๊ตฌ์กฐ๊ฐ AccessToken (์งง๊ฒ) + RefreshToken (๊ธธ๊ฒ)์ด๋ค.
๋ ๊ฐ๊ฐ ํฉ์ณ์ ธ์ ๋ณด์ + ์ ์ ๊ฒฝํ ๋ ๋ค ์ก๋ ๊ตฌ์กฐ๊ฐ ๋๋ค.
| ์ข ๋ฅ | ์ ์ฅ ์์น | ๋ง๋ฃ | ์ญํ |
|---|---|---|---|
| AccessToken | ๋ฉ๋ชจ๋ฆฌ/Zustand/localStorage | 15๋ถ~1์๊ฐ | ์์ฒญ ์ธ์ฆ |
| RefreshToken | httpOnly ์ฟ ํค(๋ธ๋ผ์ฐ์ ์๋ ๊ด๋ฆฌ) | 2์ฃผ~1๋ฌ | AccessToken ์ฌ๋ฐ๊ธ |
AccessToken (AT) โ
์ญํ โ
- ์ฌ์ฉ์๊ฐ ๋๊ตฌ์ธ์ง ์ธ์ฆํ๋ ์ ๋ณด
- ์์ฒญ์ ๋ณด๋ผ ๋ Authorization ํค๋์ ๋ด์ ์ ๋ฌ
ํน์ง โ
- ๋ง๋ฃ ์๊ฐ์ด ๋งค์ฐ ์งง๋ค (5๋ถ ~ 30๋ถ)
- ํ์ทจ๋๋ฉด ๊ณง ๋ง๋ฃ๋๋ฏ๋ก ํผํด๊ฐ ์ ํ์
- ํ๋ก ํธ์์๋ ๋ณด์์ ๋ฉ๋ชจ๋ฆฌ(Zustand ๋ฑ)์ ๋๋ ๊ฒ์ ์ฐ์ ์ผ๋ก ํ๊ณ ,
ํ์์ ๋ฐ๋ผ LocalStorage์ ์ ์ฅํ๋ ๋ฐฉ์๋ ์ฌ์ฉ๋๋ค. (XSS ์ทจ์ฝ์ฑ ๊ณ ๋ ค ํ์)
์์ฒญ ์์ โ
Authorization: Bearer <access_token>RefreshToken (RT) โ
์ญํ โ
- AccessToken์ด ๋ง๋ฃ๋์์ ๋ ์ ํ ํฐ์ ๋ฐ๊ธ๋ฐ๊ธฐ ์ํ ์ฅ๊ธฐ ํ ํฐ
ํน์ง โ
- ์๋ช ์ด ๊น (7์ผ ~)
- ํ์ทจ๋๋ฉด ๊ณ์ ์ด ์ํ๋ฐ์ โ ๊ฐ์ฅ ๋ฏผ๊ฐํ ํ ํฐ
- JS ์ ๊ทผ์ด ๋ถ๊ฐํ httpOnly + Secure ์ฟ ํค๋ก ์ ์ฅ
- ๋ธ๋ผ์ฐ์ ๊ฐ ์๋์ผ๋ก ์ ์ก
์๋ฒ๊ฐ RefreshToken์ ์ฟ ํค๋ก ์ฃผ๋ ์์ โ
Set-Cookie: refresh_token=abc123; HttpOnly; Secure; SameSite=Strict; Path=/authํ๋ก ํธ์์๋ RT๋ฅผ ์ฝ์ ์ ์๋ค โ
console.log(document.cookie); // refresh_token ๋ณด์ด์ง ์์โ ์ด ํน์ฑ์ด XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ํ ํฐ์ ๋ณดํธํ๋ค.
RefreshToken์ด ์ฟ ํค์ฌ์ผ ํ๋ ์ด์ โ
RefreshToken์ ํด๋ผ์ด์ธํธ์ ์ ์(Identity)์ ์ฆ๋ช ํ๋ ๋ฐ์ดํฐ์ด๊ธฐ ๋๋ฌธ์ ํ๋ก ํธ๊ฐ ์ง์ ์ ์ฅํ๊ฑฐ๋ ๊ด๋ฆฌํ๋ฉด ์ ๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ httpOnly ์ฟ ํค์ฌ์ผ ํ๋ค.
1. RefreshToken์ ์๋ฒ๊ฐ ์ ์์ ํ๋จํ๋ ์ธ์ฆ ์ฑ๋์ด์ด์ผ ํ๋ค. โ
- ์๋ฒ๊ฐ RT๋ฅผ ํตํด โ์ด ์ฌ๋ฐ๊ธ ์์ฒญ์ด ์ง์ง ์ฐ๋ฆฌ ์ฌ์ฉ์๊ฐ ๋ณด๋ธ ์์ฒญ์ธ์งโ ํ๋จํ๋ค.
์ฟ ํค๋ ์๋ฒ๊ฐ Set-Cookie๋ก ๋ด๋ ค์ฃผ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ์ ์ฅ + ์๋ ์ ์กํด์ฃผ๋ฏ๋ก ํ๋ก ํธ ์ฝ๋ ๊ฐ์ ์์ด ์์ ์ ์ธ ์ธ์ฆ ์ฑ๋์ ์ ์งํ ์ ์๋ค.
2. RefreshToken์ JS์์ ์ฝํ๋ฉด ์ ๋๋ค. โ
RT๋ฅผ localStorage ๊ฐ์ ๊ณณ์ ์ ์ฅํ๋ฉด ์ ์ฑ ์คํฌ๋ฆฝํธ๊ฐ ์ฝ์ ๋๋ ์๊ฐ ๋ฐ๋ก ํธ๋ฆฐ๋ค. httpOnly ์ฟ ํค๋ JS๋ก ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ RefreshToken์ ๋ณดํธํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ด๋ค.
3. RT๋ ์ฌ๋ฐ๊ธ ์ฉ๋๋ผ ๋ ธ์ถ๋๋ฉด ์ธ์ ์ด ์๊ตฌ ํ์ทจ๋๋ค. โ
- AccessToken์ ์งง์์ ํผํด๊ฐ ์ ํ์ ์ด๋ค.
- RefreshToken์ ๊ธธ์ด์ ํธ๋ฆฌ๋ฉด ์น๋ช ์ ์ด๋ฏ๋ก ๋ฌด์กฐ๊ฑด ๋ณดํธํด์ผ ํ๋ค.
๊ทธ๋์ RT๋ ์ค๋ฌด์์ ๋ณดํตhttpOnly + Secure + SameSite=strict(or lax) ์กฐํฉ์ ์ฟ ํค๋ก ์ ์ฅํ๋ค.
SameSite ์ค์ ์ CSRF ๊ณต๊ฒฉ์ ์ผ๋ง๋ ํ์ฉ/์ฐจ๋จํ ์ง ์ ์ฑ
์ ๋ฐ๋ผ ์กฐ์ ํ๋ค.
JWT์ ์ฅ์ ๊ณผ ๋จ์ โ
์ฅ์ โ
- ํ์ฅ์ฑ ๋ฐ์ด๋จ (์๋ฒ๊ฐ ์ํ๋ฅผ ๋ค๊ณ ์์ง ์์๋ ๋จ)
- ์๋ฒ๊ฐ ์ฌ๋ฌ ๋์ฌ๋ ๋ฌธ์ ์์ (Load Balancing ์๋ฒฝ)
- bearer token ํ์ค ๋ฐฉ์
- ๋ก๊ทธ์ธ ์ํ ์ ์ง๊ฐ ๊ฐ๋จ
๋จ์ โ
- ํ ํฐ ํฌ๊ธฐ๊ฐ ํผ โ Network ๋น์ฉ ์ฆ๊ฐ
- ํ ํฐ ํ์ทจ๋๋ฉด ๋ง๋ฃ๋๊ธฐ ์ ๊น์ง ๋ฌด์กฐ๊ฑด ์ ํจ
- ํ ํฐ ๊ฐ์ ๋ฌดํจํ(revoke)๊ฐ ์ด๋ ค์ โ ๋ธ๋๋ฆฌ์คํธ DB ํ์
- ์ฟ ํค 4KB ์ ํ์ผ๋ก payload๋ฅผ ๋ง์ด ๋ฃ์ ์ ์์
์ ๋ฆฌ โ
๐ก
- JWT ์ธ์ฆ์ HTTP/HTTPS + Authorization ํค๋ + Cookie ์์์ ๋์ํ๋ค.
- AccessToken์ ์์ฒญ ์ธ์ฆ์ฉ์ด๋ฉฐ, ๋ณด์์ ์ํด ์งง๊ฒ ์ ์งํด์ผ ํ๋ค.
- RefreshToken์ ์ฌ๋ฐ๊ธ์ฉ์ด๋ฉฐ, httpOnly ์ฟ ํค๋ก ๋ฐ๋์ ๋ณดํธํด์ผ ํ๋ค.
- AccessToken์ด ๋ง๋ฃ๋๋ฉด ์๋ฒ๋ 401 Unauthorized๋ฅผ ๋ด๋ ค ์ ํธ๋ฅผ ๋ณด๋ธ๋ค.
- ์ด ์ ํธ๋ฅผ ๋ฐ์ RefreshToken์ผ๋ก ์ฌ๋ฐ๊ธ โ ์์ฒญ ์ฌ์๋ ํ๋ฆ์ด ์์๋๋ค.
- Axios๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, interceptor๊ฐ ์ด ์ฌ๋ฐ๊ธ ๊ณผ์ ์ ์๋ํํ๋ ๋๊ตฌ๊ฐ ๋๋ค.
- ํต์ฌ์ Axios๊ฐ ์๋๋ผ โHTTP ์๋ต(401) โ ํ ํฐ ์ฌ๋ฐ๊ธ โ ์์ฒญ ์ฌ์๋โ๋ผ๋ ํ๋ฆ ์์ฒด!