

# API Gateway에서 HTTP API에 대한 액세스 제어 및 관리
<a name="http-api-access-control"></a>

API Gateway는 HTTP API 액세스 제어 및 관리에 다중 메커니즘을 지원합니다.
+ **Lambda 권한 부여자**는 Lambda 함수를 사용하여 API에 대한 액세스를 제어합니다. 자세한 내용은 [AWS Lambda 권한 부여자를 사용하여 HTTP API에 대한 액세스 제어](http-api-lambda-authorizer.md) 단원을 참조하세요.
+ **JWT 권한 부여자**는 JSON 웹 토큰을 사용하여 API에 대한 액세스를 제어합니다. 자세한 내용은 [API Gateway에서 JWT 권한 부여자를 사용하여 HTTP API에 대한 액세스 제어](http-api-jwt-authorizer.md) 단원을 참조하세요.
+ **표준 AWS IAM 역할 및 정책**은 유연하고 강력한 액세스 제어를 제공합니다. IAM 역할 및 정책을 사용하여 API를 생성하고 관리할 수 있는 사용자와 API를 호출할 수 있는 사용자를 제어할 수 있습니다. 자세한 내용은 [API Gateway에서 IAM 권한 부여를 통해 HTTP API에 대한 액세스 제어](http-api-access-control-iam.md) 섹션을 참조하세요.

보안 태세를 개선하려면 HTTP API의 모든 라우팅에 대해 권한 부여자를 구성하는 것이 좋습니다. 다양한 규정 준수 프레임워크를 준수하기 위해 이 작업을 수행해야 할 수 있습니다. 자세한 내용은 *AWS Security Hub 사용 설명서*에서 [Amazon API Gateway 제어](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)를 참조하세요.

# AWS Lambda 권한 부여자를 사용하여 HTTP API에 대한 액세스 제어
<a name="http-api-lambda-authorizer"></a>

Lambda 권한 부여자를 사용하여 HTTP API에 대한 액세스를 제어하는 Lambda 함수를 사용합니다. 그런 다음 클라이언트가 API를 호출하면 API Gateway에서 Lambda 함수를 호출합니다. API Gateway는 Lambda 함수의 응답을 사용하여 클라이언트가 API에 액세스할 수 있는지 여부를 결정합니다.

## 페이로드 형식 버전
<a name="http-api-lambda-authorizer.payload-format"></a>

권한 부여자 페이로드 형식 버전은 API Gateway에서 Lambda 권한 부여자로 전송하는 데이터의 형식과 API Gateway에서 Lambda의 응답을 해석하는 방법을 지정합니다. 페이로드 형식 버전을 지정하지 않으면 AWS Management Console에서는 기본적으로 최신 버전을 사용합니다. AWS CLI, CloudFormation 또는 SDK를 사용하여 Lambda 권한 부여자를 생성하는 경우 `authorizerPayloadFormatVersion`을 지정해야 합니다. 지원되는 값은 `1.0` 및 `2.0`입니다.

 REST API와의 호환성이 필요한 경우 `1.0` 버전을 사용합니다.

다음 예제에서는 각 페이로드 형식 버전의 구조를 보여 줍니다.

------
#### [ 2.0 ]

```
{
  "version": "2.0",
  "type": "REQUEST",
  "routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": ["user1", "123"],
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": ["cookie1", "cookie2"],
  "headers": {
    "header1": "value1",
    "header2": "value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "IP",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "pathParameters": { "parameter1": "value1" },
  "stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}
```

------
#### [ 1.0 ]

