Authenticate the caller to a lambda function - aws-lambda

I have a web app.
The login process is done with cognito (AWS javascript SDK) in the client side.
This works fine. The user can register, login and edit his attributes in cognito.
I have a Lambda function.
The Lambda function is triggered via an API gateway.
The question:
What is the best practice for authenticating the calling user in Lambda?
What do I need to pass in my HTTP request? Is it the accessToken from the client?

You pass that in the header
Authorization: Bearer {yourtoken}
{yourtoken} is the idToken in AuthenticationResult when you request CognitoIdentityServiceProvider
If you want the caller in your lambda function you can pass it to your lambda function with $context.authorizer.claims.email in API Gateway request template

Related

Make request to Lambda Function URL with access token as Authorization header

I've been dealing with this for a while. I want to call an AWS_IAM authenticated Lambda Function URL sending an access token (generated by Cognito User pool) as the Authorization header.
I know I can send access token as a request header for API Gateway HTTP or REST API, but I'm not sure if it works for Lambda Functions too.
I couldn't find any documentation about my problem, just this other about Signature V4 authentication method to invoke Lambda Functions URL: https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html
The Security and auth model for Lambda function URLs has two AuthType options:
AWS_IAM – Lambda uses AWS IAM to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy.
NONE – Lambda doesn't perform any authentication before invoking your function.
The Cognito JWT-based access token is not an AWS IAM session token, so cannot sign the request using SigV4. You have a different option for each of the Lambda function URL AuthType options.
To use AWS_IAM, you can use Amazon Cognito identity pools to deliver temporary, limited-privilege credentials which can SigV4 sign the request.
To use NONE, you will need to verify the JSON web token yourself, preferably with a software framework (such as AWS JWT Verify).

Can AWS LAMBDA Web API authenticate by middleware if you send jwt token in the header

I have a .net core 3.1 web api authenticated by jwt in the middle ware pipline.Works fine. I converted the web api to a lambda web api by adding a aws Lambda entry class and published into aws with an API Gateway in front
All the endpoints without Authorization attribute worked fine.
All the endpoints with Authorization attribute gets 401.
All request has a jwt Authorization Bearer token header
One endpoint without Authorization attribute reponses with all the headers converted to a string.From that i can see the request's jwt is getting thru to the endpoint.
1.Why isnt the endpoint giving me 401 even tho there is a token?
2.Does AWS lambda or the API getway not pass the header direstly?
3.Do I need to configure the api geteway to send the header to the lamdbda endpoint?
4.Can Lambda authenticate by pipline like a normal web api?
Another solution was to use authorization Lambda with the API GETWAY.
If I use authorization Lambda does that mean my end point wont need the authorization attriibutes any more because it done in the getway?
JWT is generated and authenticated by Firebase.
It works I finally figured the reason. Its so awesome you can have Web api as a Lambda in aws. I can now spend less money in AWS.

AWS Cognito Pre-Token Generation not adding custom claims to ID Token (with ALB setup + Auth Code flow)

I'm adding custom claims to Cognito's ID token using the "Pre Token Generation" trigger.
Problem
The lambda is triggered, but the issued ID Token doesn't include the claims I added. Am I missing something?
My setup
Using OAuth 2.0 with authorization code flow
My client app sits behind a load balancer (alb). The alb interacts with Cognito to get the Access + ID Tokens in the form of a ALBSessionCookie. Very similar to [0]
To get the ID Token, the client calls a custom endpoint to my backend with the ALBSessionCookie. The backend uses that cookie to return a decoded ID Token to the user. This is the ID Token that I expect should have the custom claims included.
[0] https://www.exampleloadbalancer.com/auth_detail.html
Lambda function (pre-token generation trigger)
Format taken from https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html#aws-lambda-triggers-pre-token-generation-example-1
exports.handler = (event, context, callback) => {
event.response = {
"claimsOverrideDetails": {
"claimsToAddOrOverride": {
"my-custom-claims-namespace": JSON.stringify({
"custom-claim-1": "hello",
"custom-claim-2": "hello",
})
}
}
}
callback(null, event)
}
If I can't make this work with ALB, what are some workarounds? Some ideas:
Call Cognito directly for an ID Token (somehow), hoping that will trigger the lambda to issue a JWT with the custom claims
Call Cognito via AmplifyJS
I have a feeling this is expected behavior, though seems like a limitation. Looking here:
https://www.exampleloadbalancer.com/auth_detail.html
We can see that the following steps occur:
ALB receives JWT (ID token, Access Token)
ALB to send access token
ALB receives user info(claims)
I believe the ALB is then not sending the contents of the Decoded ID token (That were manipulated by the Lambda trigger) back to the backend but instead sends the 'user info(claims)' (returned from the UserInfo endpoint) which are not effected by the Cognito trigger.
Yeah the ALB doesn't work that way, the ID Token that Lambda trigger customizes is the one you get when a user Authenticates. There are a couple of options.
Custom User Attributes
The least invasive IMO if instead of adding these attributes in the Lambda trigger, you could have them as custom attributes in Cognito, these I do believe will be in this token. You can sync these attributes at each successful Authorization. That may meet your requirements.
API GW
You could put an API GW either between your LB and your APP or infront of your LB. The API GW does give you a layer in which you can do all this stuff and more with customizing headers, tokens etc. For example you could have a Lambda Authorizer which reads this access token, and returns a context which you can reference in your integration requests back to your backend. It's a bit more involved and will add at least some latency to your app, although you can safely have a large TTL on your auth response because your LB is already doing Auth and you only want some extra attributes. You could also do a re-design and put this all in API GW and get all the bells and whistles it has but you might not need them.
But yeah probably easiest to use the first option if possible as that won't require you to do a redesign and you will just need to change your attribute names to custom:....

request "Unauthorized" when using Cognito User Pool Authorizer

Similar questions have been asked here and other places, but I'm stuck...
I have a user pool set up as the authorizer for my REST API and the method, which point to a Lambda function (proxy integration). I can go through the sign-in process but I get 401 Unauthorized -- without it hitting the Lambda at all (no logs appear for the lambda function, and the API Gateway logs just show that it was an unauthorized request). I see the id_token in the URL -- but it's not sent as the Authorization header. If I take that id_token and use Postman to run the request with that in the Authorization header, it works.
I'm sure I'm missing some kind of configuration that would send those parameters in headers instead of in the URL, but I can't find it.
fwiw, I'm just serving up static HTML pages from the endpoint in question...
I've set the app client to accept either Google or the Cognito User Pool user auth. Same results.

How to store session in AWS lambda

I have a AWS Lambda function which need to talk to an external API to validate the user using bearer token pass in API request header.
Now I want to store that token in session, so I don't want to call external API every time when user send request again with that token.
So which is a best way to do it with AWS lambda.
Thanks
If this request is coming through API Gateway you should look at using a Customer Authorizer. Rather than storing the token in a session, since Lambda APIs are meant to be stateless, you should validate the token in a Custom Authorizer using the necessary keys. The key(s) would typically be set in an environment variable so you can easily access it and validate the token.
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

Resources