admin管理员组

文章数量:1415119

I'm building a rich front-end client for AWS S3 using the AWS SDK. It works fine to hard code IAM credentials into the AWS SDK configuration, but I would like to provision access to the end user via AWS Cognito.

How can I get credentials for the users I've created in my Cognito user pool?

The AWS documentation is very unclear. There are examples I've seen using the AWS SDK and examples I've seen saying you need to have a different AWS Cognito SDK. Which documentation article is correct?

For this particular project I'm NOT wanting to use third-party federated identities at all.


UPDATE 2:

The AWS Cognito SDK has been merged into a new library called AWS Amplify.

UPDATE 1:

The problem is two-fold. Understanding the terminology and properly setting up Cognito is the first part. Thanks to Bruce0 for getting me up and running there. The second part is the javascript part. It turns out that you need two separate libraries to authenticate Cognito users purely from javascript.

This is the solution I came up with. If it looks foreign to you, make sure that you've studied up on your es6 with promises/async/await. To run it in node you just need to preprocess it using babel, preset es2015, preset stage-2, and the babel-transform-runtime plugin. If you want to run it in the browser you'll probably need to use the babel-loader with webpack (which is notoriously plicated to set up, just a forewarning).

import AWS from 'aws-sdk/global';
import S3 from 'aws-sdk/clients/s3';
import {
  AuthenticationDetails,
  CognitoUser,
  CognitoUserPool,
} from 'amazon-cognito-identity-js';

const REGION = 'some-string-value';
const USER_POOL_ID = 'some-string-value';
const IDENTITY_POOL_ID = 'some-string-value';
const APP_CLIENT_ID = 'some-string-value';
const POOL_KEY = `cognito-idp.${REGION}.amazonaws/${USER_POOL_ID}`;

let Username = 'some-string-value';
let Password = 'some-string-value';

let authenticationDetails = new AuthenticationDetails({
  Username,
  Password
});

let userPool = new CognitoUserPool({
  UserPoolId: USER_POOL_ID,
  ClientId: APP_CLIENT_ID
});

let cognitoUser = new CognitoUser({
  Username,
  Pool: userPool
});

let skateboards = {
  mfaRequired(codeDeliveryDetails) {
    let mfaCode = prompt('MFA code is required!');

    cognitoUser.sendMFACode(mfaCode, mfaRequired);
  },
  newPasswordRequired(userAttributes, requiredAttributes) {
    delete userAttributes.email_verified; // it's returned but not valid to submit

    let newPassword = prompt('A new password is required!');

    cognitoUserpleteNewPasswordChallenge(newPassword, userAttributes, newPasswordRequired);
  }
};

let updateAWSCreds = (jwtToken) => {
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: IDENTITY_POOL_ID,
    Logins: {
      [POOL_KEY]: jwtToken
    }
  });
};

let authenticateCognitoUser = async ({mfaRequired, newPasswordRequired} = skateboards) => {
  return new Promise((resolve, reject) => {
    cognitoUser.authenticateUser(authenticationDetails, {
      onSuccess(result) {
        let jwtToken = result.getIdToken().getJwtToken();
        updateAWSCreds(jwtToken);
        resolve();
      },
      onFailure(err) {
        reject(err);
      },
      mfaRequired,
      newPasswordRequired
    });
  });
};

let doSomethingInS3ForExample = async () => {
  await authenticateCognitoUser();

  // now do your stuff
};

doSomethingInS3ForExample();

I'm building a rich front-end client for AWS S3 using the AWS SDK. It works fine to hard code IAM credentials into the AWS SDK configuration, but I would like to provision access to the end user via AWS Cognito.

How can I get credentials for the users I've created in my Cognito user pool?

The AWS documentation is very unclear. There are examples I've seen using the AWS SDK and examples I've seen saying you need to have a different AWS Cognito SDK. Which documentation article is correct?

For this particular project I'm NOT wanting to use third-party federated identities at all.


UPDATE 2:

The AWS Cognito SDK has been merged into a new library called AWS Amplify. https://github./aws/aws-amplify

UPDATE 1:

The problem is two-fold. Understanding the terminology and properly setting up Cognito is the first part. Thanks to Bruce0 for getting me up and running there. The second part is the javascript part. It turns out that you need two separate libraries to authenticate Cognito users purely from javascript.

This is the solution I came up with. If it looks foreign to you, make sure that you've studied up on your es6 with promises/async/await. To run it in node you just need to preprocess it using babel, preset es2015, preset stage-2, and the babel-transform-runtime plugin. If you want to run it in the browser you'll probably need to use the babel-loader with webpack (which is notoriously plicated to set up, just a forewarning).

import AWS from 'aws-sdk/global';
import S3 from 'aws-sdk/clients/s3';
import {
  AuthenticationDetails,
  CognitoUser,
  CognitoUserPool,
} from 'amazon-cognito-identity-js';

