简体   繁体   中英

AWS API Gateway Custom Authorizer lambda

I am trying to authorise the API calls though AWS API Gateway's Custom authorizer,
which is basically a custom lambda function which takes in the following header of following format-

{
    "authorizationToken": "0c34ba00bde34200b383abe22bcfef96",
    "methodArn": "arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/",
    "type": "TOKEN"
}

And expects a response in the following format -

{
  "principalId": "xxxxxxx", // the principal user identification associated with the token send by the client
  "policyDocument": { // example policy shown below, but this value is any valid policy
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "execute-api:Invoke"
        ],
        "Resource": [
          "arn:aws:execute-api:us-east-1:xxxxxxxxxxxx:xxxxxxxx:/test/*/mydemoresource/*"
        ]
      }
    ]
  }
}

I am able to do the internal logic with the authorizationToken and validate whether the function should respond in a "Allow" or "Deny" policy ,
But I am getting a parsing error when I tried to test the Authorizer from the console,
Following are my request logs -

Execution log for request test-request
Thu Jun 29 11:48:10 UTC 2017 : Starting authorizer: 1o3dvk for request: test-request
Thu Jun 29 11:48:10 UTC 2017 : Incoming identity: **************************cfef96
Thu Jun 29 11:48:10 UTC 2017 : Endpoint request URI: https://lambda.ap-southeast-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:ap-southeast-1:855399270504:function:um_guestSessionAuthoriser/invocations
Thu Jun 29 11:48:10 UTC 2017 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=*********************************************************************************************************************************************************************************************************************************************************************************************************************************************751e60, X-Amz-Date=20170629T114810Z, x-amzn-apigateway-api-id=z6t3cv0z4m, X-Amz-Source-Arn=arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/authorizers/1o3dvk, Accept=application/json, User-Agent=AmazonAPIGateway_z6t3cv0z4m, X-Amz-Security-Token=FQoDYXdzEHQaDOcIbaPscYGsl1wF4iLBAxzOTpZlR2r3AO3g96xwhRuQjEhU9OjOaRieBWQPeosNqv53aGKnBTT2CmkrVzHo3UqOdT1eakuS7tAXAbEcUIHVheWpBnvxqTkaPcknRL7QE79RSqVeryoXo2R1Kmk0Q9Iq+JGFlOJYQQJqvY/hcUg189xqbpTGrhZjcA+pjuSp+M9D97Kce0VP0e3peu/YvON0eGvUlj59MAJAwGVPIzplMKTDFrFg5NKEj79RSxNrNE8y4bAebOwlD8xLv649Zny7++xlMBBwHqMNHu3K9lFXSnKY9DHf6kvezZmpoFB2uu8WbrpInH0eQ/bIAd [TRUNCATED]
Thu Jun 29 11:48:10 UTC 2017 : Endpoint request body after transformations: {"type":"TOKEN","methodArn":"arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/","authorizationToken":"0c34ba00bde34200b383abe22bcfef96"}
Thu Jun 29 11:48:10 UTC 2017 : Sending request to https://lambda.ap-southeast-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:ap-southeast-1:855399270504:function:um_guestSessionAuthoriser/invocations
Thu Jun 29 11:48:21 UTC 2017 : Authorizer result body before parsing: {"principalId":"user","policyDocument":{"version":"2012-10-17","statement":[{"resource":"arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/","action":"execute-api:Invoke","effect":"Allow"}]}}
Thu Jun 29 11:48:21 UTC 2017 : Execution failed due to configuration error: Could not parse policy: {"version":"2012-10-17","statement":[{"resource":"arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/","action":"execute-api:Invoke","effect":"Allow"}]}
Thu Jun 29 11:48:21 UTC 2017 : AuthorizerConfigurationException

I am using Java on the Lambda function and I have build and returned the policy using aa PoJo class(setter-getter class)
After beautifying the lambda response my Policy looks like follows -

{
    "principalId": "user",
    "policyDocument": {
        "version": "2012-10-17",
        "statement": [{
            "resource": "arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/",
            "action": "execute-api:Invoke",
            "effect": "Allow"
        }]
    }
}

I am wondering why it's not able to parse my response?
As per advise I tried to capitalise the response IAM Policy,
I used @SerializedName of com.google.gson.annotations.SerializedName import and was able to get the following output -

{
    "principalId": "user",
    "policyDocument": {
        "version": "2012-10-17",
        "statement": [{
            "effect": "Deny",
            "action": ["execute-api:Invoke"],
            "resource": ["arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/"]
        }]
    }
}

But it looks like something weird is happening in between my lambda response and the API Gateway,
The variables are getting internally lower cased somewhere,
And I still got the same parsing error,
Could it be accepting a response in some other format? String didn't work either.

What else should I try? Is my policy format wrong?
I got two different Policy formats from these sites -
1. http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html
2. https://aws.amazon.com/blogs/compute/introducing-custom-authorizers-in-amazon-api-gateway/

Your policy attributes need proper capitalization. Instead of:

{
    "principalId": "user",
    "policyDocument": {
        "version": "2012-10-17",
        "statement": [{
            "resource": "arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/",
            "action": "execute-api:Invoke",
            "effect": "Allow"
        }]
    }
}

Should be:

{
    "principalId": "user",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [{
            "Resource": "arn:aws:execute-api:ap-southeast-1:855399270504:z6t3cv0z4m/null/GET/",
            "Action": "execute-api:Invoke",
            "Effect": "Allow"
        }]
    }
}

Might as well use "PrincipalId" to keep things consistent.

Chris, your answer is almost correct. Version , Statement , Resource , Action and Effect must be capitalized but be aware of policyDocument and principalId

A correct response should look like:

{
  "principalId": "yourUserId",
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:eu-west-1:0123456878910:g3ttos57v5/live/PUT/your/resource/*"
      }
    ]
  }
}

I found that when AWS serializes the return value of your Authorizer handler, it does not honor the com.google.gson.annotations.SerializedName flag to capitalize certain fields. They're probably using a different serializer than gson.

The way I solved it was to instead return Map<String, Object> with correct capitalization:

private Map<String, Object> formatAuthorizerResponse(AuthorizerResponseEvent response) {
    String json = gson.toJson(response);
    Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
    return new Gson().fromJson(json, mapType);
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM