Postman Pre-request Script에서 JWT 토큰 생성하기

사람·2025년 2월 5일

Backend

목록 보기
2/11
post-thumbnail

현재 스코어는 회원가입 및 온보딩 페이지 외에는 모두 소셜 로그인 인증 완료 후 발급되는 JWT 토큰이 Authorization 헤더에 있어야만 접속할 수 있게 구현되어 있다.
OncePerRequestFilter를 상속받아 커스텀 Authentication Filter를 구현해서 매 요청이 발생할 때마다 헤더에 있는 JWT 토큰을 검증하도록 했기 때문이다.
그래서 기능을 테스트하기 위해 요청을 보내려면 일단 소셜 로그인을 완료한 후 JWT 토큰을 발급받아야 했는데, 지금 구현하고 있는 서비스가 네이티브 앱 서비스라 그런지 테스트 환경인 PC상에서는 소셜 로그인이 제대로 되지가 않았다. JWT 토큰 값만 있으면 테스트를 할 수 있는데, 굳이 소셜 로그인까지 해서 이걸 발급받아야 할까? JWT 토큰을 임의로 생성할 수 있는 방법이 없을까?
하는 생각에 찾아봤는데, Postman의 Pre-request Script에 JWT 토큰을 생성하는 로직을 작성하면 테스트 요청을 보낼 때마다 JWT 토큰을 자동으로 생성할 수 있었다.


일단 Postman에 테스트하고자 하는 request를 생성한다. 나는 회원 탈퇴 API를 가져와봤다.

현재 DB에는 user_id가 1인 유저 정보가 하나 저장되어 있는 상태이다. 이 유저 정보를 삭제하는 요청이다.

현재 상태에서 요청을 보내면 403 Forbidden이 뜬다. 헤더에 JWT 토큰이 없어 인증되지 않은 사용자로 간주하고 요청을 수행하지 않는 것이다.
테스트를 수행하려면 유효한 JWT가 필요하다...!!


JWT 토큰을 생성하려면 우선 JWT 토큰의 구조를 알아야 할 것이다.
JWT 토큰은 '.'를 구분자로 하는 세 문자열로 이루어져 있다.
순서대로 Header, Payload, Signature를 의미한다.

각 부분은 JSON 형태이며, Base64인코딩이 되어 있다.
각 부분에 들어가는 내용들에 대해서는 제가 과거에 작성한 글과 공식 사이트의 introduction을 참고하시길....

즉, 작성할 Pre-request Script도 Header, Payload, Signature를 각각 Base64 인코딩하고, 이를 '.'로 구분자로 해 합쳐 놓은 형태로 생성하는 기능을 수행해야 함을 알 수 있다.

그렇다면 테스트를 위해 Pre-request Script를 작성해보자.

테스트할 요청에서 Scripts 탭에 들어간 후 Pre-request에 작성하면 된다.
Postman의 Pre-request Script는 javascript로 작성해야 한다. Postman은 Node.js 기반 패키지 중에서 crypto-js라는 걸 지원하는데, 이걸 사용하면 JWT 토큰 생성을 위해 필요한 Base64 인코딩 및 디코딩, 그리고 각종 암호화를 할 수 있다고 한다.
Postman에서 사용 가능한 crypto-js 여러 기능들은 여기에서 확인할 수 있다.

crypto-js를 사용해 Pre-request Script를 다음과 같이 작성할 수 있었다.

// secretkey Base64 인코딩
// secretkey를 Base64 인코딩하지 않고 사용하도록 구현한 경우 삭제
function base64Encode(str) {
    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str))
        .replace(/=+$/, '')  // 패딩 제거
        .replace(/\+/g, '-') // '+'를 '-'로 변경
        .replace(/\//g, '_'); // '/'를 '_'로 변경
}

// JWT 생성
function createJwtToken(secret, payload) {
    var header = {
        alg: "HS256",
        typ: "JWT"
    };

    function base64url(source) {
        var encoded = CryptoJS.enc.Base64.stringify(source);
        encoded = encoded.replace(/=+$/, ''); // 패딩 제거
        encoded = encoded.replace(/\+/g, '-'); // '+'를 '-'로 변경
        encoded = encoded.replace(/\//g, '_'); // '/'를 '_'로 변경
        return encoded;
    }

  	// 헤더를 Base64 인코딩
    var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
    var encodedHeader = base64url(stringifiedHeader);
	
  	// payload를 Base64 인코딩
    var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(payload));
    var encodedData = base64url(stringifiedData);
	
  	// 헤더와 페이로드를 .을 구분자로 해 합치기
    var token = encodedHeader + "." + encodedData;
    
  	// secretkey를 Base64 인코딩
  	// secretkey를 Base64 인코딩하지 않고 사용하도록 구현한 경우 삭제
    var encodedSecretKey = base64Encode(secret);
    
  	// signature를 Base64 인코딩
  	// (헤더).(페이로드) 형태로 만들어진 토큰을 secretkey로 암호화 -> 다시 Base 64 인코딩
    var signature = CryptoJS.HmacSHA256(token, encodedSecretKey);
    var encodedSignature = base64url(signature);
	
  	// (헤더).(페이로드)와 Signature를 .을 구분자로 해 합치기
    return token + "." + encodedSignature;
}

// JWT 생성
var secretKey = "(application.yml에 선언해 둔 secretkey 값)";
var payload = {
    sub: "testUserKey",  // 사용자 ID (테스트용)
    iat: Math.floor(Date.now() / 1000), // 발급 시간
    exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1시간 후 만료
};

var jwtToken = createJwtToken(secretKey, payload);

// 생성한 JWT를 Postman 전역 변수로 저장
pm.globals.set("jwtToken", jwtToken);

위 script를 Postman에 아래와 같이 붙여 넣어 준다.

// 생성한 JWT를 Postman 전역 변수로 저장
pm.globals.set("jwtToken", jwtToken);

생성한 JWT를 jwtToken라는 변수에 저장했기 때문에, 이제 이 변수 값을 활용하면 된다.


Header 탭에 들어가서 Authorization 헤더를 추가하고, Bearer {{jwtToken}}을 입력하면 이렇게 생성된 jwt가 헤더에 추가될 것이다.


이렇게 한 후 다시 요청을 보내면 이번에는 200이 뜨며 성공하는 것을 볼 수 있다!

DB를 확인해 보면 회원이 정상적으로 삭제되어 테이블이 비어 있음을 확인할 수 있다.

이렇게 하니 테스트를 할 때마다 토큰을 수동으로 생성할 필요가 없어 아주 편해졌다....!

profile
알고리즘 블로그 아닙니다.

0개의 댓글