AWS Custom / Lambda Authorizer

A Custom authorizer (also known as a Lambda authorizer) is an AWS API Gateway feature that uses a Lambda function to control access to your API. With Custom authorizer we can implement a custom authorization scheme that uses a bearer token authentication strategy such as OAuth or SAML, or that uses request parameters to determine the caller's identity.

When a client makes a request to one of our API's methods, API Gateway calls our Lambda authorizer, which takes the caller's identity as input and returns an IAM policy as output.


Types of Lambda Authorizer:

There are two types of Lambda autorizers
  1.  Token-based: Token-based authorizer receives the caller's identity in bearer token such as JWT token or oAuth token2
  2. Request-based: Request-parameter-based authorizer receives the caller's identity in combination of headers, query string params, stage variables and $context variables.


Lambda Authorization workflow for API gateway

  1. Client calls the API Gateway method with bearer token
  2. API gateway checks the method configured and Lambda authorizers. If yes, gateway calls the lambda function
  3. Lambda function authenticates the caller
  4. If the call succeeds, the Lambda function grants access by returning an output object containing at least an IAM policy and a principal identifier.
  5. API Gateway evaluates the policy.
    1. If access is denied, API Gateway returns a suitable HTTP status code, such as 403 ACCESS_DENIED.
    2. If access is allowed, API Gateway executes the method. If caching is enabled in the authorizer settings, API Gateway also caches the policy so that the Lambda authorizer function doesn't need to be invoked again. 


Steps to Create Lambda Authorizer

1) Create a lambda authorizer function


You need to first create the lambda function in AWS Console or in your local. In this tutorial I am used a .net core lambda function created in Visual studio. 
Note: You should have AWS Toolkit for visual studio to be installed to create AWS lambda in visual studio.
For creating a lambda function in Visual Studio
  1. Click on File -> New -> Project
  2. Choose "AWS Lambda" under "Visual C#" section and select "AWS Lambda Project(.Net core - C#)" template
  3. Select Empty Lambda template. It will create a skeleton as below
    namespace AWSLambda1
    {
     public class Function
     {
      public string FunctionHandler(string input, ILambdaContext context)
      {
       return input?.ToUpper();
      }
     }
    }
    
  4. Add Amazon.Lambda.APIGatewayEvents nuget package to the project
  5. Following is my code for a request based authorizer. It will read the accountid provider in the method url path and x-api-key from headers and validate those two. So modify the above function as below
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Amazon.Lambda.APIGatewayEvents;
    using Amazon.Lambda.Core;
    
    // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
    [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
    
    namespace AWSLambda1
    {
     public class Function
     {
      
      public async Task FunctionHandler(APIGatewayCustomAuthorizerRequest request, ILambdaContext context)
      {
       var authorized = false;
       int accountId = -1;
       string authToken = string.Empty;
       try
       {
        // Parse the accountId for the parameter values
        if (!string.IsNullOrEmpty(request.PathParameters["accountId"]))
         accountId = int.Parse(request.PathParameters["accountId"]);
    
        // Parse the api key from headers
        if (!string.IsNullOrEmpty(request.Headers["x-api-key"]))
         authToken = request.Headers["x-api-key"];
    
        if (accountId != -1 && !string.IsNullOrWhiteSpace(authToken))
        {
         authorized = (accountId == 1 && authToken == "xxxx-xxxx-xxxx-xxxx") ? true : false;
        }
       }
       catch (Exception ex)
       {
        context.Logger.Log(ex.Message);
       }
       return CreateResponse(request.MethodArn, authorized);
      }
    
      /// 
      /// Create policy and returns the Authorizer response
      /// 
      /// Method Arn
      /// If it is true, it will retun Allow policy otherwise return Deny policy
      /// 
      private static APIGatewayCustomAuthorizerResponse CreateResponse(string methodArn, bool authorized)
      {
       APIGatewayCustomAuthorizerPolicy policy = new APIGatewayCustomAuthorizerPolicy
       {
        Version = "2012-10-17",
        Statement = new List()
       };
    
       policy.Statement.Add(new APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement
       {
        Action = new HashSet(new string[] { "execute-api:Invoke" }),
        Effect = authorized ? "Allow" : "Deny",
        Resource = new HashSet(new string[] { methodArn })
    
       });
    
       APIGatewayCustomAuthorizerContextOutput contextOutput = new APIGatewayCustomAuthorizerContextOutput
       {
        ["User"] = "User",
        ["Path"] = methodArn
       };
    
       return new APIGatewayCustomAuthorizerResponse
       {
        PrincipalID = "User",
        Context = contextOutput,
        PolicyDocument = policy
       };
      }
     }
    }
    
  6. Create a package file with the following command in command prompt in the project folder
    dotnet-lambda package -c Release -o LambdaAuthorizer.zip -f netcoreapp2.1
    
  7. Login to AWS Console
  8. Create a .NET Core Lambda function by uploading the above package and save it.

2) Configure the Lambda function as an API Gateway authorizer

We need to configure the lambda function we created in step 1 in API gateway to use it as a authorizer. 
  1. In AWS Console, go to API gateway and choose your api from the list
  2. Goto Authorizers and Click "Create New Authorizer"
  3. Enter a name for the authorizer.
  4. Choose Type as Lambda.
  5. For Lambda Function, choose the region where you created your Lambda authorizer function and choose the function name from the dropdown list.
  6. Leave Lambda Invoke Role blank.
  7. For Lambda Event Payload, choose Request.
  8. Under Identity Sources, add a Header named "x-api-key"
  9. Choose Authorization Cache if required. 
  10. Click on "Create"
This will create new authorizer in your API Gateway. Now navigate to a api method for which you want to add authorization in the api gateway, Open "Method Request" -> Settings -> Select Your authorizer in Authorization dropdown

3) Test your API

Now test your api from Postman by passing the token in "x-api-keytest" header to the method

Happy Coding 😊!

Reference: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html#api-gateway-lambda-authorizer-lambda-function-create

Gopikrishna

    Blogger Comment
    Facebook Comment

0 comments:

Post a Comment