0

At the moment I have an architecture in mind with AWS ApiGateway + Lambda for server HTML based on if a user is properly authenticated or not. I am trying to achieve this Cognito and a custom Lambda Authorizer. I'd like my Lambda to always return HTML and based on the cookie that is passed, generate HTML for a logged in / logged out state. In my mind that would be ideal to have a separate authorizer that does the token validation and pass a header to the HTML generating Lambda.

How can one achieve this?

I'm using AWS Sam template to define my CF stack. See my current template:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: A Lambda function for rendering HTML pages with authentication
Resources:
  WebAppGenerator:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: app.handler
      Runtime: nodejs12.x
      CodeUri: .
      Description: A Lambda that generates HTML pages dynamically
      MemorySize: 128
      Timeout: 20
      Events:
        ProxyRoute:
          Type: Api
          Properties:
            RestApiId: !Ref WebAppApi
            Path: /{proxy+}
            Method: GET
  WebAppApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        DefaultAuthorizer: WebTokenAuthorizer
        Authorizers:
          WebTokenAuthorizer:
            FunctionArn: !GetAtt WebAppTokenAuthorizer.Arn
  WebAppTokenAuthorizer:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Handler: authorizer.handler
      Runtime: nodejs12.x

In my authorizer (Typescript) I was thinking of generating a policy that always has an 'allow' effect. But if an authorization token (not cookie-based yet) is missing, it's already returning a 403. See:


function generatePolicy(principalId: string, isAuthorized: boolean, resource): APIGatewayAuthorizerResult {
    const result: APIGatewayAuthorizerResult = {
        principalId,
        policyDocument: {
            Version: '2012-10-17',
            Statement: []
        }
    };

    if (resource) {
        result.policyDocument.Statement[0] = {
            Action: 'execute-api:Invoke',
            Effect: 'Allow',
            Resource: resource
        };
    }

    result.context = {
        isAuthorized
    };

    return result
}
nicoes
  • 83
  • 1
  • 8

2 Answers2

0

With Custom Authorizer, I'm not sure whether the functionality you mentioned is directly possible to achieve.

Can you check whether you can define a mapping template with content type text/html, following this guide? (Make sure your Lambda integration is not a proxy integration)

However, there are two alternative approaches that would work, if it's an option to you.

  • Use AWS Cloudfront, infront of API Gateway and configure error responses to show a HTML based on error status code.
  • Use Lambda Layers to authorize and decide on the response.
Ashan
  • 18,898
  • 4
  • 47
  • 67
  • Hi Ashan, thanks for looking into this! A connection pointed me to trying pointing the FunctionPayloadType to REQUEST Where TOKEN is the default. In combination with setting the Identity Header to Cookie it looks like the right direction. I'll post an update if it works. This provides more info: https://stackoverflow.com/questions/38596366/how-to-access-http-headers-in-custom-authorizer-aws-lambda-function – nicoes May 13 '20 at 08:57
0

You cannot change the headers directly in the Authorizer Lambda... I achieved this using a Middleware in the lambdas and catching the "After" event...

You can check a popular middleware for lambdas: Middy

Ari Waisberg
  • 1,186
  • 1
  • 12
  • 23