๐Ÿค” JWT, ์ •ํ™•ํ•˜๊ฒŒ ๋ฌด์—‡์ด๊ณ  ์™œ ์“ฐ์ด๋Š” ๊ฑธ๊นŒ?

junghyeonsuยท2021๋…„ 9์›” 14์ผ
48

์ง€์‹์ •๋ฆฌ

๋ชฉ๋ก ๋ณด๊ธฐ
4/4
post-thumbnail

๐Ÿค” ํ™•์‹คํ•˜๊ฒŒ ํ•˜์ž

์ด๋ฒˆ์— ์กธ์—…ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฐœ๋ฐœํ•˜๋‹ค๊ฐ€ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„์„ ํ•˜๋Š”๋ฐ
๊ทธ๋ƒฅ ID / Password ๊ฐ’์„ ๋ฐ›์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋น„๊ตํ•˜๋Š” ๊ทธ๋Ÿฐ ๋กœ์ง์„ ์งœ๊ธฐ ์‹ซ์—ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์นœ๊ตฌ๋“ค๊ณผ ํšŒ์˜๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ JWT(Json Web Token).
์นœ๊ตฌ๋“ค์ด JWT๋ฅผ ์“ฐ์ž๊ณ  ํ•ด์„œ ์“ด๊ฑฐ์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์™œ ์“ฐ๋Š”์ง€ ๋ชจ๋ฅด๊ณ  ์“ฐ๋Š”๊ฑด ์˜๋ฏธ๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์ •๋ฆฌํ•˜๋Š” ๊น€์— ํ™•์‹คํ•˜๊ฒŒ ํ•˜๊ณ  ๊ฐ€์ž๋Š” ์ทจ์ง€๋กœ ์ž‘์„ฑ๋œ ๊ธ€.

๐Ÿ“Œ HTTP ํ†ต์‹ 

์™œ ๊ฐ‘์ž๊ธฐ HTTP์— ๋Œ€ํ•ด์„œ ๋‚˜์˜ค๋Š”์ง€ ๊ถ๊ธˆํ•  ์ˆ˜ ์žˆ๋‹ค.
"๋กœ๊ทธ์ธ" ์ด๋ผ๋Š” ๊ณผ์ •์€ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ํ†ต์‹  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค.
๊ทธ ํ†ต์‹  ๋ฐฉ๋ฒ•์ด HTTP ๋ผ๋Š” ํ”„๋กœํ† ์ฝœ(ํ†ต์‹  ๋ฐฉ๋ฒ•)์ด๋‹ค.
HTTP์—๋Š” ๋ช‡ ๊ฐ€์ง€ ํŠน์„ฑ์ด ์žˆ๋‹ค.

connectionless

HTTP๋Š” ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ผ๋Š” ํŠน์„ฑ์ด๋‹ค.
์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•œ๋ฒˆ ํ†ต์‹ ์ด ์ผ์–ด๋‚˜๊ณ  ๋‚˜๋ฉด
๊ทธ ์—ฐ๊ฒฐ์ด ์œ ์ง€๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฐ”๋กœ ๋Š์–ด์ง„๋‹ค.

stateless

HTTP๋Š” ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ผ๋Š” ํŠน์„ฑ์ด๋‹ค.
์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋Š” ์ฒซ๋ฒˆ์งธ ํ†ต์‹ ์„ ํ•˜๊ณ  ๋‚˜์„œ ๋‘๋ฒˆ์งธ ํ†ต์‹ ์„ ํ•  ๋•Œ๋Š”
์ด์ „์˜ ํ†ต์‹ ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กญ๊ฒŒ ๊ฐฑ์‹ ์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์œ„์˜ ํŠน์„ฑ๋“ค ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ "๋กœ๊ทธ์ธ"์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ๋งŽ์€ ์–ด๋ ค์›€์ด ์žˆ๋‹ค.
์‚ฌ์šฉ์ž๊ฐ€ ๋งค๋ฒˆ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ๋งˆ๋‹ค
์ž์‹ ์ด ๋ˆ„๊ตฌ์ธ์ง€ ๊ณ„์†ํ•ด์„œ ์ธ์ฆ์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ.
๋งค๋ฒˆ ์„œ๋ฒ„์— ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€ ์ธ์ฆ์„ ํ•˜๋Š” ๊ณผ์ •์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ๊ท€์ฐฎ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ
๋งค๋ฒˆ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ์˜ ์›นํŽ˜์ด์ง€๊ฐ€ ๋Š๋ ค์ง€๋Š” ์›์ธ์ด ๋œ๋‹ค.

