dherault / serverless-offline

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
5.2k stars 793 forks source link

httpApi custom authorizer does not work by the docs #1624

Closed dragonautdev closed 5 months ago

dragonautdev commented 1 year ago

Bug Report

Serverless doesn't allow for custom httpApi authorizers as shown in the documentation.

Current Behavior

  1. Create a simple project using the following serverless.yml definition as found here

  2. Run the project using serverless-offline.

  3. Get the following error as result:

The command throws the following error: Function "authorizerFunc" doesn't exist in this Service

Sample Code

```yml
provider:
  name: aws
  httpApi:
    authorizers:
      customAuthorizer:
        type: request
        functionName: authorizerFunc

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: get
          path: /hello
          authorizer:
            name: customAuthorizer

  authorizerFunc:
    handler: authorizer.handler

Expected behavior/code

The expected behavior is that serverless-offline runs the local instance normally.

Environment

Running "serverless" from node_modules
Framework Core: 3.25.0 (local) 3.25.0 (global)
Plugin: 6.2.2
SDK: 4.3.2
dnalborczyk commented 1 year ago

thank you for filing the issue @srodriki

I tried to reproduce with your provided serverless.yml above, but I'm getting Function "customAuthorizer" doesn't exist in this Service. that said, this error is being thrown by the serverless framework itself, not by serverless-offline. I just compared to the serverless docs, and it appears your example is the same. could it be that the documentation is incorrect? does your config deploy to AWS successfully?

dragonautdev commented 1 year ago

Hey @dnalborczyk thank you so much for looking into it. The problem also happens when deploying to AWS, that's why I filed the issue in the main repo, but got redirected here. This is the original issue.

Anyways, I'll take the discussion over there and reference this ticket.

Thank you so much!

dnalborczyk commented 1 year ago

no problem. I added some notes in the original issue.

closing this for housekeeping. if there's still an issue with serverless-offline we can re-open.

dnalborczyk commented 1 year ago

just deployed to AWS, which appears to work. it looks like an issue with serverless-offline .

ShadovvBeast commented 1 year ago

i'm also facing this issue, is it expected to be resolved soon?

gsavvidis96 commented 1 year ago

Hello. it seems that this configuration works when deploying to the cloud but not offline as I get the Function "auth" doesn't exist in this Service error.

service: techstack

frameworkVersion: "3"

provider:
  name: aws
  runtime: nodejs16.x
  httpApi:
    authorizers:
      auth:
        type: request
        functionName: auth-function
        identitySource:
          - $request.header.Authorization

functions:
  auth-function:
    handler: src/handlers/auth.handler
  create:
    handler: src/handlers/create.handler
    events:
      - httpApi:
          path: /item/create
          method: POST
          authorizer:
            name: auth

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

while this one works for offline but I get Event references not configured authorizer 'auth-function'

service: techstack

frameworkVersion: "3"

provider:
  name: aws
  runtime: nodejs16.x
  # httpApi:
  #   authorizers:
  #     auth:
  #       type: request
  #       functionName: auth-function
  #       identitySource:
  #         - $request.header.Authorization

functions:
  auth-function:
    handler: src/handlers/auth.handler
  create:
    handler: src/handlers/create.handler
    events:
      - httpApi:
          path: /item/create
          method: POST
          authorizer:
            name: auth-function
            type: request

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

So it's pretty close, but is there any way to be consistent between the two environments?

jdhrivas commented 1 year ago

Has anyone been able to use the option enableSimpleResponses: true? This bug is preventing the usage of all authorizer configurations offline

Haprog commented 1 year ago

I also ran into this issue but I found a workaround. If you use the same name for both the authorizer and the function then it works both with serverless-offline and also when deployed to AWS

For example:

service: my-service
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs18.x
  httpApi:
    authorizers:
      myAuthorizer:
        type: request
        functionName: myAuthorizer
        enableSimpleResponses: true

functions:
  dataHandler:
    handler: dataHandler.handler
    events:
      - httpApi:
          path: /my-path
          method: get
          authorizer:
            name: myAuthorizer
  myAuthorizer:
    handler: myAuthorizerHandler.handler
Haprog commented 1 year ago

Has anyone been able to use the option enableSimpleResponses: true? This bug is preventing the usage of all authorizer configurations offline

Yes, I'm using that setting (see my previous message) and my authorizer is like this (using TypeScript):

'use strict';

import type {
  APIGatewayRequestAuthorizerEventV2,
  APIGatewaySimpleAuthorizerResult,
} from 'aws-lambda';

export const handler = async (
  event: APIGatewayRequestAuthorizerEventV2
): Promise<APIGatewaySimpleAuthorizerResult> => {
  const { headers } = event;
  // serverless-offline uses capitalized headers while AWS uses all lowercase header names here
  const authHeader = headers?.authorization ?? headers?.Authorization;
  const isAuthorized = authHeader === `Bearer ${process.env.MY_ACCESS_TOKEN}`;

  return { isAuthorized };
};
edwinrosemond1 commented 1 year ago

@Haprog Are you sure serverless isn't directly referencing your auth function now. I tried this method but api gateway doesn't seem to be using the other attributes I set in that authorizer. For example, i set type: request and resultTtlInSeconds: 0. I'm also setting the identitysource, but don't see those in reflected in api gateway

Haprog commented 12 months ago

I'm not sure. I haven't worked with serverless in over 6 month now and can't remember the details of this that well anymore so I'm probably not going to spend time checking this unless I need to get back to that project (or if I need this in the future).

pseudoCoder0 commented 11 months ago

I also ran into this issue but I found a workaround. If you use the same name for both the authorizer and the function then it works both with serverless-offline and also when deployed to AWS

For example:

service: my-service
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs18.x
  httpApi:
    authorizers:
      myAuthorizer:
        type: request
        functionName: myAuthorizer
        enableSimpleResponses: true

functions:
  dataHandler:
    handler: dataHandler.handler
    events:
      - httpApi:
          path: /my-path
          method: get
          authorizer:
            name: myAuthorizer
  myAuthorizer:
    handler: myAuthorizerHandler.handler

This does not work if you have authorizer configured with Cognito and not custom lambda function.

mvergaray commented 8 months ago

Hello, any updates on this issue? Seeing the same error here.

adamldoyle commented 8 months ago

I looked into the source a bit because I was running into the same issue, and this is what I noticed as the core part of the problem.

The original reported error of Function "authorizerFunc" doesn't exist in this Service is thrown from the getFunction call that happens at this point when configuring the authorization: https://github.com/dherault/serverless-offline/blob/master/src/events/http/HttpServer.js#L306. It only uses the name defined in the event's authorizer section, as opposed to checking if a different function name was defined in the global provider section. Additionally, even if you get around this issue by naming your authorizer function the same as the provider authorizer, most of the configuration is still pulled from the event's authorizer section (like type: 'request'). It's interesting that some of the configuration is used from the provider section back when support was originally added, but some some of it was missed.

The good news is that I was able to hack together a solution locally which pulls configuration from both the provider section as well as the event's authorizer section. I'll see if I can piece together a PR which solves this problem.

celadari commented 6 months ago

I looked into the source a bit because I was running into the same issue, and this is what I noticed as the core part of the problem.

The original reported error of Function "authorizerFunc" doesn't exist in this Service is thrown from the getFunction call that happens at this point when configuring the authorization: https://github.com/dherault/serverless-offline/blob/master/src/events/http/HttpServer.js#L306. It only uses the name defined in the event's authorizer section, as opposed to checking if a different function name was defined in the global provider section. Additionally, even if you get around this issue by naming your authorizer function the same as the provider authorizer, most of the configuration is still pulled from the event's authorizer section (like type: 'request'). It's interesting that some of the configuration is used from the provider section back when support was originally added, but some some of it was missed.

The good news is that I was able to hack together a solution locally which pulls configuration from both the provider section as well as the event's authorizer section. I'll see if I can piece together a PR which solves this problem.

Can you share your local hack please ? :)

adamldoyle commented 6 months ago

Can you share your local hack please ? :)

The linked PR #1763 contains the changes that I've been using.

celadari commented 6 months ago

Thanks @adamldoyle , but why is no one looking at your PR ? :'(

adamldoyle commented 6 months ago

I think they're struggling with keeping active maintainers and at this point there's a large backlog of open PRs. My solution has been to publish a version with the fixes that I need and use that instead.