Lời nói đầu
Chào các bạn, mình là Duy Nam - Solution Architect Engineer VTI Japan. Tiếp theo Authorization sử dụng Amazon Cognito, API Gateway và IAM (Phần 1) hôm nay mình xin giới thiệu về tiếp về việc thêm chức năng Authorization vào API Gateway.
III. Thêm chức năng Authorizer vào API Gateway
1. Tạo Amazon Cognito Resource và đăng ký User
- Overview
2. Sử dụng Cloudformation để triển khai Amazon Cognito
- api-with-auth.yaml
...
#===========================================================================================#
# Resource Block
#===========================================================================================#
Resources:
#================================================================#
# Create Cognito Resource
#================================================================#
#----------------------------------------------#
# Cognito User Pool
#----------------------------------------------#
CognitoUserPool:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: CognitoPool
#----------------------------------------------#
# Cognito User Pool Group
#----------------------------------------------#
CognitoUserPoolGroup:
DependsOn:
- CognitoUserPool
Type: 'AWS::Cognito::UserPoolGroup'
Properties:
GroupName: pet-veterinarian
UserPoolId: !Ref CognitoUserPool
#----------------------------------------------#
# Cognito User Pool Client
#----------------------------------------------#
CognitoUserPoolClient:
DependsOn:
- CognitoUserPool
Type: 'AWS::Cognito::UserPoolClient'
Properties:
UserPoolId: !Ref CognitoUserPool
AllowedOAuthFlows:
- implicit
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- email
- openid
CallbackURLs:
- 'http://localhost'
GenerateSecret: false
ExplicitAuthFlows:
- ALLOW_USER_PASSWORD_AUTH
- ALLOW_USER_SRP_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
SupportedIdentityProviders:
- COGNITO
#----------------------------------------------#
# Cognito User Pool Domain
#----------------------------------------------#
CognitoUserPoolDomain:
DependsOn:
- CognitoUserPoolClient
Type: 'AWS::Cognito::UserPoolDomain'
Properties:
# using client id will make the domain unique
Domain: !Sub dns-name-${CognitoUserPoolClient}
UserPoolId: !Ref CognitoUserPool
#----------------------------------------------#
# Helper Cognito Lambda Role
#----------------------------------------------#
HelperCognitoLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: helperCognitoLambdaRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- cognito-idp:Admin*
Resource: !GetAtt CognitoUserPool.Arn
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-HelperInitCognitoFunction-*:*
#----------------------------------------------#
# PetAPI Lambda LogGroup
#----------------------------------------------#
HelperInitCognitoFunctionLogGr:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/HelperInitCognitoFunction
RetentionInDays: 7
#----------------------------------------------#
# Helper Cognito Lambda Init
#----------------------------------------------#
HelperInitCognitoFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: HelperInitCognitoFunction
Code:
ZipFile: >
const AWS = require("aws-sdk");
const response = require("cfn-response");
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
exports.handler = function (event, context, callback) {
var userPoolId = event.ResourceProperties.UserPoolId;
var username = event.ResourceProperties.CognitoUserName;
var pass = event.ResourceProperties.CognitoUserPassword;
console.log("username: " + username);
var params = {
UserPoolId: userPoolId,
Username: username,
TemporaryPassword: pass
};
cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
if (err) {
console.log(err, err.stack);
} else {
console.log(data);
}
const params = {
UserPoolId: userPoolId,
Username: username,
Password: pass,
Permanent: true
};
cognitoidentityserviceprovider.adminSetUserPassword(params, function (err, data) {
if (err) {
response.send(event, context, "FAILED", {});
} else {
response.send(event, context, "SUCCESS", {});
}
});
});
};
Handler: index.handler
Role: !GetAtt HelperCognitoLambdaRole.Arn
Runtime: nodejs12.x
Timeout: 30
#----------------------------------------------#
# Helper Cognito Lambda Invoke
#----------------------------------------------#
HelperInitializeCognitoUser:
Type: Custom::HelperInitCognitoFunction
DependsOn: CognitoUserPool
Properties:
ServiceToken: !GetAtt HelperInitCognitoFunction.Arn
UserPoolId: !Ref CognitoUserPool
CognitoUserName: !Ref CognitoUserName
CognitoUserPassword: !Ref CognitoUserPassword
# <<< helper to create Cognito User without the need to confirm email
#----------------------------------------------#
# Cognito User Pool User To Group Attachment
#----------------------------------------------#
CognitoUserPoolUserToGroupAttachment:
DependsOn:
- CognitoUserPoolGroup
- HelperInitializeCognitoUser
Type: 'AWS::Cognito::UserPoolUserToGroupAttachment'
Properties:
GroupName: !Ref CognitoUserPoolGroup
Username: !Ref CognitoUserName
UserPoolId: !Ref CognitoUserPool
#================================================================#
# PetAPI Resource
#================================================================#
#----------------------------------------------#
# IAM Policy for PetAPI Lambda
#----------------------------------------------#
ApiServiceIAMPolicy:
Type: 'AWS::IAM::Policy'
Properties:
Roles:
- !Ref ApiServiceIAMRole
PolicyName: ApiServiceIAMPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- cognito-idp:Admin*
Resource: !GetAtt CognitoUserPool.Arn
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/ApiServiceLambdaFunction:*
...
- Mình có thêm một Lambda tiến hành tự động đăng ký user vào trong Amazon Cognito khi chạy cloudformation một user/password sẽ được tạo ra thông qua parameter truyền vào
3. Tạo Lambda-Authorizer
- Tạo requirements.txt
python-jose==3.2.0
- Lambda source code (lambda.py)
import os
import boto3
import json
import time
import urllib.request
from jose import jwk, jwt
from jose.utils import base64url_decode
# envs
TABLE_NAME = os.environ['TABLE_NAME']
AWS_REGION = os.environ['AWS_REGION']
COGNITO_USER_POOL_ID = os.environ['COGNITO_USER_POOL_ID']
COGNITO_APP_CLIENT_ID = os.environ['COGNITO_APP_CLIENT_ID']
keys_url = 'https://cognito-idp.{}.amazonaws.com/{}/.well-known/jwks.json'.format(AWS_REGION, COGNITO_USER_POOL_ID)
# instead of re-downloading the public keys every time
# we download them only on cold start
# https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/
with urllib.request.urlopen(keys_url) as f:
response = f.read()
keys = json.loads(response.decode('utf-8'))['keys']
def handler(event, context):
print(event)
token_data = parse_token_data(event)
if token_data['valid'] is False:
return get_deny_policy()
try:
claims = validate_token(token_data['token'])
groups = claims['cognito:groups']
results = batch_query_wrapper(TABLE_NAME, 'group', groups)
print(results)
if len(results) > 0:
policy = {
'Version': results[0]['policy']['Version'],
'Statement': []
}
for item in results:
policy['Statement'] = policy['Statement'] + item['policy']['Statement']
return get_response_object(policy)
return get_deny_policy()
except Exception as e:
print(e)
return get_deny_policy()
def get_response_object(policyDocument, principalId='yyyyyyyy', context={}):
return {
"principalId": principalId,
"policyDocument": policyDocument,
"context": context,
"usageIdentifierKey": "{api-key}"
}
def get_deny_policy():
return {
"principalId": "yyyyyyyy",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": "arn:aws:execute-api:*:*:*/ANY/*"
}
]
},
"context": {},
"usageIdentifierKey": "{api-key}"
}
def batch_query_wrapper(table, key, values):
results = []
dynamodb = boto3.resource('dynamodb', region_name=AWS_REGION)
values_list = [values[x:x + 25] for x in range(0, len(values), 25)]
for vlist in values_list:
response = dynamodb.batch_get_item(RequestItems={table: {'Keys': [{key: val} for val in vlist]}})
results.extend(response['Responses'][table])
while response['UnprocessedKeys']:
response = dynamodb.batch_get_item(RequestItems={table: {'Keys': [{key: val} for val in vlist]}})
results.extend(response['Response'][table])
return results
def parse_token_data(event):
response = {'valid': False}
if 'Authorization' not in event['headers']:
return response
auth_header = event['headers']['Authorization']
auth_header_list = auth_header.split(' ')
# deny request of header isn't made out of two strings, or
# first string isn't equal to "Bearer" (enforcing following standards,
# but technically could be anything or could be left out completely)
if len(auth_header_list) != 2 or auth_header_list[0] != 'Bearer':
return response
access_token = auth_header_list[1]
return {
'valid': True,
'token': access_token
}
def validate_token(token):
# get the kid from the headers prior to verification
headers = jwt.get_unverified_headers(token)
kid = headers['kid']
# search for the kid in the downloaded public keys
key_index = -1
for i in range(len(keys)):
if kid == keys[i]['kid']:
key_index = i
break
if key_index == -1:
print('Public key not found in jwks.json')
return False
# construct the public key
public_key = jwk.construct(keys[key_index])
# get the last two sections of the token,
# message and signature (encoded in base64)
message, encoded_signature = str(token).rsplit('.', 1)
# decode the signature
decoded_signature = base64url_decode(encoded_signature.encode('utf-8'))
# verify the signature
if not public_key.verify(message.encode("utf8"), decoded_signature):
print('Signature verification failed')
return False
print('Signature successfully verified')
# since we passed the verification, we can now safely
# use the unverified claims
claims = jwt.get_unverified_claims(token)
# additionally we can verify the token expiration
if time.time() > claims['exp']:
print('Token is expired')
return False
# and the Audience (use claims['client_id'] if verifying an access token)
if claims['client_id'] != COGNITO_APP_CLIENT_ID:
print('Token was not issued for this audience')
return False
# now we can use the claims
print(claims)
return claims
- Tiến hành Package Lambda
cd ./Lambda/custom-auth
pip3 install --target ./package python-jose==3.2.0
cd ./package
zip -r ../custom-auth.zip . > /dev/null
cd .. && zip -g custom-auth.zip lambda.py
mv ./custom-auth.zip ../../cf-lambdas
rm -r ./package
cd ./../..
- Upload source lên S3
aws s3 cp ./cf-lambdas/custom-auth.zip s3://$S3_BUCKET_NAME
4. Sử dụng Cloudformation để triển khai Amazon DynamoDB, Lambda-Authorizer
4.1 OverView
4.2 Update API Gateway resource sử dụng Cognito tiến hành Protect API
...
#================================================================#
# API Gateway Resource
#================================================================#
#----------------------------------------------#
# Create API Gateway with RestApi type
#----------------------------------------------#
ApiGatewayRestApi:
Type: 'AWS::ApiGateway::RestApi'
Properties:
Name: "MyApiGateway"
#----------------------------------------------#
# Create API Gateway Resource
#----------------------------------------------#
ApiGatewayResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref ApiGatewayRestApi
ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
PathPart: "{api+}"
#----------------------------------------------#
# API Gateway Invoke Lambda Policy
#----------------------------------------------#
ApiGatewayCustomAuthIAMPolicy:
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: ApiGatewayCustomAuthIAMPolicy
Roles:
- !Ref ApiGatewayCustomAuthIAMRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'lambda:InvokeFunction'
Resource: !GetAtt CustomAuthLambdaFunction.Arn
#----------------------------------------------#
# API Gateway Invoke Lambda Role
#----------------------------------------------#
ApiGatewayCustomAuthIAMRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: ApiGatewayCustomAuthIAMRole
AssumeRolePolicyDocument: |-
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
#----------------------------------------------#
# API Gateway Authorizer
#----------------------------------------------#
ApiGatewayAuthorizer:
Type: 'AWS::ApiGateway::Authorizer'
Properties:
Name: custom-auth
RestApiId: !Ref ApiGatewayRestApi
Type: REQUEST
IdentitySource: method.request.header.Authorization
AuthorizerResultTtlInSeconds: '300'
AuthorizerCredentials: !GetAtt ApiGatewayCustomAuthIAMRole.Arn
AuthorizerUri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CustomAuthLambdaFunction.Arn}/invocations
#----------------------------------------------#
# Create API Gateway Method
#----------------------------------------------#
ApiGatewayMethod:
DependsOn: ApiGatewayAuthorizer
Type: 'AWS::ApiGateway::Method'
Properties:
HttpMethod: "ANY"
ResourceId: !Ref ApiGatewayResource
RestApiId: !Ref ApiGatewayRestApi
AuthorizationType: CUSTOM
AuthorizerId: !Ref ApiGatewayAuthorizer
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: "POST"
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiServiceLambdaFunction.Arn}/invocations
#----------------------------------------------#
# Deploy API Gateway
#----------------------------------------------#
ApiGatewayDeploymentProtected:
DependsOn:
- ApiGatewayAuthorizer
- ApiGatewayMethod
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref ApiGatewayRestApi
StageName: dev
Description: protected api
...
4.3 Tạo Custom-Auth Lambda
...
#================================================================#
# Custom-Auth Resource
#================================================================#
#----------------------------------------------#
# IAM Policy for Custom-Auth Lambda
#----------------------------------------------#
CustomAuthIAMPolicy:
Type: 'AWS::IAM::Policy'
Properties:
Roles:
- !Ref CustomAuthIAMRole
PolicyName: CustomAuthIAMPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- cognito-idp:*
Resource: !GetAtt CognitoUserPool.Arn
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/CustomAuthLambdaFunction:*
- Effect: Allow
Action:
- dynamodb:BatchGetItem
Resource: !GetAtt DynamoDBTable.Arn
#----------------------------------------------#
# IAM Role for Custom-Auth Lambda
#----------------------------------------------#
CustomAuthIAMRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: CustomAuthIAMRole
AssumeRolePolicyDocument: |-
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
#----------------------------------------------#
# Custom-Auth Lambda LogGroup
#----------------------------------------------#
CustomAuthLambdaLogGr:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/CustomAuthLambdaFunction
RetentionInDays: 7
#----------------------------------------------#
# Custom-Auth Lambda
#----------------------------------------------#
CustomAuthLambdaFunction:
DependsOn:
- CustomAuthLambdaLogGr
Type: 'AWS::Lambda::Function'
Properties:
FunctionName: CustomAuthLambdaFunction
Runtime: "python3.6"
Handler: "lambda.handler"
Role: !GetAtt CustomAuthIAMRole.Arn
Code:
S3Bucket: !Sub cognito-api-gateway-${AWS::AccountId}-${AWS::Region}-lambdas
S3Key: "custom-auth.zip"
Environment:
Variables:
TABLE_NAME: "auth-policy-store"
COGNITO_USER_POOL_ID: !Ref CognitoUserPool
COGNITO_APP_CLIENT_ID: !Ref CognitoUserPoolClient
...
4.4 Tạo DynamoDB Resource và Lambda Init giá trị của DynamoDB
...
#================================================================#
# DynamoDB Resource
#================================================================#
#----------------------------------------------#
# DynamoDB Table
#----------------------------------------------#
DynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
TableName: auth-policy-store
AttributeDefinitions:
- AttributeName: "group"
AttributeType: "S"
KeySchema:
- AttributeName: "group"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: "5"
WriteCapacityUnits: "5"
#----------------------------------------------#
# Helper DynamoDb Lambda Role
#----------------------------------------------#
HelperDynamoDbLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: dynamodbAccessRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:PutItem
Resource: !GetAtt DynamoDBTable.Arn
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub arn:aws:logs:${AWS::Region}::log-group:/aws/lambda/${AWS::StackName}-*:*
#----------------------------------------------#
# Helper DynamoDb Lambda LogGroup
#----------------------------------------------#
HelperDynamoDbInitLambdaLogGr:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/HelperDynamoDbInitFunction
RetentionInDays: 7
#----------------------------------------------#
# Helper DynamoDb Lambda Init
#----------------------------------------------#
HelperDynamoDbInitFunction:
DependsOn:
- HelperDynamoDbInitLambdaLogGr
Type: AWS::Lambda::Function
Properties:
FunctionName: HelperDynamoDbInitFunction
Code:
ZipFile: >
const AWS = require("aws-sdk");
const response = require("cfn-response");
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event, context) {
console.log(JSON.stringify(event,null,2));
var params = {
TableName: event.ResourceProperties.DynamoTableName,
Item:{
"group": "pet-veterinarian",
"policy": {
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": [
"arn:aws:execute-api:*:*:*/*/*/petstore/v1/*",
"arn:aws:execute-api:*:*:*/*/GET/petstore/v2/status"
],
"Sid": "PetStore-API"
}
],
"Version": "2012-10-17"
}
}
};
docClient.put(params, function(err, data) { if (err) {
response.send(event, context, "FAILED", {});
} else {
response.send(event, context, "SUCCESS", {});
}
});
};
Handler: index.handler
Role: !GetAtt HelperDynamoDbLambdaRole.Arn
Runtime: nodejs12.x
Timeout: 30
#----------------------------------------------#
# Helper DynamoDb Lambda Invoke
#----------------------------------------------#
HelperDynamoDbInitializeDynamoDB:
Type: Custom::InitFunction
DependsOn: DynamoDBTable
Properties:
ServiceToken: !GetAtt HelperDynamoDbInitFunction.Arn
DynamoTableName: !Ref DynamoDBTable
#===========================================================================================#
# Output Block
#===========================================================================================#
Outputs:
CognitoUserPoolClientId:
Value: !Ref CognitoUserPoolClient
CognitoHostedUiUrl:
Value: !Sub https://${CognitoUserPoolDomain}.auth.${AWS::Region}.amazoncognito.com/login?client_id=${CognitoUserPoolClient}&response_type=token&scope=email+openid&redirect_uri=http://localhost
ApiGatewayDeploymentUrlApiEndpoint:
Value: !Sub https://${ApiGatewayRestApi}.execute-api.${AWS::Region}.amazonaws.com/dev/petstore/v1/pets
ApiGatewayDeploymentUrlApiEndpointV2:
Value: !Sub https://${ApiGatewayRestApi}.execute-api.${AWS::Region}.amazonaws.com/dev/petstore/v2/pets
4.5 Tạo Service sử dụng Cloudformation
- Sau khi tổng hợp các nội dung Cloudformation phía trên các bạn chạy lại để tiến hành update resource
CF_STACK_NAME="cognito-api-gateway"
S3_BUCKET_NAME="${CF_STACK_NAME}-${ACCOUNT_ID}-${STACK_REGION}-lambdas"
aws cloudformation deploy --template-file ./infrastructure/api-with-auth.yaml \
--stack-name $CF_STACK_NAME \
--s3-bucket $S3_BUCKET_NAME \
--s3-prefix cfn \
--parameter-overrides CognitoUserName=cognitouser CognitoUserPassword=Password@1990 \
--capabilities CAPABILITY_NAMED_IAM
- Sử dụng Postman test service xuất hiện thông báo Unauthorized
5. Để tạo một request thành công đến phía service bạn cần phải làm theo từng bước sau:
5.1 Có một user name và password để chứng thực tại Amazon Cognito user pool.
5.2 Nhận lấy tokens (id token, access token, and refresh token) dựa trên thông tin user/password.
- Các bạn có thể tham khảo thông tin trong file get-token.sh dưới đây
#!/usr/bin/env bash
CF_STACK_NAME="cognito-api-gateway"
ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
STACK_REGION=$(aws configure get region)
get_login_payload_data() {
OUTPUT=($(aws cloudformation describe-stacks \
--stack-name ${CF_STACK_NAME} \
--query 'Stacks[0].[Parameters[0:2].ParameterValue, Outputs[1].OutputValue, Outputs[0].OutputValue] | []' \
--output text))
COGNITO_USERS_PASSWORD="${OUTPUT[0]}"
COGNITO_USERNAME="${OUTPUT[1]}"
API_URL="${OUTPUT[2]}"
COGNITO_CLIENT_ID="${OUTPUT[3]}"
DATA=$(cat<<EOF
{
"AuthParameters" : {
"USERNAME" : "${COGNITO_USERNAME}",
"PASSWORD" : "${COGNITO_USERS_PASSWORD}"
},
"AuthFlow" : "USER_PASSWORD_AUTH",
"ClientId" : "${COGNITO_CLIENT_ID}"
}
EOF)
echo $DATA
}
get_access_token() {
ACCESS_TOKEN=$(curl -s -X POST --data "${DATA}" \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
https://cognito-idp."${STACK_REGION}".amazonaws.com/ | cut -d':' -f 3 | cut -d'"' -f 2)
echo $ACCESS_TOKEN
}
get_login_payload_data
get_access_token
- Chạy get-token.sh và thu thấy access token
bash ./source/get-token.sh
5.3 Tạo một HTTPS (TLS) request đến API Gateway và truyền access token vào headers.
-
Tại Headers thêm giá trị:
- Key: Authorization
- Value: Bearer eyJraWQiOiJReDB6SkMy...(Access Token)
-
Thử gọi api-v1
- Trong lần gọi này đã nhận được data từ API service. Chúng ta hãy xem các bước đã được thực thi:
- Lambda authorizer tiến hành validate access token
- Lambda authorizer xác định policy trong DynamoDB dựa trên group name đã nhận được từ access token
- Lambda authorizer trả lại IAM Policy ngược lại cho API Gateway
- API Gateway thu lấy IAM Policy và xác nhận các hành động cho phép
- API Gateway forward request đến Lambda Service
- Lambda trả về một Response
- Trong lần gọi này đã nhận được data từ API service. Chúng ta hãy xem các bước đã được thực thi:
-
Thử gọi api-v2
- Tại Policy đã định nghĩa trong DynamoDB, chỉ "/petstore/v2/status" API được sử dụng nên response trả về sẽ là unauthorized
- Sử dụng Policy định nghĩa trong DynamoDB chúng ta có thể giới hạn được quyền của người dùng
-
Thử gọi api-v2 lấy status
- Access thành công, status trả về ok
4. Xóa Resource
- Để tiến hành xóa resource đã được tạo ra các bạn sử dụng các lệnh dưới đây:
aws cloudformation delete-stack --stack-name $CF_STACK_NAME
aws s3 rm s3://"${S3_BUCKET_NAME}/custom-auth.zip"
aws s3 rm s3://"${S3_BUCKET_NAME}/pets-api.zip"
aws s3 rm s3://"${S3_BUCKET_NAME}/cfn" --recursive
aws s3api delete-bucket \
--bucket "${S3_BUCKET_NAME}" \
--region "${STACK_REGION}" > /dev/null
Kết luận
- Qua bài viết này hi vọng các bạn có một Overview về việc Authorize sử dụng Congito và API Gateway
- Mình là Duy Nam - VTI Japan các bạn có câu hỏi gì có thể comment phía dưới
- Thanks and Best Regaruads
Leave a Reply