์œ„์˜ ์›์ธ๊ณผ ์ด์œ ๋กœ ์šฐ๋ฆฌ๋Š”
์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€ ๊ณ„์†ํ•ด์„œ ์ธ์ฆ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ• ๋Œ€์‹ 
๋‹ค๋ฅธ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์œ ์ง€์‹œํ‚ฌ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ๋‹ค.

์•„๋ž˜ ๋ฐฉ๋ฒ•๋“ค์€ ๋กœ๊ทธ์ธ์„ ์œ ์ง€ ์‹œํ‚ฌ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.

๐Ÿ“Œ ๋กœ๊ทธ์ธ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฒ•

Not good ๐Ÿ‘Ž

์œ„์—์„œ ์–˜๊ธฐํ•œ๋Œ€๋กœ ์œ ์ €์—๊ฒŒ ID / Password ๋ฅผ ๋ฐ›์•„์„œ, ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ทธ๋ƒฅ ๋น„๊ตํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

ํ•ด๋‹น ๋ฐฉ๋ฒ•์€ ๋กœ๊ทธ์ธ ์œ ์ง€๊ฐ€ ์•ˆ๋  ๋ฟ๋”๋Ÿฌ
์ •๋ณด๊ฐ€ ์œ ์ง€๋˜์ง€ ์•Š์œผ๋ฉด, ๋งค๋ฒˆ ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค ๋กœ๊ทธ์ธ์„ ๋‹ค์‹œ ํ•˜๊ฑฐ๋‚˜,
์ƒํ’ˆ์„ ์„ ํƒํ–ˆ๋Š”๋ฐ ๊ตฌ๋งค ํŽ˜์ด์ง€์—์„œ ์„ ํƒํ•œ ์ƒํ’ˆ์˜ ์ •๋ณด๊ฐ€ ์—†๊ฑฐ๋‚˜ ํ•˜๋Š” ๋“ฑ์˜ ์ผ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฌด์–ธ๊ฐ€ ๋‹ค๋ฅธ, ๋กœ๊ทธ์ธ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ณ  ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ๋‹ค.

Good ๐Ÿ‘

Session (์„ธ์…˜) vs Token (ํ† ํฐ)

๋‚˜๋Š” ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋ชจ๋‘ JWT, JWT๋งŒ ์™ธ์ณ์„œ JWT ๋ฐฉ์‹๋ฐ–์— ์—†๋Š” ์ค„ ์•Œ์•˜๋‹ค.
์ฐพ์•„๋ณด๋‹ˆ ํ† ํฐ ๋ฐฉ์‹๋ง๊ณ ๋„ ์„ธ์…˜ ๋ฐฉ์‹์ด ์žˆ์—ˆ๋‹ค.

์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์ •๋ณด์— ๋Œ€ํ•œ ๊ฒƒ์„ ์–ด๋””๋‹ค๊ฐ€ ์œ ์ง€, ์ €์žฅ์„ ํ•˜๋Š๋ƒ์— ๋”ฐ๋ผ ๋‘ ๋ฐฉ์‹์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

์„ธ์…˜ ๋ฐฉ์‹ (์„œ๋ฒ„ ์œ ์ง€)

์„ธ์…˜ ๋ฐฉ์‹์€ ์„œ๋ฒ„์˜ ๋ฉ”๋ชจ๋ฆฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ™์€ ์„œ๋ฒ„์˜ ์ž์›๋“ค์„ ์‚ฌ์šฉํ•ด์„œ
์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์œ ์ง€์‹œํ‚ค๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ด๋ฏธ์ง€ ์ถœ์ฒ˜-JWT(Json Web Token)์€ ์™œ ์‚ฌ์šฉ๋ ๊นŒ

