AWS Cognito Integration with Twilio through API Gateway - amazon-web-services

I currently have a Lex chatbot that I would like to integrate with both Twilio and Cognito (in the sense that only Cognito authenticated users will be able to communicate with Twilio and the lex bot).
To this end, I've created an API Gateway that handles Twilio requests and pushes them to a Lambda function that interacts with Lex. I've also added a Cognito authorizer to my API Gateway that blocks users from interacting with Twilio if they are unauthenticated.
I don't currently have a back end app (long story), so for now users login to a Cognito-hosted UI that redirects to Google's homepage.
The problem? I haven't yet found a way to connect the authentication credentials given out at a user's Cognito log-in (which occurs on a web browser) to the API Gateway that communicates with Twilio (since Twilio is making the initial API calls). Currently there is no such connection, so all communication with Twilio (and therefore the lexbot) is blocked. I can't push the relevant tokens to Twilio when it makes the API call.
I have two feelings:
The issue probably comes from the fact that there is no connection between the web-based login and the text messages the end user sends to Twilio to kick-off the whole process
It seems like I will have to use a Custom Lambda Function Authorizer (I'd like to avoid this, if possible)
If it helps, I used this tutorial as a starting point.
Any ideas?
Any and all help or suggestions would be greatly appreciated!

Twilio developer evangelist here.
The HTTP requests that Twilio makes to the API gateway are completely disconnected from your user in a browser. About the best thing you can do to exclude users that haven't signed in is to somehow store their phone number within AWS somewhere and, like you said, use a custom authorizer to check the From phone number on the incoming webhook matches one of your users.

Related

Authenticate an iframe using AWS

currently, we are deploying 2 APIs on AWS (using API Gateway and Lamda ):
the 2 APIs share very similar endpoints but with different authentication/authorization mechanisms
1st API uses OAuth 2.0 client credentials (it's used for server-to-server communication ).
it uses a user pool and different scopes to authenticate the server to each lambda
2nd API uses the same endpoints as the 1st API but it's using a different authentication approach ( aws_iam on the back) and amplify on the frontend - its a client-to-server communication and requires the user to sign on the client before being able to make any API request
currently, we are looking to deploy an iframe that is able to access the same endpoints that the 2 APIs are providing.
so I hope if you can recommend the best authentication/authorization approach for our use case:
oauth 2.0 client credentials is a server-to-server approach ..so i believe it doesn't fit our iframe(client) to server approach
using the 2nd approach ( aws-iam ).. but the user requires to log in before accessing the API and we won't be able to hardcode user login info in the iframe
3rd approach which is the possible solution: the server generates a JWT on the backend and returns it in the iframe ( using jwt library ).. the iframe is now authenticated and can do API calls to the endpoints directly which are using custom lambda auth as their authorizer... the custom lambda auth verify the token .. send proper policy and forward the request to the requested endpoint
any feedback on the points mentioned above? I'm not sure if auth mechanism can be done in a better way .. or if the way I'm proposing is the way to go?
Thank you

What is the best way to authorize an AWS API call for a logged in user?

I have a spring boot based web application which already authenticates the user. I would like to create some AWS APIs using AWS api gateway and a springboot rest app deployed on EC2. The user will log into the existing application and call the new AWS APIs from the browser ajax calls (like an SPA I guess but I have a server and can use client credentials/secrets if needed). What is the best way to handle security for the APIs. My first thought was to generate a JWT using a shared server side secret for hash and verify it with an AWS lambda. But this seems a bit non standard. Oauth2 might be better but might also be over kill. Not sure the performance would be good. Few requirements
token passed to the API should be a user specific token and have an expiration (and hence a refresh token)
The user is already logged into my web app and calling the api should not issue a login challenge.
AWS API Gateway should be able to verify the token before passing it to the application
Any token passed to the API should probably be generated on the logged in web application. Server knows the user is authenticated and should generate the user access token on behalf of the user. The AWS api should be able to figure out what privileges the user has based on the user principle or scopes in the token
I've thought about using Cognito AWS but I dont want to require the users to preexist in a user pool. Cognito seems geared more for the authentication rather than authorization and I would not be using the cognito login functionality. I dont know if its possible to use the oauth2/token endpoint alone with cognito.

Authenticate session with AWS API Gateway

Situation: I have an app (Next.js/React on Vercel) running on example.com. I have an api (AWS API Gateway) on api.example.com. Currently the application on example.com supports login using Auth0 as authentication provider.
Problem: I would like to be able to make authenticated requests from the application (example.com) to the api (api.example.com).
Architecturally, I was hoping for a way for the API Gateway (api.example.com) to handle the authenticated session from the app/Auth0 cookie (example.com). I thought the browser could share the cookie (since api.example.com is trusted) and the API could validate it.
But I don't see a standard way to do it. I think I could try to create some custom lambda authorizer for AWS' API Gateway. But since we're dealing with authentication, I would prefer to outsource as much as humanly possible and avoid any custom code. I just can't seem to piece together the way for API Gateway to handle the sessions, which I assumed would be a pretty common problem to solve.
Sidenote: Previously, I used the pages/api that's baked into Next.js to directly call Lambdas on AWS and expose them. With this, authentication natively works. That's the experience I'm now trying to recreate, but without the user having to take a roundtrip.
When you want to protect APIs it’s better to use JWT tokens to carry over necessary claims e.g. id of authenticated user. OpenID connect and Oauth2.0 are the standards to look into.
Auth0 has documentation of recommended authentication flow: https://auth0.com/docs/flows/authorization-code-flow
as well as example with Api Gateway’s HTTP apis: https://auth0.com/blog/securing-aws-http-apis-with-jwt-authorizers/
AWS documentation has more info about Http Apis and JWT token authorizers: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html
If your Api gateway is using Rest apis instead of more light-way Http apis then token based Lambda authorizers are the right solution: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

How to prevent unauthorized access of an API created for Twilio webhook

I have to process all the inbound messages of a Twilio account using the AWS lambda function and forward it to another number. So, I have created a POST API using Amazon API Gateway and configured it on Twilio SMS webhook configurations. For any inbound SMS, Twilio is creating an event and calling the API. The API Gateway is calling the Lambda function in turn. It's all working fine.
But the problem is that Twilio only supports public APIs for webhook as far I know. So, I have to keep the API public. I am looking for some way to prevent unauthorized access.
I have looked into two approaches -
Whitelisting the Twilio IP ranges: This seems to be not possible, as Twilio's IP addresses are variable.
Validating Requests are coming from Twilio inside the Lambda function: Twilio documentation is also suggesting this approach - https://www.twilio.com/docs/usage/security. But with this, the Lambda function has to be executed every time, even for the invalid requests.
So, I am wondering if there is any other way to prevent unauthorized access without executing the Lambda function.
Twilio will sign all inbound requests to your application with an X-Twilio-Signature HTTP header.
Twilio uses the parameters sent in the webhook (either GET or POST) and the exact URL your application supplied to Twilio to create this signature. The signature uses the HMAC-SHA1 hashing algorithm with your Twilio account's auth token as the secret key.
Your application can verify that this signature is correct using the server-side Twilio SDKs (validateRequest method) or implementing your own validator (see this page). You will need your account's auth token, the value of the X-Twilio-Signature HTTP header Twilio passed to you, the URL Twilio sent the webhook to and all of the parameters sent by Twilio.

How to publish Amazon Lex Chatbot as webservice

I am able to create Amazon lex chat bot. I am also able to publish the same in Facebook messenger. Also I found sdk's for iOS and Android.
What I want is to publish lex bot as a webservice which can be called from any rest client, so that it can be integrated to any user interface with rest calls.
I heard of Javascript sdk's for publishing lex bots as service, but I am not able to find any proper documentation on this.
The lex-runtime is accessible from the Javascript SDKs. AWS documentation is here: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/LexRuntime.html
The trickiest part is authentication. The recommendation from Amazon is usually to route your Lex requests through a Lambda function in front of an API gateway. An alternative is to have a Cognito unauthenticated role that has permissions to call Lex and then have the clients call it directly.
The getting started guide may be of use if you are unfamiliar with calling AWS from the browser: http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-started-browser.html
You can use AWS API Gateway which will get the requests from your Rest Client and forward it to Lex.
Your architecture will be like:
Chat client <==> AWS API Gateway <==> AWS Lex
Check this link for details.