Search code examples
python-3.xrestapiamazon-web-servicesamazon-lex

How do I get an authorized user for PostText API call for a Lex bot runtime


Sorry for the long post. I am trying to call a Lex bot with the PostText runtime API with my lambda function. However when I test this call then it returns that the userID is not authorized to use this. This is the error message I receive:

    Response:
{
  "errorMessage": "An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab",
  "errorType": "ClientError",
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      18,
      "lambda_handler",
      "inputText= userInput"
    ],
    [
      "/var/runtime/botocore/client.py",
      314,
      "_api_call",
      "return self._make_api_call(operation_name, kwargs)"
    ],
    [
      "/var/runtime/botocore/client.py",
      612,
      "_make_api_call",
      "raise error_class(parsed_response, operation_name)"
    ]
  ]
}

Request ID:
"677f1820-6ed2-11e8-b891-33ab1951c65f"

Function Logs:
START RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f Version: $LATEST
An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab: ClientError
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 18, in lambda_handler
    inputText= userInput
  File "/var/runtime/botocore/client.py", line 314, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 612, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab

END RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f
REPORT RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f  Duration: 325.25 ms Billed Duration: 400 ms     Memory Size: 128 MB Max Memory Used: 31 MB  

This is my code to calling the API:

    import boto3

def lambda_handler(event, context):
    responderName = event["DestinationBot"]
    userId = event["RecipientID"]
    userInput = event["message"]["text"]

    client = boto3.client('lex-runtime')

    response = client.post_text(
        botName=responderName,
        botAlias=responderName,
        userId=userId,
        sessionAttributes={
        },
        requestAttributes={
        },
        inputText= userInput
    )

This is my sample test input:

{
  "DestinationBot": "SupportBot_BookCab",
  "RecipientID": "12345",
  "message": {
      "text": "book me a cab"
  }
}

Solution

  • The userID of PostText is the way you persist the conversation back and forth between the user and Lex. It can be anything that you can identify the user by in their incoming request that is consistent and unique to them, at least for that session.

    From AWS PostText Docs:

    userID
    The ID of the client application user. Amazon Lex uses this to identify a user's conversation with your bot. At runtime, each request must contain the userID field.
    ...
    Length Constraints: Minimum length of 2. Maximum length of 100.
    Pattern: [0-9a-zA-Z._:-]+

    So if a user is using Facebook messenger, they will have a Facebook ID that is passed with their messages and you can use that as their userID.
    If a user is using Twilio-SMS, they will have a phone number passed with their messages and you can use that as their userID.

    Your code is currently taking event["RecipientID"] and using that as a userID. But the RecipientID from an incoming message is yourself, the receiver of the incoming message.

    Your error is telling you that

    ... User: arn:aws:sts::XXXXXXXXXX:assumed-role/lambda_basic_execution/OrchestratorAPIApp

    So the userID = event["RecipientID"] = 'arn:aws:sts::XXXXXXXX:assumed-role/lambda_basic_execution/OrchestratorAPIApp'

    You definitely don't want the Recipient ID to be used.

    Instead you want the sender's ID to be the userID. Something like:

    userId = event["SenderID"]

    That might not be the exact code you use, its just an example. You should be able to view the incoming request, and locate something in there to use as a proper userID as I explained above with Facebook and Twilio.