๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Web

[Web] JWT

JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ์€ ์ฟ ํ‚ค/์„ธ์…˜ ๋ฐฉ์‹๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ JWT ํ† ํฐ(Access Token)์„ HTTP ํ—ค๋”์— ์‹ค์–ด ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•œ๋‹ค.

 

๐Ÿ“˜ ๊ตฌ์กฐ

JWT๋Š” Header, Payload, Sigmature ์„ธ๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„๋œ๋‹ค.

 

Header

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: ์ •๋ณด๋ฅผ ์•”ํ˜ธํ™”ํ•  ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • typ: ํ† ํฐ์˜ ํƒ€์ž…

 

Payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
  • Payload๋Š” ํ† ํฐ์— ๋‹ด์„ ์ •๋ณด๋ฅผ ์ง€๋‹˜
  • ์ฃผ๋กœ ํด๋ผ์ด์–ธํŠธ์˜ ๊ณ ์œ  ID ๊ฐ’ ๋ฐ ์œ ํšจ ๊ธฐ๊ฐ„ ๋“ฑ์ด ํฌํ•จ
  • key-value ํ˜•์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ํ•œ ์Œ์˜ ์ •๋ณด๋ฅผ ํด๋ ˆ์ž„(Claim)์ด๋ผ๊ณ  ํ•œ๋‹ค
  • ํด๋ ˆ์ž„์„ ๊ณต๊ฐœ(public) ํ˜น์€ ๋น„๊ณต๊ฐœ(private) ํ•  ๊ฒƒ์ธ์ง€ ๋“ฑ๋ก(registered)ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค

 

Signature

HMACSHA256(
  base64UrlEncode(header) + "." +base64UrlEncode(payload),
	256-bit-secret
)
  • Signature๋Š” ์ธ์ฝ”๋”ฉ๋œ Header์™€ Payload๋ฅผ ๋”ํ•œ ๋’ค ๋น„๋ฐ€ํ‚ค๋กœ ํ•ด์‹ฑํ•˜์—ฌ ์ƒ์„ฑ
  • Header์™€ Payload๋Š” ๋‹จ์ˆœํžˆ ์ธ์ฝ”๋”ฉ๋œ ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ์ œ 3์ž๊ฐ€ ๋ณตํ˜ธํ™” ๋ฐ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Signature๋Š” ์„œ๋ฒ„ ์ธก์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๋น„๋ฐ€ํ‚ค๊ฐ€ ์œ ์ถœ๋˜์ง€ ์•Š๋Š” ์ด์ƒ ๋ณตํ˜ธํ™”ํ•  ์ˆ˜ ์—†๋‹ค. → ๋”ฐ๋ผ์„œ Signature๋Š” ํ† ํฐ์˜ ์œ„๋ณ€์กฐ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š”๋ฐ ์‚ฌ์šฉ

 

๐Ÿ“’ ๋™์ž‘๋ฐฉ์‹

[์ถœ์ฒ˜] https://velog.io/@junghyeonsu/ํ”„๋ก ํŠธ์—์„œ-๋กœ๊ทธ์ธ์„-์ฒ˜๋ฆฌํ•˜๋Š”-๋ฐฉ๋ฒ•

  1. ํด๋ผ์ด์–ธํŠธ ๋กœ๊ทธ์ธ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด, ์„œ๋ฒ„๋Š” ๊ฒ€์ฆ ํ›„ ํด๋ผ์ด์–ธํŠธ ๊ณ ์œ  ID ๋“ฑ์˜ ์ •๋ณด๋ฅผ Payload์— ๋‹ด๋Š”๋‹ค
  2. ์•”ํ˜ธํ™”ํ•  ๋น„๋ฐ€ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด Access Token(JWT)์„ ๋ฐœ๊ธ‰
  3. ํด๋ผ์ด์–ธํŠธ๋Š” ์ „๋‹ฌ๋ฐ›์€ ํ† ํฐ์„ ์ €์žฅํ•ด๋‘๊ณ , ์„œ๋ฒ„์— ์š”์ฒญํ•  ๋•Œ ๋งˆ๋‹ค ํ† ํฐ์„ ์š”์ฒญ ํ—ค๋” Authorization์— ํฌํ•จ์‹œ์ผœ ํ•จ๊ป˜ ์ „๋‹ฌ
  4. ์„œ๋ฒ„๋Š” ํ† ํฐ์˜ Signature๋ฅผ ๋น„๋ฐ€ํ‚ค๋กœ ๋ณตํ˜ธํ™”ํ•œ ๋‹ค์Œ, ์œ„๋ณ€์กฐ ์—ฌ๋ถ€ ๋ฐ ์œ ํšจ ๊ธฐ๊ฐ„ ๋“ฑ์„ ํ™•์ธ
  5. ์œ ํšจํ•œ ํ† ํฐ์ด๋ผ๋ฉด ์š”์ฒญ์— ์‘๋‹ต

 

