dherault / serverless-offline

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

customAuthenticationProvider breaks if the service has more than one function #1795

Open humodz opened 1 month ago

humodz commented 1 month ago

Bug Report

I'd be interested in working on a pull request for this fix, if the maintainers are open to it, I just need some help understanding the intent of the name/scheme properties in the custom auth provider.

Current Behavior

customAuthenticationProvider only works if the service has a single function

HttpServer.setAuthorizationStrategy loops over every function event and calls auth.scheme() on the custom auth provider, but auth.scheme() throws if you try to add the same scheme multiple times.

Sample Code

https://github.com/humodz/serverless-offline/blob/master/tests/integration/custom-authentication/serverless.yml

service: integration-tests

configValidationMode: error
deprecationNotificationMode: error

custom:
  offline:
    customAuthenticationProvider: ./src/authenticationProvider

plugins:
  - ../../../src/index.js

provider:
  architecture: arm64
  deploymentMethod: direct
  memorySize: 1024
  name: aws
  region: us-east-1
  runtime: nodejs18.x
  stage: dev
  versionFunctions: false

functions:
  echo:
    events:
      - httpApi:
          method: get
          path: /echo
    handler: src/handler.echo
  echo2:
    events:
      - httpApi:
          method: get
          path: /echo2
    handler: src/handler.echo

Expected behavior/code

customAuthenticationProvider should still work if the service has more than one function

Environment

Possible Solution

Change HttpServer.setAuthorizationStrategy or auth.js : scheme() so that it either allows adding the same scheme multiple times, or so that it stops adding the same scheme over and over for each function

Additional context/Screenshots

Stack trace:

Error:
AssertError: Authentication scheme name already exists: scheme
    at module.exports.internals.Auth.scheme (/home/hugo/projects/personal/serverless-offline/node_modules/@hapi/hapi/lib/auth.js:49:14)
    at #setAuthorizationStrategy (file:///home/hugo/projects/personal/serverless-offline/src/events/http/HttpServer.js:419:25)
    at HttpServer.createRoutes (file:///home/hugo/projects/personal/serverless-offline/src/events/http/HttpServer.js:1027:60)
    at #createEvent (file:///home/hugo/projects/personal/serverless-offline/src/events/http/Http.js:41:22)
    at file:///home/hugo/projects/personal/serverless-offline/src/events/http/Http.js:46:24
    at Array.forEach (<anonymous>)
    at Http.create (file:///home/hugo/projects/personal/serverless-offline/src/events/http/Http.js:45:12)
    at #createHttp (file:///home/hugo/projects/personal/serverless-offline/src/ServerlessOffline.js:192:16)
    at async Promise.all (index 0)
    at async ServerlessOffline.start (file:///home/hugo/projects/personal/serverless-offline/src/ServerlessOffline.js:98:5)
    at async #startWithExplicitEnd (file:///home/hugo/projects/personal/serverless-offline/src/ServerlessOffline.js:154:5)
    at async PluginManager.runHooks (/home/hugo/projects/personal/serverless-offline/node_modules/serverless/lib/classes/plugin-manager.js:530:9)
    at async PluginManager.invoke (/home/hugo/projects/personal/serverless-offline/node_modules/serverless/lib/classes/plugin-manager.js:564:9)
    at async PluginManager.run (/home/hugo/projects/personal/serverless-offline/node_modules/serverless/lib/classes/plugin-manager.js:604:7)
    at async Serverless.run (/home/hugo/projects/personal/serverless-offline/node_modules/serverless/lib/serverless.js:179:5)
    at async /home/hugo/projects/personal/serverless-offline/node_modules/serverless/scripts/serverless.js:819:9