ํ† ํฐ๋ฐฉ์‹๋ณด๋‹ค ๋ณด์•ˆ์— ๊ฐ•ํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ
๋‹จ์ ์œผ๋กœ๋Š” ์„œ๋ฒ„์˜ ํ™•์žฅ์„ฑ์ด ๋–จ์–ด์ง€๊ณ , ์„œ๋ฒ„์˜ ์ž์›(์„ธ์…˜์„ ์ €์žฅ, ์œ ์ง€ํ•  ๊ณต๊ฐ„)์ด ๋งŽ์ด ํ•„์š”ํ•˜๋‹ค.
๋˜ํ•œ ์„ธ์…˜์ด ์„œ๋ฒ„์— ์ €์žฅ์ด ๋˜๊ณ , ํŠธ๋ž˜ํ”ฝ ๋ถ„์‚ฐ์„ ์œ„ํ•ด์„œ ์—ฌ๋Ÿฌ ๋Œ€์˜ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ
๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ–ˆ์„ ๋•Œ๋Š” ๋งŒ๋“ค์–ด์ง„ ์„ธ์…˜์„ ์ฐธ์กฐํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
์ฒ˜์Œ ๋กœ๊ทธ์ธํ•œ ๊ทธ ์„œ๋ฒ„์—์„œ๋งŒ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ  ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์€ ํ† ํฐ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

ํ† ํฐ ๋ฐฉ์‹ (ํด๋ผ์ด์–ธํŠธ ์œ ์ง€)

ํ† ํฐ ๋ฐฉ์‹์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ๋ฐœํ–‰ํ•ด์ฃผ๋Š” ํ† ํฐ์„ ๊ฐ€์ง€๊ณ 
๋ธŒ๋ผ์šฐ์ €์˜ ์ €์žฅ์†Œ์— ํ† ํฐ์„ ์œ ์ง€์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
์š”๊ธฐ์„œ ๋งํ•˜๋Š” ํ† ํฐ์ด ์šฐ๋ฆฌ๊ฐ€ ๋งํ•˜๋Š” JWT์ด๋‹ค.

์„œ๋ฒ„์— ์ €์žฅํ•˜์ง€ ์•Š์•„์„œ ์„œ๋ฒ„์— ํ™•์žฅ์„ฑ์ด ์žˆ๋‹ค.
์œ„์—์„œ ๋งํ–ˆ๋“ฏ ๋กœ๊ทธ์ธ์„ ํ–ˆ์„ ๋•Œ ํ•ด๋‹น ์„œ๋ฒ„์—๋งŒ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹Œ
์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ ํ•ด๋‹น ํ† ํฐ์ด ์œ ํšจํ•œ์ง€๋งŒ ์ฒดํฌํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์—
์–ด๋–ค ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋„ ์ƒ๊ด€์ด ์—†๋‹ค๋Š” ๋œป์ด๋‹ค.

๐Ÿช™ JWT

JWT๋Š” ๋‘ ๊ฐœ์ฒด ์‚ฌ์ด์—์„œ ์•ˆ์ •์„ฑ์žˆ๊ฒŒ ์ •๋ณด๋ฅผ ๊ตํ™˜ํ•˜๊ธฐ ์ข‹์€ ๋ฐฉ๋ฒ•

JWT๋Š” ์šฐ๋ฆฌ๊ฐ€ ์œ„์—์„œ ๊ณ„์† ๋งํ•œ ์›น ํ† ํฐ, JSON Web Token์˜ ์•ฝ์ž์ด๋‹ค.
JWT๋Š” ์›นํ‘œ์ค€ (RFC 7519)์œผ๋กœ,
์ „์ž ์„œ๋ช… ๋œ URL-safe (URL๋กœ ์ด์šฉํ•  ์ˆ˜์žˆ๋Š” ๋ฌธ์ž ๋งŒ ๊ตฌ์„ฑ๋œ)์˜ JSON์ด๋‹ค.

JWT๋Š” .์„ ๊ธฐ์ค€์œผ๋กœ ์„ธ ํŒŒํŠธ๋กœ ๋‚˜๋‰œ๋‹ค.

Header

{
 	"alg": "์„œ๋ช… ์‹œ ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜",
	"kid": "์„œ๋ช… ์‹œ ์‚ฌ์šฉํ•˜๋Š” ํ‚ค๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๊ฐ’",
      	"typ": "ํƒ€์ž…"
}