```
{
  "version": "1.0",
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": "user1,123",
  "authorizationToken": "user1,123",
  "resource": "/request",
  "path": "/request",
  "httpMethod": "GET",
  "headers": {
    "X-AMZ-Date": "20170718T062915Z",
    "Accept": "*/*",
    "HeaderAuth1": "headerValue1",
    "CloudFront-Viewer-Country": "US",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Is-Mobile-Viewer": "false",
    "User-Agent": "..."
  },
  "queryStringParameters": {
    "QueryString1": "queryValue1"
  },
  "pathParameters": {},
  "stageVariables": {
    "StageVar1": "stageValue1"
  },
  "requestContext": {
    "path": "/request",
    "accountId": "123456789012",
    "resourceId": "05c7jb",
    "stage": "test",
    "requestId": "...",
    "identity": {
      "apiKey": "...",
      "sourceIp": "...",
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "resourcePath": "/request",
    "httpMethod": "GET",
    "apiId": "abcdef123"
  }
}
```

------

## Lambda 권한 부여자 응답 형식
<a name="http-api-lambda-authorizer.payload-format-response"></a>

페이로드 형식 버전은 Lambda 함수에서 반환되어야 하는 응답 구조도 결정합니다.

### 형식 1.0에 대한 Lambda 함수 응답
<a name="http-api-lambda-authorizer.v1"></a>

`1.0` 형식 버전을 선택하는 경우 Lambda 권한 부여자는 API 라우팅에 대한 액세스를 허용하거나 거부하는 IAM 정책을 반환해야 합니다. 정책에서 표준 IAM 정책 구문을 사용할 수 있습니다. IAM 정책에 대한 예시는 [API 호출을 위한 액세스 제어](api-gateway-control-access-using-iam-policies-to-invoke-api.md) 단원을 참조하세요. `$context.authorizer.property`를 사용하여 컨텍스트 속성을 Lambda 통합 또는 액세스 로그에 전달할 수 있습니다. `context` 객체는 선택 사항이며 `claims`는 예약된 자리 표시자이므로 컨텍스트 객체로 사용할 수 없습니다. 자세한 내용은 [HTTP API 액세스 로그 사용자 정의](http-api-logging-variables.md)를 참조하세요.

**Example**    
****  

```
{
  "principalId": "abcdef", 
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "exampleKey": "exampleValue"
  }
}
```

### 형식 2.0에 대한 Lambda 함수 응답
<a name="http-api-lambda-authorizer.v2"></a>

`2.0` 형식 버전을 선택하는 경우 Lambda 함수에서 부울 값 또는 표준 IAM 정책 구문을 사용하는 IAM 정책을 반환할 수 있습니다. 부울 값을 반환하려면 권한 부여자에 대한 간단한 응답을 활성화합니다. 다음 예제에서는 Lambda 함수에서 반환하도록 코딩해야 하는 형식을 보여줍니다. `context` 객체는 선택 사항입니다. `$context.authorizer.property`를 사용하여 컨텍스트 속성을 Lambda 통합 또는 액세스 로그에 전달할 수 있습니다. 자세한 내용은 [HTTP API 액세스 로그 사용자 정의](http-api-logging-variables.md) 단원을 참조하세요.

------
#### [ Simple response ]

```
{
  "isAuthorized": true/false,
  "context": {
    "exampleKey": "exampleValue"
  }
}
```

------
#### [ IAM policy ]

****  

```
{
  "principalId": "abcdef", 
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "exampleKey": "exampleValue"
  }
}
```

------

## Lambda 권한 부여자 함수의 예
<a name="http-api-lambda-authorizer.example-code"></a>

다음 예제 Node.js Lamdba 함수는 `2.0` 페이로드 형식 버전의 경우 Lambda 함수에서 반환해야 하는 응답 형식을 보여줍니다.

------
#### [ Simple response - Node.js ]

```
export const handler = async(event) => {
    let response = {
        "isAuthorized": false,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": true,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    };
    
    if (event.headers.authorization === "secretToken") {
        console.log("allowed");
        response = {
            "isAuthorized": true,
            "context": {
                "stringKey": "value",
                "numberKey": 1,
                "booleanKey": true,
                "arrayKey": ["value1", "value2"],
                "mapKey": {"value1": "value2"}
            }
        };
    }

    return response;

};
```

------
#### [ Simple response - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        "isAuthorized": False,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                "isAuthorized": True,
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------
#### [ IAM policy - Node.js ]

