Repository: serverless/serverless (JavaScript) — Bug Fix

Issue:
Cannot read property 'length' of undefined when defining a string authorizer
<!--
1. If you have a question and not a bug report please ask first at http://forum.serverless.com
2. Please check if an issue already exists. This bug may have already been documented
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a Bug Report

## Description

* What went wrong?
Running `serverless deploy` on a serverless.yml file that has a lambda function with a "string" authorizer (AWS Cognito authorizer). I found out by debugging that it is related to the claims in `validate.js` file (https://github.com/serverless/serverless/blob/add5e3ebb5d3d9050e36bf720ab9ab1c3fd8f3d8/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js#L223). If I manually define it as `[]` at the beginning, it will execute successfully.
* What did you expect should have happened?
To deploy successfully.
* What was the config you used?
My lambda function section looks like:
```
  my-function:
    handler: bin/my-function
    timeout: 15
    package:
      include:
        - bin/my-function
    role: "arn:aws:iam::${self:custom.tenant_id}:role/${self:custom.project_name}-${self:custom.env}-my-function-lambda-role"
    events:
      - http:
          path: my-path
          method: any
          authorizer: "arn:aws:cognito-idp:${self:custom.region}:${self:custom.tenant_id}:userpool/${self:custom.cognito_user_pool}"
      - http:
          path: my-path/{id}
          method: any
          authorizer: "arn:aws:cognito-idp:${self:custom.region}:${self:custom.tenant_id}:userpool/${self:custom.cognito_user_pool}"
    environment:
      MY_VARIABLE: "/${self:custom.project_name}-${self:custom.env}"
```
* What stacktrace or error message from your provider did you see?
The error message is from serverless itself

Similar or dependent issues:
* #12345

## Additional Data

* ***Serverless Framework Version you're using***:
* ***Operating System***: MacOS Mojave 10.14.5
* ***Stack Trace***: 
```
 
  Type Error ---------------------------------------------
 
  Cannot read property 'length' of undefined
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Stack Trace --------------------------------------------
 
TypeError: Cannot read property 'length' of undefined
    at AwsCompileApigEvents.getAuthorizer (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js:286:17)
    at _.forEach (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js:51:36)
    at arrayEach (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:516:11)
    at Function.forEach (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:9344:14)
    at _.forEach (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js:43:9)
    at /usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:4911:15
    at baseForOwn (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:2996:24)
    at /usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:4880:18
    at Function.forEach (/usr/local/lib/node_modules/serverless/node_modules/lodash/lodash.js:9344:14)
    at AwsCompileApigEvents.validate (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js:42:7)
    at Object.package:compileEvents [as hook] (/usr/local/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/index.js:53:31)
    at BbPromise.reduce (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:446:55)
From previous event:
    at PluginManager.invoke (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:446:22)
    at PluginManager.spawn (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:464:17)
    at Deploy.BbPromise.bind.then (/usr/local/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:122:50)
From previous event:
    at Object.before:deploy:deploy [as hook] (/usr/local/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:107:10)
    at BbPromise.reduce (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:446:55)
From previous event:
    at PluginManager.invoke (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:446:22)
    at PluginManager.run (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:477:17)
    at variables.populateService.then (/usr/local/lib/node_modules/serverless/lib/Serverless.js:110:33)
    at processImmediate (internal/timers.js:443:21)
    at process.topLevelDomainCallback (domain.js:136:23)
From previous event:
    at Serverless.run (/usr/local/lib/node_modules/serverless/lib/Serverless.js:97:6)
    at serverless.init.then (/usr/local/lib/node_modules/serverless/bin/serverless:43:28)
    at /usr/local/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:111:16
    at /usr/local/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:45:10
    at FSReqCallback.args [as oncomplete] (fs.js:145:20)
From previous event:
    at initializeErrorReporter.then (/usr/local/lib/node_modules/serverless/bin/serverless:43:6)
    at processImmediate (internal/timers.js:443:21)
    at process.topLevelDomainCallback (domain.js:136:23)
From previous event:
    at /usr/local/lib/node_modules/serverless/bin/serverless:28:46
    at Object.<anonymous> (/usr/local/lib/node_modules/serverless/bin/serverless:65:4)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:877:12)
    at internal/main/run_main_module.js:21:11
```
* ***Provider Error messages***:
No error messages from the provider.


Discussion:
I would like to suggest to make both checks, `claims && claims.length > 0`, in the change from: https://github.com/serverless/serverless/commit/9b4ec28a1e377cf1163ab153e99b5afd18727038#diff-a15f3a24289528534cb043857ccac565
Thanks for opening @camilosampedro 👍

🤔 this seems to be related to https://github.com/serverless/serverless/pull/6121 where we already tried to fix some other issues with claims. Would you want to jump in a work on a PR since you know what could fix it? Thanks in advance!

Resolving patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js
index 08e13da2fc8..2b6ced95f33 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js
@@ -283,6 +283,7 @@ module.exports = {
     if (integration === 'AWS_PROXY'
       && typeof arn === 'string'
       && awsArnRegExs.cognitoIdpArnExpr.test(arn)
+      && claims
       && claims.length > 0) {
       const errorMessage = [
         'Cognito claims can only be filtered when using the lambda integration type',


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js
index 43f20c7f7c6..a0e692af1a6 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js
@@ -325,6 +325,25 @@ describe('#validate()', () => {
     expect(() => awsCompileApigEvents.validate()).not.to.throw(Error);
   });
 
+  it('should not throw when using a cognito string authorizer', () => {
+    awsCompileApigEvents.serverless.service.functions = {
+      first: {
+        events: [
+          {
+            http: {
+              path: '/{proxy+}',
+              method: 'ANY',
+              integration: 'lambda-proxy',
+              authorizer: 'arn:aws:cognito-idp:us-east-1:$XXXXX:userpool/some-user-pool',
+            },
+          },
+        ],
+      },
+    };
+
+    expect(() => awsCompileApigEvents.validate()).not.to.throw(Error);
+  });
+
   it('should accept AWS_IAM as authorizer', () => {
     awsCompileApigEvents.serverless.service.functions = {
       foo: {},