Node.js에서 Google 서비스 계정 JWT 구현하기

대부분의 개발자는 Google API를 호출하기 위해 googleapis npm 패키지를 사용합니다. 잘 작동하지만, 프로젝트에 380KB의 용량과 450개 이상의 의존성(dependencies)을 추가하게 됩니다.

간단한 CI 스크립트를 위해 API 하나만 필요하다면, 이는 과한 설정(overkill)입니다.

저는 단 세 가지의 Node.js 내장 모듈인 crypto, fetch, URL만을 사용하여 URL 인덱스 상태를 확인하는 스크립트를 만들었습니다. 외부 패키지는 전혀 사용하지 않습니다.

인증은 RFC 7523을 따릅니다. 방법은 다음과 같습니다:

  • 서비스 계정 이메일과 개인 키(private key)를 사용하여 JWT를 생성합니다.
  • 해당 JWT를 Google 토큰 엔드포인트로 POST 요청합니다.
  • 수명이 짧은 액세스 토큰(access token)을 받습니다.
  • 해당 토큰을 API 요청의 Bearer 헤더로 사용합니다.

JWT에는 다음과 같은 클레임(claims)이 필요합니다:

  • iss: 클라이언트 이메일.
  • scope: webmasters.readonly.
  • aud: Google 토큰 URL.
  • iat: 현재 시간.
  • exp: 현재 시간 + 3600초.

참고: webmasters 스코프를 사용하세요. 최신 버전인 searchconsole 스코프는 URL 검사(URL Inspection) API에서 작동하지 않습니다.

까다로운 부분은 Base64url 인코딩입니다. 호환성을 위해 패딩(padding)을 제거하고 문자를 교체해야 합니다. node:crypto 모듈을 사용하여 RSA 개인 키로 JWT에 서명할 수 있습니다. Google Cloud JSON 파일에 있는 키를 그대로 사용할 수 있습니다.

토큰을 교환할 때 원본 에러 응답(raw error response)을 로그로 남기세요. Google은 "Service account not found"와 같이 구체적인 메시지를 제공하므로 에러를 빠르게 수정하는 데 도움이 됩니다.

이 방식은 다음과 같은 경우에 가장 적합합니다:

  • CI 파이프라인에서 단일 API를 사용하는 경우.
  • 저장소(repo)를 가볍게 유지하고 싶은 경우.
  • 인증 흐름을 이해하고 싶은 경우.

다음과 같은 경우에는 사용하지 마세요:

  • 다양한 Google API를 호출해야 하는 경우.
  • 자동 토큰 갱신(refreshing)이 필요한 경우.
  • 대규모 프로덕션 서버를 구축하는 경우.

좁은 범위의 작업을 수행할 때는 수백 개의 숨겨진 의존성보다 작고 읽기 쉬운 코드가 더 낫습니다.

출처: https://dev.to/morinaga/rolling-a-google-service-account-jwt-in-nodejs-without-the-googleapis-package-22am