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

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).

Related

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.

Authenticate the caller to a lambda function

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

AWS Cognito: Add custom claim/attribute to JWT access token

My app creates a custom attribute "userType" for each new signed-up user. Now I would like this "userType" claim/attribute to be added to the JWT access token whenever the user signs in or the token gets refreshed.
Is there an option to tell cognito to add my custom claim/attribute to the JWT access token? (Without a pre token generation Lambda)
Custom attributes are not available in Cognito access token. Currently it is not possible to inject additional claims in Access Token using Pre Token Generation Lambda Trigger as well. PreToken Generation Lambda Trigger allows you to customize identity token(Id Token) claims only.
You can use ID token to get the token with custom attributes.
Access tokens are not intended to carry information about the user. They simply allow access to certain defined server resources.
You can pass an ID Token around different components of your client, and these components can use the ID Token to confirm that the user is authenticated and also to retrieve information about them.
How to retrieve Id token using amazon cognito identity js
cognitoUser.authenticateUser(authenticationDetails,{
onSuccess: function(result) {
var accessToken = result.getIdToken().getJwtToken();
console.log('accessToken is: ' + accessToken);
},
onFailure: function(err) {
alert(err.message || JSON.stringify(err));
},
});
I have the same problem when I want to create several microservice. There isn't a way I can customize an access token, but only an identity token. However, I use client credentials in the machine-to-machine which needs access token. So, in no way I can customize my token. At last, I decide to add such info(like user type) in the event header. It's not a very secure way compared to customize a token, but there isn't any other easy way to do it right now. Otherwise, I have to rewrite the authorizer in Cognito. Like rewriting a customize authorizer and it's very painful.
I have the same issue with Cognito; exist other tools like "PingFederate"Auth-server of Ping identity and Auth0 Auth-server; I know that the requirement isn't part of the standard, but these applications were my alternatives to fix this issue
The responses suggesting to use the ID Token for authorization in your backend systems are bad security practice. ID Tokens are for determining that the user is in fact logged in and the identity of that user. This is something that should be performed in your frontend. Access Tokens on the other hand are for determining that a request (to your backend) is authorized. ID Tokens do not have the same security controls against spoofing that Access Tokens have (see this blog from Auth0: https://auth0.com/blog/id-token-access-token-what-is-the-difference/).
Instead, I recommend that your backend accept an Access Token as a Bearer token via the Authorization HTTP header. Your backend then calls the corresponding /userinfo endpoint (see: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) on the authorization server that issued the Access Token, passing such said Access Token to that endpoint. This endpoint will return all of the ID Token information and claims, which you can then use to make authorization decisions in your code.

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

How to make AWS Cognito User Data available to Lambda via API Gateway, without an Authorizer?

I have a website that uses AWS Cognito (via Amplify) for user login. The API is on a separate stack that deploys with Serverless.
I am trying to have an API endpoint that can access the current logged-in user's Cognito User Pool data (username, email) if it is available. The only way I've been able to achieve this is by using a cognito user pool authorizer via API Gateway.
Example:
functions:
getMe:
handler: /endpoints/myService.get
events:
- http:
path: /myService
method: GET
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: ${self:custom.apiGatewayAuthorizerId.${self:custom.stage}}
Where authorizerId is set to the 6-character Authorizer ID found on the AWS Console's API Gateway Authorizers page. However, this blocks all traffic that is not authenticated with Cognito. That isn't what I want, since I have a number of services that should be accessible by both anonymous and logged-in users. I just want to personalize the data for users that are logged-in.
Is there any way to allow traffic and pass the cognito user parameters through the API Gateway to Lambda if they are available?
All resources I've been able to find regarding Cognito + API Gateway + Lambda are specifically about restricting access to endpoints and not layering on data to the requests...
Based on comments above you want Anonymous and Logged-in users pass through same gateway end point ?
You can still use the same setup but remove the authentication from API Gateway and take the logic in your application.
If users try to access your services while being logged in AWS amplify will send through the Authorization header with Id token to API Gateway and API Gateway will pass this header as it is to the application. You will have to check inside your application for this Authorization header and crack open Id token passed to find the user claims/attributes and do your logic. For any other user that doesn't have this token can be considered anonymous.
You still need to Validate the token if you find one in request to make sure it's a valid token and extract claims/Attributes thereafter.

Resources