ํ—ค๋”(Header)์—๋Š” JWT๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฒ€์ฆํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค.
ํ† ํฐ์˜ ํƒ€์ž…, ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์–ด๋–ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ๋‹ค.
ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ด๋ฆ„์„ ์ ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

payload

{
	"sub": "hyeonsu.jung",
    	"exp": 1623235123,
    	"iat": 1532341234
}

ํ† ํฐ์— ๋‹ด์•„์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ด๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ด๊ณณ์— ๋‹ด๊ฒจ์ ธ ์žˆ๋‹ค.
์ด ์ •๋ณด์˜ ์กฐ๊ฐ์€ ํด๋ ˆ์ž„(claim) ์ด๋ผ๊ณ  ํ•˜๊ณ , key - value์˜ ํ•œ ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  payload์—๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํด๋ ˆ์ž„์„ ๋‹ด์„ ์ˆ˜ ์žˆ๊ณ , ํด๋ ˆ์ž„์„ ๊ณต๊ฐœ(public) ํ˜น์€ ๋น„๊ณต๊ฐœ(private) ํ•  ๊ฒƒ์ธ์ง€ ๋“ฑ๋ก(registered)ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

signature

์‹œ๊ทธ๋‹ˆ์ฒ˜(signature)์—๋Š” ์œ„์˜ ํ—ค๋”(header)์™€ ํŽ˜์ด๋กœ๋“œ(Paylaod)๋ฅผ ํ•ฉ์นœ ๋ฌธ์ž์—ด์„ ์„œ๋ช…ํ•œ ๊ฐ’์ด๋‹ค. ์„œ๋ช…์€ ํ—ค๋”์˜ alg์— ์ •์˜๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ secret key๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•˜๊ณ  Base64 URL-Safe๋กœ ์ธ์ฝ”๋”ฉํ•œ๋‹ค.
secret key๋ฅผ ํฌํ•จํ•ด์„œ ์•”ํ˜ธํ™”๊ฐ€ ๋˜์–ด์žˆ๋‹ค.

์ƒ์„ฑ๋œ JWT๋Š” ์™ผ์ชฝ์˜ Encoded๋œ ๊ฐ’์ฒ˜๋Ÿผ ์ (.)์„ ๊ตฌ๋ถ„์ž๋กœ ํ—ค๋”, ํŽ˜์ด๋กœ๋“œ, ์‹œ๊ทธ๋‹ˆ์ณ๋กœ ๋‚˜๋ˆ ์„œ ์„œ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋˜๊ณ , ์„œ๋ฒ„๋Š” ํ—ค๋”์˜ alg, kid ์†์„ฑ๊ณผ ๊ณต๊ฐœ ํ‚ค๋ฅผ ์ด์šฉํ•ด ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ฒ€์ฆ(์ด ํ† ํฐ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ† ํฐ์ธ๊ฐ€?)๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด ํŽ˜์ด๋กœ๋“œ์˜ ๊ฐ’์œผ๋กœ ์ ‘๊ทผ์„ ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ.

์ž ๊น, ๊ณต๊ฐœ ํ‚ค(public key)์™€ ๋น„๋ฐ€ ํ‚ค(secret key)

JWT์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ณต๊ฐœ ํ‚ค ์•”ํ˜ธ ๋ฐฉ์‹(PKC, Public Key Cryptograpyh)๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ,
๋น„๋Œ€์นญ ์•”ํ˜ธ ๋ฐฉ์‹์„ ์ด์šฉํ•ด ๊ณต๊ฐœ ํ‚ค์™€ ๋น„๋ฐ€ ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด ํ‚ค๋“ค์„ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‚˜๋ˆ„์–ด ๊ฐ€์ง€๊ณ  ํ†ต์‹ ํ•œ๋‹ค.

