사용자 인증 후 API와 다른 서비스 간의 상호 작용도 필요할 수 있습니다. 사용자는 클라이언트 애플리케이션에서 보내는 웹 로그인 프롬프트를 통해 사용자 인증 정보를 제출할 수 있지만, 서비스 간의 안전한 통신에는 다른 접근 방식이 필요합니다. 이 페이지는 서비스 간 인증 구현을 위한 권장 사항과 샘플 코드를 보여줍니다.
개요
API에 요청을 보내는 서비스를 식별하려면 서비스 계정을 사용합니다. 호출하는 서비스는 서비스 계정의 비공개 키를 사용하여 보안 JSON 웹 토큰(JWT)에 서명하고, 서명된 JWT를 요청에 포함하여 API에 보냅니다.
API와 호출 서비스 사이의 인증 구현 절차는 다음과 같습니다.
- 호출 서비스에서 사용할 서비스 계정과 키를 만듭니다.
- Cloud Endpoints 서비스에 대한 OpenAPI 문서의 인증 지원을 추가합니다.
호출 서비스에 다음과 같은 코드를 추가합니다.
- JWT를 만들고 이를 서비스 계정의 비공개 키로 서명합니다.
- 서명된 JWT를 API에 대한 요청에 포함하여 전송합니다.
ESP는 요청을 API로 전달하기 전에 JWT의 클레임이 OpenAPI 문서의 구성과 일치하는지 확인합니다. ESP는 서비스 계정에 부여한 Cloud Identity 권한을 확인하지 않습니다.
기본 요건
이 페이지에서는 다음 작업을 이미 완료했다고 가정합니다.
키가 있는 서비스 계정 만들기
호출 서비스의 JWT 서명을 위한 비공개 키 파일을 보유한 서비스 계정이 필요합니다. API에 요청을 보내는 서비스가 두 개 이상이면 이 호출 서비스를 모두 포함하는 하나의 서비스 계정을 만들 수 있습니다. 서비스를 구분해야 하는 경우(예를 들어 서비스마다 사용 권한이 다른 경우) 호출 서비스별로 서비스 계정과 키를 만들 수 있습니다.
이 섹션에서는 Google Cloud 콘솔 및 gcloud
명령줄 도구를 사용하여 서비스 계정 및 비공개 키 파일을 만들고 서비스 계정을 서비스 계정 토큰 작성기 역할에 할당하는 방법을 보여줍니다. API를 사용하여 이 작업을 수행하는 방법에 대한 자세한 내용은 서비스 계정 만들기 및 관리를 참조하세요.
서비스 계정 및 키를 만들려면 다음 안내를 따르세요.
Google Cloud Console
서비스 계정을 만듭니다.
Google Cloud Console에서 서비스 계정 만들기 페이지로 이동합니다.
사용할 프로젝트를 선택합니다.
서비스 계정 이름 필드에 이름을 입력합니다.
선택사항: 서비스 계정 설명 필드에 설명을 입력합니다.
만들기를 클릭합니다.
역할 선택 필드를 클릭합니다. 모든 역할에서 서비스 계정 > 서비스 계정 토큰 생성자를 선택합니다.
완료를 클릭합니다.
브라우저 창을 닫지 마세요. 다음 단계에서 사용합니다.
서비스 계정 키 만들기
- Google Cloud Console에서 만든 서비스 계정의 이메일 주소를 클릭합니다.
- 키를 클릭합니다.
- 키 추가를 클릭한 후 새 키 만들기를 클릭합니다.
- 만들기를 클릭합니다. 서비스 계정의 비공개 키를 포함하는 JSON 파일이 컴퓨터에 다운로드됩니다.
- 닫기를 클릭합니다.
gcloud
로컬 머신이나 Cloud Shell 내에서 Google Cloud CLI를 사용하여 다음 명령어를 실행할 수 있습니다.
gcloud
에 기본 계정을 설정합니다. 계정이 2개 이상이면 사용하려는 Google Cloud 프로젝트에 있는 계정을 선택해야 합니다.gcloud auth login
Google Cloud 프로젝트의 프로젝트 ID를 표시합니다.
gcloud projects list
기본 프로젝트를 설정합니다.
PROJECT_ID
를 사용하려는 Google Cloud 프로젝트 ID로 바꿉니다.gcloud config set project PROJECT_ID
서비스 계정 만들기
SA_NAME
과SA_DISPLAY_NAME
을 사용하려는 이름과 표시 이름으로 바꿉니다.gcloud iam service-accounts create SA_NAME \ --display-name "SA_DISPLAY_NAME"
방금 만든 서비스 계정의 이메일 주소를 표시합니다.
gcloud iam service-accounts list
서비스 계정 토큰 생성자 역할을 추가합니다.
SA_EMAIL_ADDRESS
를 서비스 계정의 이메일 주소로 바꿉니다.gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:SA_EMAIL_ADDRESS \ --role roles/iam.serviceAccountTokenCreator
현재 작업 디렉터리에 서비스 계정 키 파일을 만듭니다.
FILE_NAME
을 키 파일에 사용할 이름으로 바꿉니다.gcloud
명령어가 JSON 파일을 생성하는 것이 기본 설정입니다.gcloud iam service-accounts keys create FILE_NAME.json \ --iam-account SA_EMAIL_ADDRESS
앞에 나온 명령어에 대한 자세한 내용은 gcloud
참조 문서를 확인하세요.
비공개 키 보호에 대한 자세한 내용은 사용자 인증 정보 관리 권장사항을 참조하세요.
인증을 지원하도록 API 구성
ESP가 서명된 JWT의 클레임을 확인하려면 OpenAPI 문서에 보안 요구사항 객체와 보안 정의 객체가 있어야 합니다.
OpenAPI 문서에 서비스 계정을 발급기관으로 추가합니다.
securityDefinitions: DEFINITION_NAME: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "SA_EMAIL_ADDRESS" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS"
DEFINITION_NAME
을 이 보안 정의를 식별하는 문자열로 바꿉니다. 서비스 계정 이름 또는 호출 서비스를 식별하는 이름으로 바꿀 수 있습니다.SA_EMAIL_ADDRESS
를 서비스 계정의 이메일 주소로 바꿉니다.- OpenAPI 문서가 여러 개의 보안 정의를 포함할 수는 있지만 각 정의의
x-google-issuer
는 서로 달라야 합니다. 호출 서비스마다 별도의 서비스 계정을 만들었으면 서비스 계정마다 보안 정의를 만들 수 있습니다. 예를 들면 다음과 같습니다.
securityDefinitions: service-1: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-1@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com" service-2: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-2@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
선택사항으로
x-google-audiences
를securityDefinitions
섹션에 추가합니다.x-google-audiences
를 추가하지 않으면 ESP에는https://SERVICE_NAME
형식으로 된 JWT의"aud"
(잠재고객) 클레임이 필요합니다. 여기에서 SERVICE_NAME은 플래그--disable_jwt_audience_service_name_check
가 사용되지 않은 한 OpenAPI 문서의host
필드에 구성한 Endpoints 서비스의 이름입니다. 플래그가 사용되고x-google-audiences
가 지정되지 않으면 JWTaud
필드가 확인되지 않습니다.선택사항으로
x-google-jwt-locations
를securityDefinitions
섹션에 추가합니다. 이 값을 사용하여 커스텀 JWT 위치를 정의할 수 있습니다. 기본 JWT 위치는Authorization
헤더('Bearer'가 앞에 나옴),X-Goog-Iap-Jwt-Assertion
헤더 또는access_token
쿼리 매개변수입니다. 참고:x-google-jwt-locations
를 지정하면 Endpoints는 모든 기본 위치를 무시합니다.x-google-jwt-locations
는 ESPv2에서만 지원됩니다.
security
섹션을 파일의 최상위 수준(들여쓰거나 중첩하지 않음)에서 추가하여 전체 API에 적용하거나 메서드 수준에서 추가하여 특정 메서드에 적용합니다. API 및 메서드 수준 모두에security
섹션을 사용하는 경우에는 메서드 수준 설정이 API 수준 설정보다 우선 적용됩니다.security: - DEFINITION_NAME: []
DEFINITION_NAME
을securityDefinitions
섹션에 사용한 이름으로 바꿉니다.securityDefinitions
섹션에 정의가 둘 이상 있는 경우security
섹션에 이를 추가합니다. 예를 들면 다음과 같습니다.security: - service-1: [] - service-2: []
업데이트된 OpenAPI 문서를 배포합니다.
OPENAPI_DOC
를 OpenAPI 문서의 이름으로 바꿉니다.gcloud endpoints services deploy OPENAPI_DOC
ESP는 요청을 API에 전달하기 전에 다음을 확인합니다.
- 공개 키를 사용한 JWT의 서명이 OpenAPI 문서의
x-google-jwks_uri
필드에 지정된 URI에 있는지 확인합니다. - JWT의
"iss"
(발급기관) 클레임이x-google-issuer
필드에 지정된 값과 일치하는지 확인합니다. - JWT의
"aud"
(대상) 클레임이 Endpoints 서비스 이름에 포함되었는지,x-google-audiences
필드에서 지정한 값 중 하나와 일치하는지 확인합니다. "exp"
(만료 시간) 클레임을 사용하여 토큰이 만료되었는지 확인합니다.
x-google-issuer
, x-google-jwks_uri
, x-google-audiences
, x-google-jwt-locations
에 대한 자세한 내용은 OpenAPI 확장 프로그램을 참조하세요.
Endpoints API에 인증된 요청 실행
인증된 요청을 위해서는 OpenAPI 문서 상 지정된 서비스 계정이 서명한 JWT를 호출 서비스에서 보내야 합니다. 호출 서비스는 다음을 수행해야 합니다.
- JWT를 만들고 이를 서비스 계정의 비공개 키로 서명합니다.
- 서명된 JWT를 API에 대한 요청에 포함하여 전송합니다.
다음 샘플 코드는 특정 언어에 대한 이 프로세스를 보여줍니다. 다른 언어로 인증된 요청을 수행하려면 jwt.io를 참조하여 지원되는 라이브러리 목록을 확인하세요.
-
호출 서비스에서 다음 함수를 추가하고 이를 다음 매개변수에 전달합니다.
자바 saKeyfile
: 서비스 계정의 비공개 키 파일에 대한 전체 경로입니다.saEmail
: 서비스 계정의 이메일 주소입니다.-
audience
:x-google-audiences
필드를 OpenAPI 문서에 추가한 경우audience
를x-google-audiences
에 지정한 값 중 하나로 설정합니다. 그 이외에는audience
를https://SERVICE_NAME
으로 설정합니다. 여기에서SERVICE_NAME
은 Endpoints 서비스 이름입니다. expiryLength
: JWT 만료 시간(초)입니다.
Python -
sa_keyfile
: 서비스 계정의 비공개 키 파일에 대한 전체 경로입니다. -
sa_email
: 서비스 계정의 이메일 주소입니다. -
audience
:x-google-audiences
필드를 OpenAPI 문서에 추가한 경우audience
를x-google-audiences
에 지정한 값 중 하나로 설정합니다. 그 이외에는audience
를https://SERVICE_NAME
으로 설정합니다. 여기에서SERVICE_NAME
은 Endpoints 서비스 이름입니다. expiry_length
: JWT 만료 시간(초)입니다.
Go saKeyfile
: 서비스 계정의 비공개 키 파일에 대한 전체 경로입니다.-
saEmail
: 서비스 계정의 이메일 주소입니다. -
audience
:x-google-audiences
필드를 OpenAPI 문서에 추가한 경우audience
를x-google-audiences
에 지정한 값 중 하나로 설정합니다. 그 이외에는audience
를https://SERVICE_NAME
으로 설정합니다. 여기에서SERVICE_NAME
은 Endpoints 서비스 이름입니다. expiryLength
: JWT 만료 시간(초)입니다.
이 함수는 JWT를 만들고 비공개 키 파일을 사용하여 이에 서명한 다음, 서명된 JWT를 반환합니다.
자바 Python Go - 호출 서비스에서 다음 함수를 추가해서 API에 대한 요청의
Authorization: Bearer
헤더에 서명된 JWT를 보냅니다.자바 Python Go
JWT를 사용하여 요청을 보낼 때는 보안상의 이유로 Authorization: Bearer
헤더에 인증 토큰을 포함하는 것이 좋습니다. 예를 들면 다음과 같습니다.
curl --request POST \ --header "Authorization: Bearer ${TOKEN}" \ "${ENDPOINTS_HOST}/echo"
여기서 ENDPOINTS_HOST
와 TOKEN
은 각각 API 호스트 이름과 인증 토큰을 포함하는 환경 변수입니다.
API에서 인증 결과 수신
ESP는 수신하는 모든 헤더를 전달합니다. 하지만 OpenAPI 사양의 x-google-backend
또는 gRPC 서비스 구성의 BackendRule
에서 백엔드 주소를 지정할 때 ESP는 원래 Authorization
헤더를 재정의합니다.
ESP는 X-Endpoint-API-UserInfo
의 인증 결과를 백엔드 API에 전송합니다. 원래 Authorization
헤더 대신 이 헤더를 사용하는 것이 좋습니다. 이 헤더는 base64url
이 JSON 객체를 인코딩하는 문자열입니다. JSON 객체 형식은 ESPv2와 ESP 간에 다릅니다.
ESPv2의 경우 JSON 객체는 정확히 원래 JWT 페이로드입니다. ESP의 경우 JSON 객체는 서로 다른 필드 이름을 사용하고 원래 JWT 페이로드를 claims
필드에 넣습니다.
형식에 대한 자세한 내용은 백엔드 서비스에서 JWT 처리를 참조하세요.