All my users need to be registered and I don’t allow unauthenticated user; therefore, I can’t escape the cost for using user pool.
The API Gateway custom authorizer such looks like a cleaner way to do my app authorization check. But doing a quick cost calculation, it’s still more expensive than if I can do it in my Lambda function or even use Step Function. Again, out of topic, sorry, but I’m thinking a couple of ways to do it without API Gateway:
-
Do a Pre-Token Generation trigger in Cognito to check and add in addition claims pertaining to the user’s authorization against my custom rules (stored in dynamodb). My lambda function will then look at the claims and decide if the user can execute or not in the app logic
-
My Lambda function will check the user’s authorization against my custom rules and decide if the user can execute or not in the app logic.
Have you considered these 2 methods back then? Nonetheless, I’m stuck at both methods. I could hardly find any sample in writing Pre-Token Generation lambda in .net/java. And in the Lambda context, it only has the user’s CognitoID, and with the CognitoID, I can’t link it to the user in my UserPool. You know of a way?
I’m thinking of passing the jwt token as an parameter into my function, but not sure how secure it is. With API Gateway, I could use HTTPS to have it encrypted on the network layer. But with lambda direct invoke, can it be spoofed easily?
That pre-token call only works on User Pools, not Federation Pool. User Pools have JWT tokens, Federation Pools have opaque AWS specific tokens.
Another solution that I have not tried is to use multiple Federation Pools, one for each authorization level.
If you are using the User Pools with different groups like admin, when you get into to lambda you can look in the environment and see which execution role it picked. You don’t need to reverse map the CognitoID back to the pool. Each user type (like groups) can be assigned a custom execution role. That will allow you to identify the user type.
this may help… https://github.com/aws-amplify/amplify-js/issues/1022
@jonsmirl I understand how you call Lambda directly, and am trying to simulate the same approach. I have the correct policies attached to my cognito authenticated role, and have set up lambda as an endpoint with amplify as follows:
Amplify.configure({
Auth: {
identityPoolId: config.IdentityPoolId,
region: ‘us-east-1’,
userPoolId: config.UserPoolId,
userPoolWebClientId: config.UserPoolClientId,
},
API: {
endpoints: [
{
name: ‘api’,
endpoint: ‘https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/functionNameHere/invocations’,
service: ‘lambda’,
region: ‘us-east-1’
},
],
},
});
However when I try to invoke the lambda function via a API.get request, I get a 403, leading me to believe I must be calling it incorrectly. How do you call the lambda function directly? I use this:
var options = {
‘headers’ : {
Authorization: auth_session.idToken.jwtToken
}
}
API.get(‘api’, ‘’, options)
Do you know where I am going wrong? I cannot find any other documentation on this exact situation online and any help would be greatly appreciated. Thanks so much for your time.
Hi Jonsmirl
I answer you in just 3 words: Secure by Design
Best,
This is very interesting topic. It shows how many things could be done differently comparing to the old non-serveress approach.
I believe the best way would be to mix those approaches. Depends on the use case, you might move the most expensive pipelines out of API Gateway/AppSync and have direct calls to Lambda/DynamoDB/Kinesis/SQS etc. IAM policy will do exactly the same job as it does in case of using API Gateway/AppSync and in general it will reduce the costs and latency.
However it has some downsides, as some other people noticed. It makes the interfaces less flexible in case of changes and it might be also more complicated. But as always, it depends on the case. Sometimes it might be worth it to choose “apiless” approach, to have huge costs/latency optimizations.
The biggest reason why you want to expose your services through API gateway rather than Lambda is because you can expose your service as a REST service. You are
A) following industry standard practices
B) tomorrow, if you decide that lambda doesn’t fit your needs, and you need to, say implement your service in ECS, you can easily switch without changing your front end code
C) you can have regional end points, and use route 53 to redirect traffic to regional end points, whereas with regional lambdas, you will need to bake in regional redirection in your application code.
D) if you want to go multicloud, it will be easier if every cloud exposes a REST endpoint with the same signature
Front end calling REST services is part of standard internet design. Stick to it.