how do i get inbound caller id info from aws connect and lex in my lambda function - amazon-web-services

I have connect and lex up and running and can customize my lex chatbot via a lambda that checks the incoming phone number.
I would like to use caller id info to look up customer info for the lambda to use.
How do i get the inbound caller id info ?
Thanks

Use Contact Attributes
Contact attributes let you store customer input or data about a customer, and then use it later in a contact flow.
Contact attributes let you pass data between Amazon Connect and other services, such as Amazon Lex and AWS Lambda. Contact attributes can be both set and consumed by each service. For example, you could use a Lambda function to look up customer information, such as their name or order number, and use contact attributes to store the values returned to Amazon Connect. You could then reference those attributes to include the customer's name in messages using text to speech, or store their order number so they do not have to enter it again.
How to set Contact Attributes
To set a contact attribute with a Set contact attributes block
In Amazon Connect, choose Routing, Contact flows.
Select an existing contact flow, or create a new one.
Add a Set contact attributes block.
Edit the Set contact attributes block, and choose Use text.
For the Destination key, provide a name for the attribute, such as Company. This is the value you use for the Attribute field when using or referencing attributes in other blocks. For the Value, use your company name.
You can also choose to use an existing attribute as the basis for creating the new attribute.
What customer data can you get from System Attributes?
Customer number
Dialed number
Customer callback number
Stored customer input
...and more

For anyone in the future having difficulty.
In Amazon Connect, you can pass contact attributes (Inbound Caller ID) from inside the customer input block where the Lex Bot exists to the Lambda that the bot calls.
Open up the Get customer input block where your Lex Bot gets the user's input and add in a session attribute.
Set the Destination Key to any name ( I set mine to InboundCallerID).
Set Type to System.
Set Attribute to Customer Number.
Now you can access the customer number via the event variable from inside your lambda.
Example:
def lambda_handler(event, context):
phone_number = event['sessionState']['sessionAttributes']['InboundCallerID']

Related

Should I store failed login attempts in AWS Cognito or Dynamo DB?

I have a requirement to build a basic "3 failed login attempts and your account gets locked" functionality. The project uses AWS Cognito for Authentication, and the Cognito PreAuth and PostAuth triggers to run a Lambda function look like they will help here.
So the basic flow is to increment a counter in the PreAuth lambda, check it and block login there, or reset the counter in the PostAuth lambda (so successful logins dont end up locking the user out). Essentially it boils down to:
PreAuth Lambda
if failed-login-count > LIMIT:
block login
else:
increment failed-login-count
PostAuth Lambda
reset failed-login-count to zero
Now at the moment I am using a dedicated DynamoDB table to store the failed-login-count for a given user. This seems to work fine for now.
Then I figured it'd be neater to use a custom attribute in Cognito (using CognitoIdentityServiceProvider.adminUpdateUserAttributes) so I could throw away the DynamoDB table.
However reading https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-dg.pdf the section titled "Configuring User Pool Attributes" states:
Attributes are pieces of information that help you identify individual users, such as name, email, and phone number. Not all information about your users should be stored in attributes. For example, user data that changes frequently, such as usage statistics or game scores, should be kept in a separate data store, such as Amazon Cognito Sync or Amazon DynamoDB.
Given that the counter will change on every single login attempt, the docs would seem to indicate I shouldn't do this...
But can anyone tell me why? Or if there would be some negative consequence of doing so?
As far as I can see, Cognito billing is purely based on storage (i.e. number of users), and not operations, whereas Dynamo charges for read/write/storage.
Could it simply be AWS not wanting people to abuse Cognito as a storage mechanism? Or am I being daft?
We are dealing with similar problem and main reason why we have decided to store extra attributes in DB is that Cognito has quotas for all the actions and "AdminUpdateUserAttributes" is limited to 25 per second.
More information here:
https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html
So if you have a pool with 100k or more it can create a bottle neck if wanted to update a Cognito user records with every login etc.
Cognito UserAttributes are meant to store information about the users. This information can then be read from the client using the AWS Cognito SDK, or just by decoding the idToken on the client-side. Every custom attribute you add will be visible on the client-side.
Another downside of custom attributes is that:
You only have 25 values to set
They cannot be removed or changed once added to the user pool.
I have personally used custom attributes and the interface to manipulate them is not excellent. But that is just a personal thought.
If you want to store this information, and not depend on DynamoDB, you can use Amazon Cognito Sync. Besides the service, it offers a client with great features that you can incorporate to your app.
AWS DynamoDb appears to be your best option, it is commonly used for such use cases. Some of the benefits of using it:
You can store separate record for each login attempt with as much info as you want such as ip address, location, user-agent etc. You can also add datetime that can be used by pre-auth Lambda to query by time range for example failed attempt within last 30 minutes
You don't need to manage table because you can set TTL for DynamoDb record so that record will be deleted automatically after specified time.
You can also archive items in S3

AWS AppSync Subscription Arguments

