Repository: serverless/serverless (JavaScript)
Date: 2017-07-05 19:16:30+00:00
Task type: Bug Fix

Issue:
DX: Improve invalid aws credentials message
After running `serverless invoke -f hello` with invalid creds on my machine (for testing). I see this:

![image](https://user-images.githubusercontent.com/532272/27565838-99522520-5a95-11e7-91b6-027b1e35fefe.png)

The current error message "The security token included in the request is invalid." is super vague and doesn't say how to fix the error.

Instead, lets say something like: 

```
The AWS security token included in the request is invalid.
Please check your ~./aws/credentials file and verify your keys are correct
```

@eahefnawy do you know where this error throws? I couldn't track it down.


Issue discussion:
This is super annoying.

I always face this because of MFA. It's returned bey the `aws-sdk` if the MFA token expired. So nothing credentials related.

Re-authenticating via `assume-role` fixes the problem for me.
Hello,

I wanted to update the error message, but also could not find it in the project's code. Has this already been resolved?
Hey @rdugue thanks for your comment! 👍 

This issue was not resolved yet. AFAIK the error is thrown somewhere here: https://github.com/serverless/serverless/blob/bf1d07663e6963ed36b346915bcf79078fa4e223/lib/plugins/aws/provider/awsProvider.js#L153.

You could catch the error message, compare it to the one provided in the issue description and then throw a new one with more, detailed information.

We do smth. similar here: https://github.com/serverless/serverless/blob/bf1d07663e6963ed36b346915bcf79078fa4e223/lib/plugins/aws/lib/monitorStack.js#L115-L122

Let us know if you need any help here and thanks again for jumping in! 💯 

Solution patch:
diff --git a/lib/plugins/aws/provider/awsProvider.js b/lib/plugins/aws/provider/awsProvider.js
index c7354fb43bc..2bea7448aeb 100644
--- a/lib/plugins/aws/provider/awsProvider.js
+++ b/lib/plugins/aws/provider/awsProvider.js
@@ -146,11 +146,22 @@ class AwsProvider {
         f()
           .then(resolve)
           .catch((e) => {
-            if (e.statusCode === 429) {
+            const err = e;
+            if (err.statusCode === 429) {
               that.serverless.cli.log("'Too many requests' received, sleeping 5 seconds");
               setTimeout(doCall, 5000);
             } else {
-              reject(e);
+              if (err.message.match(/(.+security token.+is )+(invalid)*|(expired)*/)) {
+                const errorMessage = [
+                  'The AWS security token included in the request is invalid / expired.\n',
+                  '  Please re-authenticate if you\'re using MFA.\n',
+                  '  Or check your ~./aws/credentials file and verify your keys are correct.\n',
+                  '  More information on setting up credentials',
+                  ` can be found here: ${chalk.green('https://git.io/vXsdd')}.`,
+                ].join('');
+                err.message = errorMessage;
+              }
+              reject(new this.serverless.classes.Error(err.message, err.statusCode));
             }
           });
       };


Test patch:
diff --git a/lib/plugins/aws/provider/awsProvider.test.js b/lib/plugins/aws/provider/awsProvider.test.js
index f4b8e7705c4..d796dd19ee1 100644
--- a/lib/plugins/aws/provider/awsProvider.test.js
+++ b/lib/plugins/aws/provider/awsProvider.test.js
@@ -3,6 +3,7 @@
 const expect = require('chai').expect;
 const proxyquire = require('proxyquire');
 const sinon = require('sinon');
+const chalk = require('chalk');
 
 const AwsProvider = require('./awsProvider');
 const Serverless = require('../../../Serverless');
@@ -214,6 +215,43 @@ describe('AwsProvider', () => {
         .catch(() => done());
     });
 
+    it('should ask to re-authenticate MFA or check if AWS credentials are valid', (done) => {
+      const error = {
+        statusCode: 403,
+        message: 'The security token included in the request is invalid',
+      };
+      class FakeS3 {
+        constructor(credentials) {
+          this.credentials = credentials;
+        }
+
+        error() {
+          return {
+            send(cb) {
+              cb(error);
+            },
+          };
+        }
+      }
+      awsProvider.sdk = {
+        S3: FakeS3,
+      };
+      awsProvider.request('S3', 'error', {})
+        .then(() => done('Should not succeed'))
+        .catch((err) => {
+          const errorMessage = [
+            'The AWS security token included in the request is invalid / expired.\n',
+            '  Please re-authenticate if you\'re using MFA.\n',
+            '  Or check your ~./aws/credentials file and verify your keys are correct.\n',
+            '  More information on setting up credentials',
+            ` can be found here: ${chalk.green('https://git.io/vXsdd')}.`,
+          ].join('');
+          expect(err.message).to.equal(errorMessage);
+          done();
+        })
+        .catch(done);
+    });
+
     it('should return ref to docs for missing credentials', (done) => {
       const error = {
         statusCode: 403,