2025. 2. 13. 11:27ㆍProgramming Language/Node.js
1. 인증을 위한 미들웨어 생성
먼저 클라이언트에서 토큰을 받을 텐데 클라이언트에서 토큰이랑 같이 정보를 보낼텐데 이 토큰은 요청의 requet.header['authorization']에 들어 있게 된다.
그래서 인증 하는 미들웨어에서 받을때 토큰에 있는 헤더에서 요청한 값을 가져오게 될것이다.
근데 우리는 이 토큰을 포스트맨을 사용해서 직접 넣어서 보내줘야 한다.
이전에 토큰을 요청하는 메서드를 통해 토큰을 받은 다음에
포스트맨 URL창 밑에 Authorization을 선택
Auth Type을 Bearer Token을 선택해준 후에
옆창에 생성되는 토큰 입력 칸에
토큰을 넣어주자.
그러면 헤더 안에 Authorization에 자동으로 넣어주게 된다.
이를 통해서 먼저 토큰을 서버로 요청의 헤더에담아 보내주는 부분이고 이제 이 토큰을 서버에서 받아 처리할 수 있도록 해야한다.
먼저 미들웨어를 생성하고
이 미들웨어가 특정 요청을 받을때 사용되기 위해서는 요청을 받아주는 함수의
두번째 매개변수에 미들웨어가 들어가야한다.
이런식으로 그런데 우리는 이 미들웨어를 함수로 만들어 줄 것이기 때문에 그냥 저 미들웨어 공간에 미들웨어 함수를 넣어주면 된다.
이제 요청에 들어 있던 토큰을 확인할 차례인데 토큰은 request의 header의 authorization안에 들어 있다고 했었고 이걸 가져와서 변수로 담아준 다음에
콘솔로 출력해서 확인해보기 위해서 요청을 보내보면
아래와 같이 토큰이 전달됨을 볼 수 있다.
여기서 우리는 앞 Bearer문자열을 제외한 나머지를 얻기 위해서 토큰값이 있다면(authRowToken이 있다면) 토큰값만 갖고와서 스플릿 해라 라고 작성해서
요청을 보내보면
파싱을 잘 해온걸 볼 수 있다.
이제 토큰이 없다면 401 에러를 보내고 종료되도록 코드를 추가해주고
이제 이 토큰을 인증하는 코드를 추가해줘야한다.
인증하는 함수는 verifiy()함수로 아래와 같이 사용하면 된다.
2. JWT.verify()
jwt.verify()는 JWT(JSON Web Token)를 검증하고 디코딩하는 함수로 서명이 유효한지 확인하고, 토큰이 만료되었는지 검증한다
발급된 secret 또는 publicKey를 사용하여 서명을 검증해야 한다
2-1. jwt.verify() 함수의 기본 구조
jwt.verify(token, secretOrPublicKey, [options, callback])
매개변수1 : token(필수)
jwt.verify()가 검증할 JWT 문자열로 Base64Url 인코딩된 header.payload.signature 형식의 JWT 토큰으로 토큰이 변조되었거나 만료되었으면 에러를 발생시킨다
매개변수2 : secretOrPublicKey (필수)
JWT가 서명(Signature)된 키를 검증하는 데 사용되고 HS256 (HMAC)의 경우는 비밀키를 사용하고
const secret = "mySecretKey"; // HMAC-SHA256 방식의 서명 검증
jwt.verify(token, secret);
RS256 (RSA)는 공개키를 사용한다.
const fs = require('fs');
const publicKey = fs.readFileSync('public.key'); // 공개 키 사용
jwt.verify(token, publicKey, { algorithms: ['RS256'] });
매개변수3 : options (선택)
JWT 검증 시 추가적인 보안 검사를 수행하는 옵션으로 algorithms, issuer, audience, ignoreExpiration 등 설정 가능하다.
옵션명 | 기본값 | 설명 |
algorithms | HS256 | 허용할 알고리즘 리스트 (예: ['HS256', 'RS256']) |
issuer (iss) | 없음 | 토큰 발급자(issuer) 검증 |
audience (aud) | 없음 | 토큰 대상(audience) 검증 |
ignoreExpiration | false | 만료 시간(exp)을 무시하고 검증 |
maxAge | 없음 | 토큰 최대 사용 가능 시간 (예: '1h') |
subject (sub) | 없음 | 토큰 주제(subject) 검증 |
사용하는 방식은
jwt.verify(token, secret, {
algorithms: ['HS256'], // 허용할 알고리즘 지정
issuer: "MyCompany", // 발급자(iss) 검증
audience: "https://example.com", // 대상(aud) 검증
ignoreExpiration: false // 만료 시간(exp) 검증 활성화
}, (err, decoded) => {
if (err) {
console.error("❌ 검증 실패:", err.message);
} else {
console.log("🔹 검증 성공:", decoded);
}
});
와 같이 사용하면 된다
보안 강화를 위해 algorithms, issuer, audience등의 검증을 추가하는 것이 좋다
매개변수4 : callback (선택)
jwt.verify()는 기본적으로 동기적(Synchronous)이지만 비동기(Asynchronous) 방식으로 실행하려면 callback을 추가해야 한다
콜백함수의 매개변수에는 err와 decoded가 있는데 err는 검증 실패 시 발생하는 에러 객체이고 decoded는 검증 성공 시 반환되는 디코딩된 payload이다.
사용은 아래와 같이 사용한다.
jwt.verify(token, secret, (err, decoded) => {
if (err) {
console.error("검증 실패:", err.message);
} else {
console.log("검증 성공:", decoded);
}
});
*다만, 일반적으로는 동기 방식(try-catch)이 더 많이 사용된다
JWT가 성공적으로 반환되면 값은 payload값으로
{
"userId": 123,
"exp": 1710000000,
"iss": "MyCompany",
"aud": "https://example.com"
}
와 같이 반환된다.
3. JWT 요청 인증
이제 전달 받은 토큰을 verify함수를 사용해서 디코드 해서 가져와보자
먼저 값을 받아줄 변수를 생성하고 jwt의 verify함수를 생성해보자
그리고 첫번째 전달인자로 authToken을 넣어주고
우리가 비밀키로 사용했던 'secret'을 두번쨰 전달인자로 넣어주고
콘솔로 한번 출력시켜보자.
Postman을 사용해서 요청을 보내보면
서버에서 값을 파싱하는 것을 볼 수 있다.
그러면 이제 verify 함수 내부에 콜백을 하나 추가해주고
만약에 에러가 발생했다면 403 에러를 발생시키고
아니라면 값을 전달할건데 이 코드가 실행되는 부분은 미들웨어이고 이 미들웨어에서 발생한 값을 이 미들웨어가 끝나고 실행되는 아래 코드에서 사용해야하기 때문에 값을 전달해줘야만 한다.
미들웨어에서 다음 미들웨어로 값을 전달하는 방법은 req의 값에 담아주면 다음 미들웨어에서 받는 req에도 이 값이 그대로 담겨 있게 된다.
이렇게 넣어주고 다음 미들웨어로 넘겨주기 위해서 next() 함수를 호출해주자.
이러고 요청을 postman으로 보내보면
여태 안보내지던 응답이 돌아오게 된다.
요청을 처리하는 곳에서 req.user를 콘솔로 찍어보면
응답이 다음 미들웨어 까지 같이 전달된것을 볼 수 있다.
만약 토큰을 지우고 요청을 전달하면
이렇게 인증되지 못함을 전달한다.