์„œ๋ช…์€ ๋น„๋ฐ€ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ณณ์—์„œ๋งŒ ํ•  ์ˆ˜ ์žˆ๊ณ  ๊ณต๊ฐœ ํ‚ค๋ฅผ ๊ฐ€์ง„ ์–ด๋Š ๊ณณ์—์„œ๋‚˜ ์ด ๋ฐ์ดํ„ฐ์˜ ์„œ๋ช…์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ณต๊ฐœ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๋ˆ„๊ตฌ๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์ง€๋งŒ,
๋น„๋ฐ€ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ณณ์—์„œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณตํ˜ธํ™”ํ•ด์„œ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์š”๊ธฐ์„œ ์งš๊ณ  ๋„˜์–ด๊ฐ€์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๋น„๋Œ€์นญ ์•”ํ˜ธ ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์—
โŒ ๋น„๋ฐ€ ํ‚ค๋กœ ์•”ํ˜ธํ™”ํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋‹ค์‹œ ๋น„๋ฐ€ ํ‚ค๋กœ ํ’€ ์ˆ˜ ์—†๊ณ ,
โŒ ๊ณต๊ฐœ ํ‚ค๋กœ ์•”ํ˜ธํ™” ํ•œ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋Š” ๊ณต๊ฐœ ํ‚ค๋กœ ํ’€ ์ˆ˜ ์—†๋‹ค.

๐ŸŸข ์„œ๋ช…: ๋น„๋ฐ€ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ทน์†Œ์ˆ˜(์ฃผ๋กœ ํ•œ๋ช…)๋งŒ ๋ฐ์ดํ„ฐ์— ์„œ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ณต๊ฐœ ํ‚ค๋ฅผ ๊ฐ€์ง„ ์•„๋ฌด๋‚˜ ๋ฐ์ดํ„ฐ์˜ ์„œ๋ช…์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.
๐ŸŸข ์•”ํ˜ธํ™”: ๊ณต๊ฐœ ํ‚ค๋ฅผ ๊ฐ€์ง„ ์•„๋ฌด๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋น„๋ฐ€ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ทน์†Œ์ˆ˜๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณตํ˜ธํ™”ํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ JWT์˜ ์žฅ๋‹จ์ 

์žฅ์ 

  1. ์„ธ์…˜ ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ณ„๋„์˜ ์ธ์ฆ ์ €์žฅ์†Œ๊ฐ€ ํ•„์š” ์—†์–ด์„œ ์„œ๋ฒ„์™€์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์„ ์ตœ์†Œํ•œ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ํŠธ๋ž˜ํ”ฝ์— ๋Œ€ํ•œ ๋ถ€๋‹ด์ด ์ ๋‹ค.
  3. ์„ธ์…˜๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋…๋ฆฝ์ ์ธ ๋Š๋‚Œ์˜ JWT๋ฅผ ํ™œ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ.

๋‹จ์ 

  1. JWT์˜ ํฌ๊ธฐ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๊ฑฐ์˜ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ์ „์†ก๋˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ ํŠธ๋ž˜ํ”ฝ ํฌ๊ธฐ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค.
  2. ํ† ํฐ์€ ํด๋ผ์ด์–ธํŠธ์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— DB์—์„œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•˜๋”๋ผ๋„ ํ† ํฐ์— ์ง์ ‘ ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

๐Ÿ“Œ JWT ํ”„๋กœ์„ธ์Šค

Only "Access Token"

  1. ์‚ฌ์šฉ์ž๊ฐ€ id์™€ password๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์„œ๋ฒ„๋กœ ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
  2. ์„œ๋ฒ„๋Š” ๋น„๋ฐ€ ํ‚ค(secret key) ๋ฅผ ํ†ตํ•ด์„œ ์„œ๋ช…์„ ํ•˜๊ณ  ๊ณต๊ฐœ ํ‚ค(public key)๋กœ ์•”ํ˜ธํ™” ์‹œํ‚จ Access Token์„ ๋ฐœ๊ธ‰ํ•œ๋‹ค.
  3. Access Token์„ ์‚ฌ์šฉ์ž(ํด๋ผ์ด์–ธํŠธ)์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.

์š”๊ธฐ๊นŒ์ง€ํ•˜๋ฉด ์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์ธ์ด ๋œ ๊ฒƒ์ด๋‹ค.

  1. ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ API Call๋งˆ๋‹ค ํ† ํฐ์„ ์‹ค์–ด์„œ ๋ณด๋‚ธ๋‹ค.