What can the arguments on an AppSync GraphQL subscription be used for? According to the real-time data page on the docs:
An important part of using GraphQL subscriptions is understanding when and how to use arguments, as subtle changes will allow you to modify how and when clients are notified of mutations that have occured.
(...)
In the default sample, clients can subscribe to Comments when a specific eventId argument is passed through
I can't find any way to access the subscription arguments, though. I have different 'channels' of comments that I'd like users to be able to subscribe to individually, optionally with a password. The subscription I've set up responds to comments in all channels instead.
Is there any way to 'filter' the data coming through the subscription with a mapping template or similar? If not, what's the intended use of the subscription arguments? Must the filtering be done client side?
The name of the argument is expected to be the same as the name of the field in the mutation response that triggered the event. If your mutation returns a value of type "Post" that contains a field "title" then passing an argument named "title" to the subscription that is subscribed to that mutation will only get pushed values where the "title" passed to the subscription equals the value of field named "title" returned by the mutation.
The arguments control what data clients will get subscription notifications from. For example if you put in an argument via the schema which is required by using the bang (!) symbol then clients can only subscribe to data on a specific mutation for that parameter.
GraphQL arguments, including those passed in a subscription, should be available via $ctx.args in your resolver (this is shorthand for $context.arguments). For example if you have a query of getThing(name:"XYZ") then you can access in your resolver with $ctx.args.name.
For your use case I would suggest using arguments along with a resolver on the subscription so that users can only subscribe to a channel by that argument, if they match some authorization criteria, such as the password or looking at the logged in user. You can find an example of this here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#real-time-data

How to store chat-conversation of chatbot(in aws lex) in DynamoDB

I am building a chatbot for a website that has lots of traffic
I decided to build chatbot in AWS lex
I want to save all chat conversation an single attribute in Dynamo DB for that I had chosen list data type for that attribute
and I am able to get all the slot data into different variables but how to save user entered utterance and prompts that we defined in lex console and how to arrange them like a conversation.
If is there any alternative for storing chat conversation?
Since it's your bot, you know the session timeout value. In your lambda function you can generate a session id (random UUID) and put that in session attribute (read more here). You can create a DDB table in your account and design it like this:
Hash Key: userId
Range Key: sessionId#timeStamp
Request (String attribute): JSON format of request structure that is sent to Lambda function
Now as long as the session is valid you can always retrieve the sessionId that you put in session attributes map. Using this you will always be able to create the range key (sessionId + "#" + currentTimeStamp). In every call that you get in your lambda you also get the user-id for your bot. You can all this information to store the utterances the way you might like.

Can you stop Alexa Skill session programmatically in lambda function?

Is it possible to stop a session from inside aws-lambda code if you run lambda seperately from skill.
I am trying to run aws-lambda function from SNS to stop skill session.
From what I've ready my interpretation is that you're interested in ending the session on your Amazon echo by sending an SNS message to an unrelated lambda function. If that is correct this is how I would proceed.
I have not tried this but having extensive experience with Amazon Alexa Skills in Node.js I would say this might be accomplished in a programmatic way as follows:
1) Enable a dynamodb table within your alexa app. (as seen in line 4)
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.appId = `YOUR_ALEXA_SKILL_ID`;
alexa.dynamoDBTableName = 'NAME_OF_YOUR_DYNAMODB_TABLE'; //You literally dont need any other code it just does the saving and loading??!! WHAT?
alexa.registerHandlers(newSessionHandlers, newGameYesNoHandlers);
alexa.execute();
};
Alexa will then create a single datatable row for each unique user. Note you'll need to set up an IAm permission to allow lambda to access this data table.
2) When your session starts have it update a value in it's own data table row so that this.attributes['EXECUTING'] = True;
3) During each consecutive intent call within the session check the value of this.attributes['EXECUTING] if the value is True, Great, if it is False end the session by emitting this.emit(':tell', "Goodbye!");
4) Now, the data table rows are indexed by userId. This will be the tricky part that I have not personally tried. I suggest creating an intent where the user ask for their userId, then emit a card with the id value on it. This could then be copied into your own SMS lambda function or some other api. Alternatively amazon has recently released documentation on how to connect alexa users to your own API's.
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system
It really depends on what you're hoping the final product will look like.
5) Finally, use your external api or alternate lambda function along with the users userId to access the same dynamodb table and alter the value of ['EXECUTING'] to False. The next intent that is run will then check the database and cause the skill to exit.
Voila!
For more on specific code, account linking, and sms please ask additional questions. Thanks

ColdFusion Office 365 Exchange distribution group access?

I am currently using cfexchangeConnection in order to connect to our outlook.office365.com connection.
My goal is to connect a user, find out what distribution group they are in (e.g., Staff, Members, Clerks, ...), and then send them to the appropriate web page, depending on their group.
I've looked at and played around with cfexchangeContact, but the best I could come up with is a list of that person's contacts.
We have a 'global' address book throughout our company, but I have no idea how to access it.
Edit:
The code I use to contact Exchange is as follows:
<cfexchangeConnection action="open"
username ="#username#"
password="#password#"
server="outlook.office365.com"
protocol="https"
connection="myConnection"
serverversion="2010">
I used the following code to try get access to the distribution groups, through the global address book with this code:
<cfexchangecontact required action = "get"
name = "query identifier"
optional connection = "connection ID">
Alas, this only gets me the contacts, not the address book.
What I would like to get as a result, is whether the person who authenticated through the cfexchangeConnection tag, is a member of one of our distribution groups/global address book group. So far I am thinking of adding another Exchange member, adding the distribution group as a contact, and then using the cfexchangeContact tag to see whether they are in the contact list of this new Exchange member.