Ghost Jwt Post Tech

๐Ÿง  Ghost Admin API์—์„œ JWT ์ธ์ฆ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ๊ธฐ

Ghost ๋ธ”๋กœ๊ทธ์—์„œ Admin API๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด JWT๋ฅผ ๋ฐœ๊ธ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์„œ๋„ ๋งŽ๊ณ  ์˜ˆ์ œ๋„ ์žˆ์–ด์„œ ๊ฐ„๋‹จํ•ด ๋ณด์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์ž‘์€ ์ฐจ์ด ํ•˜๋‚˜๋กœ ๊ณ„์† ์ธ์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์€ datetime.utcnow()๋กœ JWT๋ฅผ ๋ฐœ๊ธ‰ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•œ 401 Invalid JWT ๋ฌธ์ œ์˜ ์›์ธ์„ ๋ถ„์„ํ•˜๊ณ ,
"์™œ datetime.now()๋กœ๋Š” ๋˜๋Š”๋ฐ, utcnow()๋กœ ํ•˜๋ฉด ์‹คํŒจํ• ๊นŒ?"๋ผ๋Š” ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋ชจ๋“  ํ•ด๋‹ต์„ ๋‹ด์•˜์Šต๋‹ˆ๋‹ค.


โณ JWT ๊ธฐ๋ณธ ๊ตฌ์กฐ

JWT๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ์‹œ๊ฐ„ ๊ด€๋ จ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:

ํ•„๋“œ ์„ค๋ช…
iat ํ† ํฐ ๋ฐœ๊ธ‰ ์‹œ๊ฐ (issued at)
exp ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ (expiration)
{
  "iat": 1712900400,
  "exp": 1712900700
}

๐Ÿ” Ghost๋Š” ์–ด๋–ป๊ฒŒ JWT๋ฅผ ๊ฒ€์ฆํ• ๊นŒ?

Ghost๋Š” jsonwebtoken์ด๋ผ๋Š” Node.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด JWT๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
Ghost์˜ ํ•ต์‹ฌ ์ฝ”๋“œ (core/server/services/auth/api-key/admin.js)๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

const verified = jwt.verify(token, secret, {
    audience: '/admin/',
    algorithms: ['HS256'],
    ignoreExpiration: false
});

ignoreExpiration: false๋Š” ๋งŒ๋ฃŒ์‹œ๊ฐ„(exp)์„ ๋ฐ˜๋“œ์‹œ ๊ฒ€์‚ฌํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.


โ“ ์‹คํ—˜ ๊ฒฐ๊ณผ: now()๋Š” ๋˜๊ณ , utcnow()๋Š” ์‹คํŒจ?

์‹คํ—˜ 1 - datetime.now() ์‚ฌ์šฉ (KST ๊ธฐ์ค€)

  • ์ƒ์„ฑ๋œ iat: ํ˜„์žฌ ์‹œ๊ฐ„๋ณด๋‹ค ๋ฏธ๋ž˜๋กœ ์ธ์‹
  • โœ… ์ •์ƒ ์ธ์ฆ๋จ

์‹คํ—˜ 2 - datetime.utcnow() + 10์ดˆ ์‚ฌ์šฉ

  • ์ƒ์„ฑ๋œ iat: Ghost ์„œ๋ฒ„๋ณด๋‹ค ๊ณผ๊ฑฐ ์‹œ์ ์œผ๋กœ ์ธ์‹
  • โŒ 401 INVALID_JWT ์˜ค๋ฅ˜ ๋ฐœ์ƒ

๐Ÿงญ ์›์ธ์€ ์„œ๋ฒ„ ์‹œ๊ฐ„๊ณผ์˜ ์˜ค์ฐจ

์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ํ™•์ธํ•œ ์„œ๋ฒ„ ์‹œ๊ฐ„:

$ docker exec -it ghost date
Sat Apr 12 15:14:10 UTC 2025

์ฆ‰, JWT ๋ฐœ๊ธ‰ ์‹œ์ ์ด ์„œ๋ฒ„ ์‹œ๊ฐ„๋ณด๋‹ค ์•ž์„œ ์žˆ์–ด์•ผ ํ† ํฐ์ด ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.
utcnow()๋Š” ์‹ค์ œ ์„œ๋ฒ„๋ณด๋‹ค ๋ช‡ ์ดˆ ๊ณผ๊ฑฐ๋กœ ์ฐํžˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋˜ ๊ฒƒ์ด์ฃ .


โœ… ์ •๋ฆฌ

ํ•ญ๋ชฉ ์„ค๋ช… ๊ถŒ์žฅ
iat ํ† ํฐ ์ƒ์„ฑ ์‹œ๊ฐ„ ์„œ๋ฒ„ ์‹œ๊ฐ„๋ณด๋‹ค ๋ฏธ๋ž˜๋กœ ์„ค์ • โŒ
exp ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ๋ฐ˜๋“œ์‹œ ์ฒดํฌ๋จ โœ…
datetime.utcnow() ์‹œ์Šคํ…œ ์‹œ๊ฐ„ ์˜ค์ฐจ์— ๋ฏผ๊ฐ ๋ฒ„ํผ ์ถ”๊ฐ€ ํ•„์š”
datetime.now() KST ๊ธฐ์ค€์ด๋ผ ์„œ๋ฒ„๋ณด๋‹ค ๊ณผ๊ฑฐ๋กœ ์ธ์‹๋  ์ˆ˜ ์žˆ์Œ โœ… ํ†ต๊ณผ๋  ํ™•๋ฅ  ๋†’์Œ
ignoreExpiration false์ด๋ฉด exp๋Š” ๊ผญ ๊ฒ€์‚ฌํ•จ โ—์ฃผ์˜

๐Ÿ’ก ์‹ค์ „ ํŒ

  • ๊ฐ€๋Šฅํ•œ datetime.utcnow() + 5~10์ดˆ ๋ฒ„ํผ ์ถ”๊ฐ€
  • ์„œ๋ฒ„๋Š” ๋ฐ˜๋“œ์‹œ NTP ๋™๊ธฐํ™”
  • ํ† ํฐ ์œ ํšจ ์‹œ๊ฐ„์€ 5~10๋ถ„ ์ด๋‚ด ์œ ์ง€

๐Ÿ™‡ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์ด๋ฒˆ ๋ฌธ์ œ๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ๋ฅผ ๊ณ ์น˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ,
์‹œ๊ฐ„ ๋™๊ธฐํ™”์™€ JWT ํ‘œ์ค€ ์ดํ•ด๊ฐ€ ํ•จ๊ป˜ ํ•„์š”ํ•œ ์ด์Šˆ์˜€์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์€ Joon์˜ ์‹คํ—˜๊ณผ ChatGPT์˜ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


๐Ÿท ํƒœ๊ทธ

tech, ghost, jwt, debug

igotoo

igotoo