๐Ÿ“• ํ† ํฐ์„ ์œ ์ง€ํ•˜๋Š” ์œ„์น˜

secure httpOnly ์ฟ ํ‚ค, ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€, ์ฟ ํ‚ค ๋“ฑ์ด ์กด์žฌํ•œ๋‹ค

  • ์ฟ ํ‚ค: XSS(Cross-site scripting)์™€ CSRF(Cross-site request forgery): ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ ์šฐ๋ฆฌ ๋„๋ฉ”์ธ์œผ๋กœ API Call์„ ๋‚ ๋ฆฌ๋Š” ๊ณต๊ฒฉ์— ์ทจ์•ฝ
  • localStorage: ๊ณต๊ฒฉ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋ธŒ๋ผ์šฐ์ €์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•ด ๊ณต๊ฒฉํ•˜๋Š” XSS(Cross-site scripting)์— ์ทจ์•ฝ
  • secure httpOnly ์ฟ ํ‚ค: CSRF ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค.

 

๐Ÿ“— ๊ตฌํ˜„ 

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์ฟ ํ‚ค์— JWT๋ฅผ ์ €์žฅํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์—์„œ ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ์„œ๋ฒ„์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ณ  ๋“ฑ๋ก๋œ ์œ ์ €์ธ ๊ฒฝ์šฐ ๋˜๋Š” Oauth๋ฅผ ํ†ตํ•ด ์‘๋‹ต๋ฐ›์€ ๊ฐ’์ด ์ •์ƒ์ ์ผ ๋•Œ JWT๋ฅผ resopnse์™€ ํ•จ๊ป˜ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ด์ค€๋‹ค.

 

const createToken = (accessToken: string, expirePeriod: string) => {
  return jwt.sign({ accessToken }, process.env.JWT_SECRET_KEY, {
    expiresIn: expirePeriod,
  });
};

const decodeToken = (accessToken: string) => {
  return jwt.verify(accessToken, process.env.JWT_SECRET_KEY || '');
};
const { data: requestToken } = await axios.post(baseURI, body, {
  headers: { Accept: 'application/json' },
});

const { access_token: accessToken } = requestToken;

res.cookie('accessToken', createToken(accessToken, '7d'), {
  maxAge: 1000 * 60 * 60 * 24 * 7,
  httpOnly: true,
});

์œ„ ์ฝ”๋“œ๋Š” Oauth๋ฅผ ํ™œ์šฉํ–ˆ๋˜ ์ฝ”๋“œ์ธ๋ฐ baseURI๋กœ post ์š”์ฒญ์„ ํ•˜๊ณ  ๋ฐ›์•„์˜จ access token์„ JWT์˜ payload๋กœ ๋„ฃ์–ด์ค€ ์ฝ”๋“œ์ด๋‹ค. 

 

ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ๋กœ๊ทธ์ธ ์ดํ›„ ๋กœ๊ทธ์ธ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ์–ด๋– ํ•œ ์š”์ฒญ์„ ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„ ์ธก์—์„œ JWT๋ฅผ ํ†ตํ•œ ๊ฒ€์ฆ์ด ์ด๋ฃจ์–ด์ง€๊ณ  ์˜ฌ๋ฐ”๋ฅผ ๊ฒฝ์šฐ์—๋งŒ ์ œ๋Œ€๋กœ ๋œ ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ ์ธก์œผ๋กœ ์ „์†กํ•ด์ฃผ๋„๋ก ํ–ˆ๋‹ค. ๊ฒ€์ฆ์ด ์ด๋ฃจ์–ด์ง€๋Š” ๊ณผ์ •์€ JWT์˜ payload๋ฅผ ํ•ด์„ํ•˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์˜ฌ๋ฐ”๋ฅธ ์œ ์ €์ธ์ง€ ํ™•์ธํ–ˆ์—ˆ๋Š”๋ฐ ์„ธ์…˜์„ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„์ธก์—์„œ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค๋ฉด ํ›จ์”ฌ ํšจ์œจ์ ์ธ ์ฝ”๋“œ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™๋‹ค.