2

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 a a 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/

3 Answers 3

5

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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/*"
      }
    ]
  }
}

Comments

0

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);
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.