Access Control to AWS resources using Lambda Authorizer Function

 


Hello there! In my previous blog I have discussed how to create a REST API endpoints for CRUD functionalities using Amazon API Gateway, AWS Lambda and Amazon DynamoDB, refer this page.

Lambda Authorizer

You may create REST API services for end customers but depending upon the use case you need to decide if those services will be available for public or only the authenticated and authorized customers can access them using special token or passphrase.

You can have these services processed API Gateway has a special feature that uses a Lambda function to control access to your API. This is known as Lambda authorizer. When a request is made to one of the API’s methods, API Gateway makes a call to the Lambda authorizer that token or parameters sent by the client as input and then returns an IAM policy as output that allows the user to access the API or block the access in case the authorization fails.

There are two types of Lambda authorizers:- Token based and Request Parameter based.

So how it works? Refer to the below image for understanding:

LAMBDA AUTH FUNCTION

If Authorization is enabled, to every request that comes to API Gateway, the token or parameters along with context will be sent to Lambda Auth Function to verify the request, on the basis of which an IAM Policy for Allow access or Deny access will be generated. If Authorization fails, Client will get a 403 response code from the API Gateway else it will be able to access the resources.

Implementation of Lambda Auth Function

Without Authorization, anyone with the endpoint can easily access the resources which is not desirable.

Let’s try to create a Lambda Authorizer function in Node.js with Basic authentication to safeguard the APIs. In case you want to use OAuth or JWT for authorization you can refer to these blueprints.

Create a Lambda function from AWS Console with basic lambda execution role -

Incase we have an username — user and password as pass@123. We will expect the below request header for an authenticated request as:

authorizationToken : <Base64Encoded version of user:pass@123> i.e.
authorizationToken : dXNlcjpwYXNzQDEyMw==

Attached the below code in the lambda:

exports.handler =  function(event, context, callback) {
var token = event.authorizationToken;
switch (token) {
case 'dXNlcjpwYXNzQDEyMw==':
callback(null, generatePolicy('user', 'Allow', event.methodArn));
break;
default:
callback(null, generatePolicy('user', 'Deny', event.methodArn));
break;
}
};
var generatePolicy = function(principalId, effect, resource) {
var authResponse = {};

authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17';
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke';
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}

After creation:

Now I will configure an event to check if my lambda is working fine or not.

You can see below that the event JSON generates IAM Policy with Allow Effect when correct auth token is used and generates Policy with Deny Effect for incorrect auth tokens.

Deny event testing with wrong auth token:

This function generates a policy like below where it Allows or Denies an Action to perform ‘execute-api:Invoke’ on resource ‘arn:aws:execute-api:us-east-2:123456789012:example/prod/POST/{proxy+}’

Response
{
"principalId": "user",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Deny"/"Allow",
"Resource": "arn:aws:execute-api:us-east-2:123456789012:example/prod/POST/{proxy+}"

}
]
}
}

As our function’s sanity is checked, now I will go ahead for integrating this function with API Gateway.

Now create an Authorizer in API Gateway console and attach the Auth Lambda Function and mention the header name — authorizationToken as Token Source.

Once you grant and create:

Now edit the Method Request of the API Gateway for /orders resource’s GET method and add the Token authorizer — OrdersAPIAuth:

Now once I deploy the API, I will test. Without any auth headers if I access I get the 401 unauthorized error code from API Gateway as I am not an authenticated user.

Now in order to get authenticated access, I will add the Base64 encoded credentials in Headers field as:

authorizationToken : dXNlcjpwYXNzQDEyMw==

Now when I try to access the API with header authorizationToken , the request first reaches to Lambda Authorizer, which validates the token and generates Policies with Allow or Deny effect in order to access the REST API endpoints.


Conclusion

Now, I believe that you have got the basic idea on how to secure your APIs over the internet and you will be able to do a bit of self study to implement JWT or OAuth for further security of APIs.

There is another way of securing APIs using API Keys, you can definitely study and implement that.

Sources and References:

https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html

https://docs.aws.amazon.com/apigateway/latest/developerguide/security.html

Comments

Popular posts from this blog

Kubernetes: A Synopsis and Introduction

Kubernetes : Pod Communications, Deployments and ReplicaSets

Handle errors in Amazon API Gateway from integrated Lambda functions