```
export const handler = async(event) => {
  if (event.headers.authorization == "secretToken") {
    console.log("allowed");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Allow",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
  else {
    console.log("denied");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Deny",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
};
```

------
#### [ IAM policy - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        # The principal user identification associated with the token sent by
        # the client.
        "principalId": "abcdef",
        "policyDocument": {
            "Version": "2012-10-17",		 	 	 
            "Statement": [{
                "Action": "execute-api:Invoke",
                "Effect": "Deny",
                "Resource": event["routeArn"]
            }]
        },
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                # The principal user identification associated with the token
                # sent by the client.
                "principalId": "abcdef",
                "policyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [{
                        "Action": "execute-api:Invoke",
                        "Effect": "Allow",
                        "Resource": event["routeArn"]
                    }]
                },
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------

## 자격 증명 원본
<a name="http-api-lambda-authorizer.identity-sources"></a>

선택적으로 Lambda 권한 부여자에 대한 자격 증명 원본을 지정할 수 있습니다. 자격 증명 원본은 요청에 권한을 부여하는 데 필요한 데이터의 위치를 지정합니다. 예를 들어 헤더 또는 쿼리 문자열 값을 자격 증명 원본으로 지정할 수 있습니다. 자격 증명 원본을 지정하는 경우 클라이언트에서 해당 소스를 요청에 포함해야 합니다. 클라이언트의 요청에 자격 증명 원본이 포함되어 있지 않은 경우 API Gateway는 Lambda 권한 부여자를 호출하지 않으며 클라이언트가 `401` 오류를 수신합니다.

다음 표에서는 Lambda 권한 부여자에 대해 지원되는 자격 증명 소스를 설명합니다.


| **Type** | **예제** | **참고** | 
| --- | --- | --- | 
| 헤더 값 | \$1request.header.name | 헤더 이름은 대/소문자를 구분하지 않습니다. | 
| 쿼리 문자열 값 | \$1request.querystring.name | 쿼리 문자열 이름은 대/소문자를 구분합니다. | 
| 컨텍스트 변수 | \$1context.variableName | 지원되는 [컨텍스트 변수](http-api-logging-variables.md)의 값입니다. | 
| 단계 변수 | \$1stageVariables.variableName | [스테이지 변수](http-api-stages.stage-variables.md)의 값입니다. | 

Lambda 함수에서 직접 ` {"errorMessage" : "Unauthorized"}`를 반환하여 클라이언트에 `401` 오류를 반환할 수도 있습니다. Lambda 함수에서 클라이언트로 직접 `401` 오류를 반환하는 경우 Lambda 권한 부여자를 생성할 때 자격 증명 소스를 지정하지 마세요.

## 권한 부여자 응답 캐싱
<a name="http-api-lambda-authorizer.caching"></a>

[authorizerResultTtlInSeconds](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers.html#apis-apiid-authorizers-prop-createauthorizerinput-authorizerresultttlinseconds)를 지정하여 Lambda 권한 부여자에 대한 캐싱을 활성화할 수 있습니다. 권한 부여자에 대해 캐싱이 활성화되면 API Gateway에서 권한 부여자의 자격 증명 원본을 캐시 키로 사용합니다. 클라이언트가 구성된 TTL 내의 자격 증명 원본에서 동일한 파라미터를 지정하는 경우 API Gateway에서 Lambda 함수를 호출하는 대신 캐싱된 권한 부여자 결과를 사용합니다.

캐싱을 활성화하려면 권한 부여자에게 자격 증명 원본이 하나 이상 있어야 합니다.

권한 부여자에 대해 간단한 응답을 활성화하면 권한 부여자의 응답이 캐싱된 자격 증명 원본 값과 일치하는 모든 API 요청을 완전히 허용하거나 거부합니다. 보다 세분화된 권한이 필요한 경우 간단한 응답을 비활성화하고 IAM 정책을 반환합니다. 권한 부여자에 따라 IAM 정책이 여러 리소스에 대한 액세스를 제어해야 할 수 있습니다.

기본적으로 API Gateway에서는 권한 부여자를 사용하는 API의 모든 라우팅에 캐싱된 권한 부여자 응답을 사용합니다. 라우팅별로 응답을 캐싱하려면 권한 부여자의 자격 증명 원본에 `$context.routeKey`를 추가합니다.

## Lambda 권한 부여자 만들기
<a name="http-api-lambda-authorizer.example-create"></a>

Lambda 권한 부여자를 만들 때 API Gateway에 사용할 Lambda 함수를 지정합니다. 함수의 리소스 정책 또는 IAM 역할을 사용하여 Lambda 함수를 호출할 수 있는 권한을 API Gateway에 부여해야 합니다. 다음 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) 명령은 Lambda 권한 부여자를 생성합니다.