const REGION = 'some-string-value';
const USER_POOL_ID = 'some-string-value';
const IDENTITY_POOL_ID = 'some-string-value';
const APP_CLIENT_ID = 'some-string-value';
const POOL_KEY = `cognito-idp.${REGION}.amazonaws./${USER_POOL_ID}`;

let Username = 'some-string-value';
let Password = 'some-string-value';

let authenticationDetails = new AuthenticationDetails({
  Username,
  Password
});

let userPool = new CognitoUserPool({
  UserPoolId: USER_POOL_ID,
  ClientId: APP_CLIENT_ID
});

let cognitoUser = new CognitoUser({
  Username,
  Pool: userPool
});

let skateboards = {
  mfaRequired(codeDeliveryDetails) {
    let mfaCode = prompt('MFA code is required!');

    cognitoUser.sendMFACode(mfaCode, mfaRequired);
  },
  newPasswordRequired(userAttributes, requiredAttributes) {
    delete userAttributes.email_verified; // it's returned but not valid to submit

    let newPassword = prompt('A new password is required!');

    cognitoUser.pleteNewPasswordChallenge(newPassword, userAttributes, newPasswordRequired);
  }
};

let updateAWSCreds = (jwtToken) => {
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: IDENTITY_POOL_ID,
    Logins: {
      [POOL_KEY]: jwtToken
    }
  });
};

let authenticateCognitoUser = async ({mfaRequired, newPasswordRequired} = skateboards) => {
  return new Promise((resolve, reject) => {
    cognitoUser.authenticateUser(authenticationDetails, {
      onSuccess(result) {
        let jwtToken = result.getIdToken().getJwtToken();
        updateAWSCreds(jwtToken);
        resolve();
      },
      onFailure(err) {
        reject(err);
      },
      mfaRequired,
      newPasswordRequired
    });
  });
};

let doSomethingInS3ForExample = async () => {
  await authenticateCognitoUser();

  // now do your stuff
};

doSomethingInS3ForExample();

https://gist.github./sbussard/7344c6e1f56051da0758d1403a4343b1

Share Improve this question edited May 15, 2018 at 18:07 Stephen asked Dec 29, 2016 at 20:14 StephenStephen 8,1869 gold badges49 silver badges73 bronze badges 3
  • I would not do too much with the aws sdk on the client since it'd required to make the AWS secret key available on the client. I'd either go with cognito, or aws sdk on the backend and use presigned requests on the client – Guig Commented Dec 29, 2016 at 22:04
  • 1 The only way to get credentials in Cognito is to create a Federated Identity Pool. The cognitoIdentity and credentialsProvider methods ARE the way you get credentials. You do not have to Federate identities to use the Federated identity Pool but you DO need to have an identityId (and those only exist in the pool). So you will have a cognitoUserPool as the only authentication provider in the Federated Identity Pool (nothing will be federated) and IAM roles are provided (usually Authenticated and Unauthenticated) by that identity pool (but you can have more roles) – Bruce0 Commented Dec 29, 2016 at 22:07
  • @Bruce0 indeed! that is what I'm experiencing so far. Cognito seems truly revolutionary. Your help is greatly appreciated, and will no-doubt positively affect millions of people in the ing months, not including whitespace ;) – Stephen Commented Dec 29, 2016 at 22:31
Add a ment  | 

2 Answers 2

Reset to default 5

The only way to get credentials in Cognito is to create a Federated Identity Pool. The cognitoIdentity and credentialsProvider methods ARE the way you get credentials.

You do not have to Federate identities to use the Federated identity Pool but you DO need to have an identityId (and those only exist in the pool) in order to get credentials.

So you will have a cognitoUserPool as the only authentication provider in the Federated Identity Pool (nothing will be federated) and IAM roles are provided (usually Authenticated and Unauthenticated) by that identity pool (but you can have more roles).

Here is a link to a powerpoint explaining some of the basic confusing aspects of Cognito, I hope that helps. Cognito outline

Lastly I would remend that you start your implementation using the AWS Mobile Hub (At least as an example), as opposed to using the IOS SDK. The Mobile Hub is a thin wrapper but does a lot of the heaving lifting and is nicely architected.

This works for me below, I set up cognito to create a identity pool, and the IAM to add the profile to the user (i followed this link exactly : https://docs.aws.amazon./sdk-for-javascript/v2/developer-guide/s3-example-photo-album.html)

import S3 from 'aws-sdk/clients/s3'
import AWS from 'aws-sdk/global'

AWS.config.update({
  region: process.env.AZ_REGION,
  credentials: new AWS.CognitoIdentityCredentials({
    IdentityPoolId: 'XXX'
  })
});

const s3 = new AWS.S3({
apiVersion: '2006-03-01',
params: {Bucket: process.env.AZ_BUCKETNAME},
      });

I only wish we didn't need to import the aws-sdk/global it itself is 206k unminified. Thats a lot to throw down to the user.

本文标签: javascriptHow do I get credentials on AWS Must I use AWS Cognito SDK or AWS SDKStack Overflow