์‚ฌ์šฉ์ž(ํด๋ผ์ด์–ธํŠธ)๋Š” API๋ฅผ ์š”์ฒญํ•  ๋–„ Authorization Header์— Access Token์„ ๋‹ด์•„์„œ ๋ณด๋‚ธ๋‹ค.

  1. ์„œ๋ฒ„์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ํ† ํฐ์„ ๊ณต๊ฐœ ํ‚ค(public key)๋กœ ์„œ๋ช…์„ ์ฒดํฌํ•˜๊ณ , ์•ˆ์— ๋‹ด๊ธด ์ •๋ณด๋ฅผ ํ™•์ธํ•œ๋‹ค.

์„œ๋ฒ„๋Š” secret key๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ํ† ํฐ์˜ ์„œ๋ช…์„ ๋ณตํ˜ธํ™”ํ•˜์—ฌ์„œ ์œ ํšจํ•œ ํ† ํฐ์ธ์ง€ ํ™•์ธํ•œ๋‹ค.

  1. ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์‚ฌ์šฉ์ž(ํด๋ผ์ด์–ธํŠธ)์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.

With "Refresh Token"

Access Token ๋งŒ์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ Refresh Token

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

Refresh Token ๋˜ํ•œ Access Token๊ณผ ๊ฐ™์€ JWT์ด๋‹ค.
๋กœ๊ทธ์ธ์„ ํ–ˆ์„ ๋•Œ ์„œ๋ฒ„์—์„œ Access Token, Refresh Token์„ ๋™์‹œ์— ๋ณด๋‚ด์ค€๋‹ค
๋‹จ, ๋‘˜์˜ ์œ ํšจ๊ธฐ๊ฐ„์„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์„œ ๋ณด๋‚ธ๋‹ค.

Refresh Token์„ ํ•œ ๋‹ฌ, Access Token ์„ ํ•˜๋ฃจ๋กœ ์žก์•˜๋‹ค๋ฉด
Access Token์˜ ๊ธฐ๊ฐ„์ด ๋‹ค ๋˜์–ด๋„ Refresh Token์˜ ๊ธฐ๊ฐ„์ด ๋‚จ์•„์žˆ๊ธฐ ๋•Œ๋ฌธ์—
์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์ธ ์—†์ด ๋‹ค์‹œ Access Token์„ ๋ฐœ๊ธ‰ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. (๋กœ๊ทธ์ธ ์œ ์ง€)

Refresh Token๋Š” Access Token๋ฅผ ๋‹ค์‹œ ๋ฐœ๊ธ‰๋ฐ›๊ธฐ ์œ„ํ•œ JWT.

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

ํ† ํฐ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ๋‹ค์–‘ํ•œ ๋ธŒ๋ผ์šฐ์ € ์ €์žฅ์†Œ๊ฐ€ ์žˆ๋‹ค.
secure httpOnly ์ฟ ํ‚ค, ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€, ์ฟ ํ‚ค์™€ ๊ฐ™์ด ๋‹ค์–‘ํ•œ๋ฐ
์ด๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์˜ ์ทจํ–ฅ๊ณผ ์žฅ๋‹จ์ ์ด ์„œ๋กœ ๋‹ค๋ฅด๋‹ค.

์œ„์˜ ๋‚ด์šฉ์€ ๋„ˆ๋ฌด ์ •๋ฆฌ๊ฐ€ ์ž˜๋˜์–ด์žˆ๋Š” ๊ธ€์ด ์žˆ์–ด์„œ ์ •๋…ํ•˜์˜€๋‹ค.
์•„๋ž˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ.

๐Ÿช ํ”„๋ก ํŠธ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ (ft. React)

๊ฐ„๋žตํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋ฉด

localStorage ์ €์žฅ ๋ฐฉ์‹์€
๊ณต๊ฒฉ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋ธŒ๋ผ์šฐ์ €์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•ด ๊ณต๊ฒฉํ•˜๋Š” XSS(Cross-site scripting)์— ์ทจ์•ฝํ•˜๊ณ ,

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

secure httpOnly ์—ญ์‹œ CSRF ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค.

์ด๋ ‡๊ฒŒ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์žˆ๊ณ , ์•Œ๋งž๋Š” ๋ณด์•ˆ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋“ค์˜ ์ •๋ณด๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ
๋ณด๊ด€๋˜๋„๋ก ๊ณ„์†ํ•ด์„œ ๋…ธ๋ ฅ์„ ํ•ด์•ผํ•œ๋‹ค.

