์ฐธ๊ณ ์ฌ์ดํธ
๐ผ ๊ตฌ์กฐ
jwt๋ ' . ' ์ ๊ตฌ๋ถ์๋ก 3๊ฐ์ง ๋ฌธ์์ด๋ก ๊ตฌ์ฑ๋์ด ์๋ค. ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
๐ท๐ปโ๏ธ Header
Header๋ ๋๊ฐ์ง์ ์ ๋ณด๋ฅผ ์ง๋๊ณ ์๋ค.
• typ: ํ ํฐ์ ํ์ ์ ์ง์ ํ๋ค. ์ฆ, jwt
• alg: ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ง์ ํ๋ค.
ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ๋ณดํต HMAC SHA256 ํน์ RSA๊ฐ ์ฌ์ฉ๋๋ฉฐ, ์ด ์๊ณ ๋ฆฌ์ฆ์ ํ ํฐ์ ๊ฒ์ฆํ ๋ ์ฌ์ฉ๋๋ signature๋ถ๋ถ์์ ์ฌ์ฉ๋๋ค.
{
"typ": "JWT",
"alg": "HS256"
}
๋ค์์ base64๋ก ์ธ์ฝ๋ฉ ํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
const header = {
typ: 'JWT',
alg: 'HS256',
};
const encodedHeader = new Buffer(JSON.stringify(header))
.toString('base64')
.replace('=', '');
console.log(encodedHeader);
$ node src/Back/Auth/jwt.js
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
jwt์ Header๊ฐ ์์ฑ๋์๋ค.
๐ Payload
Payload๋ ํ ํฐ์ ๋ด์ ์ ๋ณด๋ค์ด ๋ด๊ฒจ์๋ค.
์ฌ๊ธฐ์ ๋ด๋ ์ ๋ณด์ ํ'์กฐ๊ฐ'์ ํด๋ ์(claim)์ด๋ผ๊ณ ๋ถ๋ฅด๊ณ , ์ด๋ name - value ์ ํ ์์ผ๋ก ์ด๋ฃจ์ด์ ธ์๋ค.
ํ ํฐ์๋ ์ฌ๋ฌ๊ฐ์ ํด๋ ์์ ๋ฃ์ ์ ์๋ค.
ํด๋ ์์ ์ข ๋ฅ๋ ๋ค์๊ณผ ๊ฐ์ด ํฌ๊ฒ ์ธ ๋ถ๋ฅ๊ฐ ์๋ค.
• ๋ฑ๋ก๋(registered) ํด๋ ์
• ๊ณต๊ฐ(public) ํด๋ ์
• ๋น๊ณต๊ฐ(private) ํด๋ ์
๐ ๋ฑ๋ก๋(registered) ํด๋ ์
• iss: ํ ํฐ ๋ฐ๊ธ์ (issuer)
• sub: ํ ํฐ ์ ๋ชฉ(subject)
• aud: ํ ํฐ ๋์์(audience)
• exp: ํ ํฐ์ ๋ง๋ฃ์๊ฐ (expiration), ์๊ฐ์ NummericDate ํ์์ผ๋ก ๋์ด์์ด์ผ ํ๋ฉฐ ์ธ์ ๋ ํ์ฌ ์๊ฐ๋ณด๋ค ์ดํ๋ก ์ค์ ๋์ด ์์ด์ผํ๋ค.
• nbf: Not Before๋ฅผ ์๋ฏธํ๋ฉฐ, ํ ํฐ์ ํ์ฑ ๋ ์ง์ ๋น์ทํ ๊ฐ๋ ์ ๋๋ค. ์ฌ๊ธฐ์๋ NumericDate ํ์์ผ๋ก ๋ ์ง๋ฅผ ์ง์ ํ๋ฉฐ, ์ด ๋ ์ง๊ฐ ์ง๋๊ฐ๊ธฐ ์ ๊น์ง๋ ํ ํฐ์ด ์ฒ๋ฆฌ๋์ง ์๋๋ค.
• iat: ํ ํฐ์ด ๋ฐ๊ธ๋ ์๊ฐ(issued at), ์ด ๊ฐ์ ์ฌ์ฉํ์ฌ ํ ํฐ์ age๊ฐ ์ผ๋ง๋ ๋์๋์ง ํ๋จ ํ ์ ์๋ค.
• jti: jwt ๊ณ ์ ์ ์๋ณ์๋ก์, ์ฃผ๋ก ์ค๋ณต์ ์ธ ์ฒ๋ฆฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํ์ฌ ์ฌ์ฉํฉ๋๋ค. ์ผํ์ฉ ํ ํฐ์ ์ฌ์ฉํ๋ฉด ์ ์ฉํ๋ค.
๐ ๊ณต๊ฐ(public) ํด๋ ์
๊ณต๊ฐ ํด๋ ์๋ค์ ์ถฉ๋์ด ๋ฐฉ์ง๋ (collisiton-resistant) ์ด๋ฆ์ ๊ฐ์ง๊ณ ์์ดํ๋ค. ์ถฉ๋์ ๋ฐฉ์งํ๊ธฐ ์ํด์๋, ํด๋ ์ ์ด๋ฆ์ URI ํ์์ผ๋ก ์ง์ต๋๋ค.
{
"http://localhost:3000/jwt_claim/admin": true
}
๐ ๋น๊ณต๊ฐ(private) ํด๋ ์
๋ฑ๋ก๋ ํด๋ ์๋ ์๋๊ณ , ๊ณต๊ฐ๋ ํด๋ ์๋ ์๋๋ค. ์ ์ธก๊ฐ์(ํด๋ผ์ด์ธํธ์ ์๋ฒ) ํ์ํ์ ์ฌ์ฉ๋๋ ํด๋ ์ ์ด๋ฆ๋ค์ด๋ค.
๊ณต๊ฐ ํด๋ ์๊ณผ๋ ๋ฌ๋ฆฌ ์ด๋ฆ์ด ์ค๋ณต๋์ด ์ถฉ๋์ด ๋ ์ ์์ผ๋ ์ฌ์ฉ์ ์ ์ํด์ผํ๋ค.
{
"username": "ma.caron_g"
}
payload๋ฅผ ์์๋ก ๋ง๋ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
{
"iss": "ma.caron_g",
"exp": "1488970000000",
"http://localhost:3000/jwt_claims/admin": true,
"userId": "123456789",
"username": "macarong"
}
๋ค์์ base64๋ก ์ธ์ฝ๋ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
const payload = {
iss: 'ma.caron_g',
exp: '1488970000000',
'http://localhost:3000/jwt_claims/admin': true,
userId: '123456789',
username: 'macarong',
};
const encodedPayload = new Buffer(JSON.stringify(payload))
.toString('base64')
.replace('=', '');
console.log(encodedPayload);
$ node src/Back/Auth/jwt.js
eyJpc3MiOiJtYS5jYXJvbl9nIiwiZXhwIjoiMTQ4ODk3MDAwMDAwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9qd3RfY2xhaW1zL2FkbWluIjp0cnVlLCJ1c2VySWQiOiIxMjM0NTY3ODkiLCJ1c2VybmFtZSI6Im1hY2Fyb25nIn0
jwt์ ๋ ๋ฒ์งธ ํํธ๊ฐ ์์ฑ๋์๋ค.
๐๏ธ Signature
JSON Web Token์ ๋ง์ง๋ง์ ๋ฐ๋ก ์๋ช (signature)์ด๋ค.
์ด ์๋ช ์ ํค๋์ ์ธ์ฝ๋ฉ๊ฐ๊ณผ ์ ๋ณด์ ์ธ์ฝ๋ฉ๊ฐ์ ํฉ์น ํ ์ฃผ์ด์ง ๋น๋ฐํค๋ก ํด์ฌํ์ฌ ์์ฑํ๋ค.
์๋ช ๋ถ๋ถ์ ๋ง๋๋ ์๋์ฝ๋(pseudocode)์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
์ด๋ ๊ฒ ๋ง๋ ํด์๋ฅผ, base64 ํํ๋ก ๋ํ๋ธ๋ค.
const crypto = require('crypto');
const signature = crypto
.createHmac('sha256', 'secret')
.update(encodedHeader + '.' + encodedPayload)
.digest('base64')
.replace('=', '');
console.log(signature);
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
$ node src/Back/Auth/jwt.js
BGhaVOC4b8xm1XEUZdqcNR80yiVszo6WP+97K8ucC4U
์ด๋ก์จ ๋ชจ๋ ๊ฐ์ ํฉ์ณ์
ํ๋์ ํ ํฐ์ด ์์ฑ๋๋ค.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJtYS5jYXJvbl9nIiwiZXhwIjoiMTQ4ODk3MDAwMDAwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9qd3RfY2xhaW1zL2FkbWluIjp0cnVlLCJ1c2VySWQiOiIxMjM0NTY3ODkiLCJ1c2VybmFtZSI6Im1hY2Fyb25nIn0.BGhaVOC4b8xm1XEUZdqcNR80yiVszo6WP+97K8ucC4U
ํด๋น ๊ฐ์ jwt ์ฌ์ดํธ ๋๋ฒ๊ฑฐ์ ๋ถ์ฌ๋ฃ์ผ๋ฉด ๋๋ฒ๊ทธ ํ ์ ์๋ค.
'Library > Auth' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ jwt ] React, Nodejs - jwtํ ํฐ์ ๋ฐ๊ธํ๊ณ ์ ํจ์ฑ์ ๊ฒ์ฌํด๋ณด์. (0) | 2024.02.29 |
---|---|
[ jwt ] AccessToken๊ณผ RefreshToken (0) | 2024.02.23 |
[ bcrypt ] ๐ ๋ฐ์ดํฐ ์ํธํ ํด๋ณด๊ธฐ (2) | 2024.02.22 |
[ jwt ] ๋ก๊ทธ์ธ - Json Web Token์ ๋ํด ์์๋ณด๊ธฐ (0) | 2024.02.21 |