```
aws apigatewayv2 create-authorizer \
    --api-id abcdef123 \
    --authorizer-type REQUEST \
    --identity-source '$request.header.Authorization' \
    --name lambda-authorizer \ 
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:my-function/invocations' \
    --authorizer-payload-format-version '2.0' \
    --enable-simple-responses
```

다음 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 명령은 Lambda 함수의 리소스 정책을 업데이트하여 API Gateway에 함수를 호출할 수 있는 권한을 부여합니다. API Gateway에 함수를 호출할 수 있는 권한이 없으면 클라이언트가 `500 Internal Server Error`를 수신합니다.

```
aws lambda add-permission \
    --function-name my-authorizer-function \
    --statement-id apigateway-invoke-permissions-abc123 \ 
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/authorizers/authorizer-id"
```

권한 부여자를 생성하고 이를 호출할 수 있는 권한을 API Gateway에 부여한 후에는 권한 부여자를 사용하도록 라우팅을 업데이트합니다. 다음 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 명령은 Lambda 권한 부여자를 경로에 추가합니다. Lambda 권한 부여자가 정책 캐싱을 사용하는 경우 정책을 업데이트하여 추가 경로에 대한 액세스를 제어해야 합니다.

```
aws apigatewayv2 update-route \
    --api-id abcdef123 \
    --route-id abc123 \
    --authorization-type CUSTOM \
    --authorizer-id def123
```

## Lambda 권한 부여자 문제 해결
<a name="http-api-lambda-authorizer.troubleshooting"></a>

API Gateway에서 Lambda 권한 부여자를 호출할 수 없거나 Lambda 권한 부여자가 잘못된 형식으로 응답을 반환하는 경우 클라이언트가 `500 Internal Server Error`를 수신합니다.

오류를 해결하려면 API 스테이지에 대한 [액세스 로깅을 활성화](http-api-logging.md)합니다. 로그 형식에 `$context.authorizer.error` 로깅 변수를 포함합니다.

로그에 API Gateway가 함수를 호출할 권한이 없다고 표시되면 함수의 리소스 정책을 업데이트하거나 권한 부여자를 호출할 수 있는 권한을 API Gateway에 부여하는 IAM 역할을 제공합니다.