๐Ÿ“Œ ๊ฒฐ๋ก 

  • HTTP์˜ connectionless, stateless ํŠน์„ฑ์— ์˜ํ•ด
    ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์œ ์ง€์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ ์•Œ๋งž์€ ์œ ์ง€ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ๋‹ค.

  • JWT๋Š” ์•”ํ˜ธํ™”, ๋ณตํ˜ธํ™”๋ฅผ ํ†ตํ•ด ๋‘ ๊ฐœ์ฒด ์‚ฌ์ด์—์„œ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ์ˆ˜๋‹จ์ด๋‹ค.

  • ํ•„์š”ํ•œ API

    • Refresh API
      • ์ƒˆ๋กœ๊ณ ์นจ, AccessToken ๋งŒ๋ฃŒ์‹œ์— ํ˜ธ์ถœ (setTimeout์œผ๋กœ ์ž๋™ ํ˜ธ์ถœ ์„ค์ • ๊ฐ€๋Šฅ)
      • RefreshToken์„ ์ฟ ํ‚ค์—์„œ ์ฝ์–ด์™€์„œ ์„œ๋ฒ„๋กœ ๋ณด๋ƒ„
      • RefreshToken,AccessToken์„ ๋‹ค ๋ฐ›์•„์˜ฌ์ง€ AccessToken๋งŒ ๋ฐ›์•„์˜ฌ์ง€๋Š” ์„ ํƒ
    • Login API
      • ๋กœ๊ทธ์ธ ์‹œ ํ˜ธ์ถœ
      • RefreshToken,AccessToken ์„ ๋ฐ›์•„์˜ด
    • API ํ˜ธ์ถœ ํ›„
      • AccessToken๋Š” header์— default๋กœ ์„ค์ •ํ•˜์—ฌ API๋งˆ๋‹ค ๋ณด๋‚ด๋„๋ก ์„ค์ •
      • AccessToken์˜ ์œ ํšจ๊ธฐ๊ฐ„์ด ๋๋‚˜๊ธฐ ์ „ ์ž๋™์œผ๋กœ Refresh API๊ฐ€ ํ˜ธ์ถœ๋˜๋„๋ก ์„ค์ • ๊ฐ€๋Šฅ (์„ ํƒ์ )
      • RefreshToken๋Š” ์ฟ ํ‚ค์— ์ €์žฅ
        - RefreshToken ๋˜ํ•œ ๊ธฐ๊ฐ„์ด ๋งŒ๋ฃŒ๋˜๋ฉด ์žฌ๋กœ๊ทธ์ธ์ด ํ•„์š”!

์ฐธ๊ณ 

profile
๋Š์ž„์—†๋Š” ์„ฑ์žฅ์„ ์ถ”๊ตฌ

6๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2021๋…„ 9์›” 16์ผ

Refresh Token ๊ด€๋ จํ•˜์—ฌ ๊ถ๊ธˆํ•œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค
Refresh Token๋„ ํƒˆ์ทจ๋‹นํ•œ๋‹ค๋ฉด Access Token๋งŒ ์‚ฌ์šฉํ–ˆ์„๋•Œ๋ž‘ ๋ณด์•ˆ์ƒ ์ฐจ์ด๊ฐ€ ์—†์ง€ ์•Š๋‚˜์š”?
๋‹ค๋ฅธ์ด์œ ๊ฐ€ ์žˆ์„๊นŒ์š”?

1๊ฐœ์˜ ๋‹ต๊ธ€
comment-user-thumbnail
7์ผ ์ „

ํ† ํฐ์„ ์ข…์ข… ํ™•์ธํ•ด์•ผํ•˜๋Š”๋ฐ ์–ธ์ œ ํ™•์ธํ•ด์•ผํ•˜๋‚˜์š”??

1๊ฐœ์˜ ๋‹ต๊ธ€
comment-user-thumbnail
4์ผ ์ „

minio-operator์—์„œ ์ธ์ฆํ‚ค jwt๋ฅผ ์ž…๋ ฅํ•˜๋ผ๊ณ  ํ• ๋•Œ ๋ญ”์ง€ ๊ถ๊ธˆํ–ˆ๋Š”๋ฐ ๊ถ๊ธˆ์ฆ ํ•ด๊ฒฐ...! ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!!

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