6

I am using the AWS Amplify library with MobileHub.

I have a Cognito User Pool connected, and an API Gateway (which communicates with Lambda functions). I'd like my users to sign before accessing resources, so I've enabled "mandatory sign-in" in MobileHub User Sign-In page, and the Cloud Logic page.

Authentication works fine, but when I send a GET request to my API, I receive this error:

"[WARN] 46:22.756 API - ensure credentials error": "cannot get guest credentials when mandatory signin enabled"

I understand that Amplify generates guest credentials, and has put these in my GET request. Since I've enabled "mandatory signin", this doesn't work.

But why is it use guest credentials? I've signed in -- shouldn't it use those credentials? How do I use the authenticated user's information?

Cheers.

EDIT: Here is the code from the Lambda function:

lambda function:

import { success, failure } from '../lib/response';
import * as dynamoDb from '../lib/dynamodb';

export const main = async (event, context, callback) => {
    const params = {
        TableName: 'chatrooms',
        Key: {
            user_id: 'user-abc', //event.pathParameters.user_id,
            chatroom_id: 'chatroom-abc',
        }
    };

    try {
        const result = await dynamoDb.call('get', params);
        if (result.Item) { 
            return callback(null, success(result.Item, 'Item found'));
        } else {
            return callback(null, failure({ status: false }, 'Item not found.'));
        }
    } catch (err) {
        console.log(err);
        return callback(null, failure({ status: false }), err);
    }
}

And these small helper functions:

response.js:

export const success = (body, message) => buildResponse(200, body, message)
export const failure = (body, message) => buildResponse(500, body, message)

const buildResponse = (statusCode, body, message=null) => ({
    statusCode: statusCode,
    headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    },
    body: JSON.stringify({
        ...body,
        message: message
    })
});

dynamodb.js:

import AWS from 'aws-sdk';

AWS.config.update({ region: 'ap-southeast-2' });

export const call = (action, params) => {
    const dynamoDb = new AWS.DynamoDB.DocumentClient();
    return dynamoDb[action](params).promise();
}
haz
  • 2,034
  • 4
  • 28
  • 52
  • 1
    Can you post some code of the API gateway call? – Victor 'Chris' Cabral May 14 '18 at 21:04
  • 1
    I've updated the main post. Some details are hard-coded for debugging. Does AWS require the response to be in a format that I'm not complying to? – haz May 17 '18 at 12:17
  • I would guess that were not authenticated before (even if you thought you were) and when you turned on mandatory authentication you discovered that your API calls were never authenticated. https://github.com/aws/aws-amplify/blob/master/packages/aws-amplify/src/Auth/Auth.ts#L1210 – Victor 'Chris' Cabral May 17 '18 at 17:17
  • How can I ensure I authenticate? I run `Auth.signIn('username', 'password')` and I seem to receive the correct object (No errors or anything). Is there another sign-in method I should be performing? – haz May 18 '18 at 02:18
  • I see. There seems to be some options posted here https://github.com/aws/aws-amplify/issues/432 – Victor 'Chris' Cabral May 18 '18 at 02:25

4 Answers4

2

I'm following the guide "serverless-stack" and was prompt with the same warning message, I was logging in correctly and logging out correctly and did not understand why the warning message. In my case, in the Amplify.configure I skip to add the identity pool id, and that was the problem, User pools and federated identities are not the same.

(English is not my native language)

Andrew
  • 21
  • 3
1

Have you tried checking why your SignIn request is being rejected/error prone?

Auth.signIn(username, password)
    .then(user => console.log(user))
    .catch(err => console.log(err));

// If MFA is enabled, confirm user signing 
// `user` : Return object from Auth.signIn()
// `code` : Confirmation code  
// `mfaType` : MFA Type e.g. SMS, TOTP.
Auth.confirmSignIn(user, code, mfaType)
    .then(data => console.log(data))
    .catch(err => console.log(err));

You can try this, then it would be easier for you to debug.

Abhishek Singh
  • 2,642
  • 15
  • 24
  • My SignIn request is not rejected, it passes fine and I receive the correct `User` object. This is why I'm confused -- it's the API call that fails, but the Cognito SignIn works perfectly. – haz May 22 '18 at 05:51
  • The error that you received served only if you have initiated the SignOut call or the Aws amplify library was not able to fetch the data for currentSessionUser. You might give us some of the Authentication code and code for the GET API call then only we can give you a better answer. – Abhishek Singh May 22 '18 at 06:07
0

From the suggestions on the aws-amplify issues tracker, add an anonymous user to your cognito user pool and hard code the password in your app. Seems like there are other options but this is the simplest in my opinion.

Victor 'Chris' Cabral
  • 2,135
  • 1
  • 16
  • 33
  • I'm not trying to implement an anonymous user, however. My user has all the details (username, password, email), and I'm trying to log in with that. Am I (possibly) missing a difference between a Cognito user and AWS user? – haz May 20 '18 at 16:21
0

You have to use your credentials at each request to use AWS Services : (sample code angular)

SignIn :

import Amplify from 'aws-amplify';
import Auth from '@aws-amplify/auth';

 Amplify.configure({
      Auth: {
        region: ****,
        userPoolId: *****,
        userPoolWebClientId: ******,
      }
    });

//sign in

Auth.signIn(email, password)

Request

import Auth from '@aws-amplify/auth';

from(Auth.currentCredentials())
   .pipe(
      map(credentials => {
        const documentClient = new AWS.DynamoDB.DocumentClient({
          apiVersion: '2012-08-10',
          region: *****,
          credentials: Auth.essentialCredentials(credentials)
       });

       return documentClient.query(params).promise()

      }),
      flatMap(data => {
          return data
       })
)
Sid Ali
  • 1,779
  • 4
  • 17
  • 38