로그에 Lambda 함수가 잘못된 응답을 반환한다고 표시되면 Lambda 함수가 [필요한 형식](#http-api-lambda-authorizer.payload-format-response)으로 응답을 반환하는지 확인합니다.

# API Gateway에서 JWT 권한 부여자를 사용하여 HTTP API에 대한 액세스 제어
<a name="http-api-jwt-authorizer"></a>

JWT(JSON Web Token)를 [OIDC(OpenID Connect)](https://openid.net/specs/openid-connect-core-1_0.html) 및 [OAuth 2.0](https://oauth.net/2/) 프레임워크의 일부로 사용하여 API에 대한 클라이언트 액세스를 제한할 수 있습니다.

API의 경로에 대해 JWT 권한 부여자를 구성하면 API Gateway는 클라이언트가 API 요청과 함께 제출하는 JWT를 검증합니다. API Gateway는 토큰 검증 및 선택적으로 토큰의 범위를 기반으로 요청을 허용하거나 거부합니다. 경로의 범위를 구성하는 경우 토큰에 경로의 범위 중 하나 이상이 포함되어야 합니다.

API의 각 경로에 대해 고유한 권한 부여자를 구성하거나, 여러 경로에 대해 동일한 권한 부여자를 사용할 수 있습니다.

**참고**  
OpenID Connect ID 토큰과 같은 기타 유형의 JWT와 JWT 액세스 토큰을 구별하는 표준 메커니즘은 없습니다. API 인증에 ID 토큰이 필요하지 않은 경우 인증 범위가 필요하도록 경로를 구성하는 것이 좋습니다. 자격 증명 공급자가 JWT 액세스 토큰을 발급할 때만 사용하는 발급자 또는 대상 그룹이 필요하도록 JWT 권한 부여자를 구성할 수도 있습니다.

## JWT 권한 부여자를 통한 API 요청 승인
<a name="http-api-jwt-authorizer.evaluation"></a>

API Gateway는 다음과 같은 일반 워크플로우를 사용하여 JWT 권한 부여자를 사용하도록 구성된 라우팅에 대한 요청을 승인합니다.

1. 토큰에 대한 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource)를 확인합니다. `identitySource`에는 토큰만 포함하거나 `Bearer` 접두사가 붙은 토큰만 포함될 수 있습니다.

1. 토큰을 디코딩합니다.

1. 발행자의 `jwks_uri`에서 가져온 퍼블릭 키를 사용하여 토큰의 알고리즘과 서명을 확인합니다. 현재 RSA 기반 알고리즘만 지원됩니다. API Gateway는 퍼블릭 키를 2시간 동안 캐시할 수 있습니다. 가장 좋은 방법은 키를 교체할 때 이전 키와 새 키가 모두 유효한 유예 기간을 두는 것입니다.

1. 클레임을 검증합니다. API Gateway는 다음 토큰 클레임을 평가합니다.
   +  [https://datatracker.ietf.org/doc/html/rfc7517#section-4.5](https://datatracker.ietf.org/doc/html/rfc7517#section-4.5) – 토큰에는 토큰에 서명한 `jwks_uri`의 키와 일치하는 헤더 클레임이 있어야 합니다.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) – 권한 부여자에 대해 구성된 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration)와 일치해야 합니다.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) 또는 `client_id` – 권한 부여자에 대해 구성된 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration) 항목 중 하나와 일치해야 합니다. API 게이트웨이는 `aud`가 없는 경우에만 `client_id`의 유효성을 검사합니다. `aud`와 `client_id`가 모두 있는 경우 API Gateway는 `aud`를 평가합니다.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) – 현재 시간(UTC 기준) 이후여야 합니다.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5) – 현재 시간(UTC 기준) 이전이어야 합니다.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6) – 현재 시간(UTC 기준) 이전이어야 합니다.
   + [https://datatracker.ietf.org/doc/html/rfc6749#section-3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) 또는 `scp` – 토큰에 라우팅의 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes) 범위 중 하나 이상이 포함되어야 합니다.

이러한 단계 중 하나가 실패하면 API Gateway는 API 요청을 거부합니다.

JWT를 검증한 후 API Gateway는 토큰의 클레임을 API 경로의 통합에 전달합니다. Lambda 함수와 같은 백엔드 리소스는 JWT 클레임에 액세스할 수 있습니다. 예를 들어, JWT에 자격 증명 클레임 `emailID`가 포함된 경우 `$event.requestContext.authorizer.jwt.claims.emailID`의 Lambda 통합에 해당 클레임을 사용할 수 있습니다. API Gateway가 Lambda 통합으로 보내는 페이로드에 대한 자세한 내용은 [API Gateway에서 HTTP API에 대한 AWS Lambda 프록시 통합 생성](http-api-develop-integrations-lambda.md) 단원을 참조하세요.

## JWT 권한 부여자 생성
<a name="http-api-jwt-authorizer.create"></a>

JWT 권한 부여자를 생성하기 전에 클라이언트 애플리케이션을 자격 증명 공급자에 등록해야 합니다. 또한 HTTP API를 생성해야 합니다. HTTP API 생성 예제는 [HTTP API 생성](http-api-develop.md#http-api-examples) 단원을 참조하세요.

### 콘솔을 사용하여 JWT 권한 부여자를 생성하려는 경우
<a name="http-api-jwt-authorizer.create.console"></a>

다음 단계는 콘솔을 사용하여 JWT 권한 부여자를 생성하는 방법을 보여줍니다.

**콘솔을 사용하여 JWT 권한 부여자를 생성하려는 경우**

1. [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)에서 API Gateway 콘솔에 로그인합니다.

1. HTTP API를 선택합니다.

1. 기본 탐색 창에서 **권한 부여자**를 선택합니다.

1. **권한 부여자 관리** 탭을 선택합니다.

1. **생성(Create)**을 선택합니다.

1. **권한 부여자 유형**으로는 **JWT**를 선택합니다.

1. JWT 권한 부여자를 구성하고 토큰 소스를 정의하는 ID **소스**를 지정합니다.

1. **생성(Create)**을 선택합니다.

#### AWS CLI를 사용하여 사용자 지정 권한 부여자 생성
<a name="http-api-jwt-authorizer.create.cli"></a>

다음 [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) 명령은 JWT 권한 부여자를 생성합니다. `jwt-configuration`의 경우 ID 공급자에 대한 `Audience`와 `Issuer`를 지정합니다. Amazon Cognito를 ID 공급자로 사용하는 경우 `IssuerUrl`은 `https://cognito-idp.us-east-2.amazonaws.com/userPoolID`입니다.

```
aws apigatewayv2 create-authorizer \
    --name authorizer-name \
    --api-id api-id \
    --authorizer-type JWT \
    --identity-source '$request.header.Authorization' \
    --jwt-configuration Audience=audience,Issuer=IssuerUrl
```

##### AWS CloudFormation을 사용하여 JWT 권한 부여자 생성
<a name="http-api-jwt-cfn.create"></a>

다음 CloudFormation 템플릿은 Amazon Cognito를 ID 공급자로 사용하는 JWT 권한 부여자를 사용하여 HTTP API를 만듭니다.

CloudFormation 템플릿의 출력은 Amazon Cognito 호스팅 UI의 URL로, 클라이언트가 가입하고 로그인하여 JWT를 받을 수 있습니다. 클라이언트가 로그인하면 URL에 액세스 토큰이 있는 HTTP API로 클라이언트가 리디렉션됩니다. 액세스 토큰으로 API를 간접 호출하려면 토큰을 쿼리 문자열 파라미터로 사용하도록 URL의 `#`를 `?`로 변경하세요.

##### 예제 CloudFormation 템플릿
<a name="http-api-jwt-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Example HTTP API with a JWT authorizer. This template includes an Amazon Cognito user pool as the issuer for the JWT authorizer 
  and an Amazon Cognito app client as the audience for the authorizer. The outputs include a URL for an Amazon Cognito hosted UI where clients can 
  sign up and sign in to receive a JWT. After a client signs in, the client is redirected to your HTTP API with an access token 
  in the URL. To invoke the API with the access token, change the '#' in the URL to a '?' to use the token as a query string parameter.

Resources:
  MyAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties: 
      Description: Example HTTP API
      Name: api-with-auth
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn
  DefaultRouteOverrides:
    Type: AWS::ApiGatewayV2::ApiGatewayManagedOverrides
    Properties: 
      ApiId: !Ref MyAPI
      Route: 
        AuthorizationType: JWT
        AuthorizerId: !Ref JWTAuthorizer
  JWTAuthorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties: 
      ApiId: !Ref MyAPI
      AuthorizerType: JWT
      IdentitySource: 
        - '$request.querystring.access_token'
      JwtConfiguration: 
        Audience: 
        - !Ref AppClient
        Issuer: !Sub https://cognito-idp.${AWS::Region}.amazonaws.com/${UserPool}
      Name: test-jwt-authorizer
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs18.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello from the ' + event.routeKey + ' route!'),
              };
              return response;
          };
  APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17		 	 	 '
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: http-api-user-pool
      AutoVerifiedAttributes:
        - email
      Schema:
        - Name: name
          AttributeDataType: String
          Mutable: true
          Required: true
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
  AppClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      AllowedOAuthFlows: 
        - implicit
      AllowedOAuthScopes: 
        - aws.cognito.signin.user.admin
        - email
        - openid
        - profile
      AllowedOAuthFlowsUserPoolClient: true
      ClientName: api-app-client
      CallbackURLs:
        - !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: !Ref UserPool
      SupportedIdentityProviders:
        - COGNITO 
  HostedUI:
    Type: AWS::Cognito::UserPoolDomain
    Properties: 
      Domain: !Join
        - '-'
        - - !Ref MyAPI
          - !Ref AppClient
      UserPoolId: !Ref UserPool
Outputs:
  SignupURL:
    Value: !Sub https://${HostedUI}.auth.${AWS::Region}.amazoncognito.com/login?client_id=${AppClient}&response_type=token&scope=email+profile&redirect_uri=https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
```

## CLI를 사용하여 JWT 권한 부여자를 사용하도록 경로 업데이트
<a name="http-api-jwt-authorizer.create.route"></a>

콘솔, AWS CLI, 또는 AWS SDK를 사용하여 JWT 권한 부여자를 사용하도록 경로를 업데이트할 수 있습니다.

### 콘솔을 사용하여 JWT 권한 부여자를 사용하도록 경로 업데이트
<a name="http-api-jwt-authorizer.create.route"></a>

다음 단계는 콘솔을 사용하여 JWT 권한 부여자를 사용하도록 경로를 업데이트하는 방법을 보여줍니다.

**콘솔을 사용하여 JWT 권한 부여자를 생성하는 경우**

1. [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)에서 API Gateway 콘솔에 로그인합니다.

1. HTTP API를 선택합니다.

1. 기본 탐색 창에서 **권한 부여자**를 선택합니다.

1. 방법을 선택한 다음 드롭다운 메뉴에서 권한 부여자를 선택하고 **권한 부여자**을 선택합니다.

#### AWS CLI를 사용하여 JWT 권한 부여자를 사용하도록 경로 업데이트
<a name="http-api-jwt-authorizer.create.route"></a>

다음 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 명령은 JWT 권한 부여자를 사용하도록 경로를 업데이트합니다.

```
aws apigatewayv2 update-route \
   --api-id api-id  \
   --route-id route-id  \
   --authorization-type JWT \
   --authorizer-id authorizer-id \
   --authorization-scopes user.email
```

# API Gateway에서 IAM 권한 부여를 통해 HTTP API에 대한 액세스 제어
<a name="http-api-access-control-iam"></a>

HTTP API 라우팅에 대해 IAM 권한 부여를 활성화할 수 있습니다. IAM 권한 부여가 활성화된 경우 클라이언트는 [Signature Version 4(SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html)를 사용하여 AWS 자격 증명으로 요청에 서명해야 합니다. API Gateway는 클라이언트가 라우팅에 대한 `execute-api` 권한을 가진 경우에만 API 라우팅을 호출합니다.

HTTP API에 대한 IAM 권한 부여는 [REST API](api-gateway-control-access-using-iam-policies-to-invoke-api.md)에 대한 권한 부여와 유사합니다.

**참고**  
리소스 정책은 현재 HTTP API에 대해 지원되지 않습니다.

클라이언트에 API 호출 권한을 부여하는 IAM 정책의 예는 [API 호출을 위한 액세스 제어](api-gateway-control-access-using-iam-policies-to-invoke-api.md) 단원을 참조하세요.

## 라우팅에 대한 IAM 권한 부여 활성화
<a name="http-api-access-control-iam-example"></a>

다음 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 명령은 HTTP API 경로에 대한 IAM 권한 부여를 활성화합니다.

```
aws apigatewayv2 update-route \
    --api-id abc123 \
    --route-id abcdef \
    --authorization-type AWS_IAM
```