0xD1x0n
0xD1x0n

Reputation: 653

Access AWS Secrets from React Amplify APP

This May be a stupid question, But is it safe to access AWS Secrets from my React front end app (Hosted on AWS Amplify) In this manner ?

These Secrets are obviously not intended to be public so I dont want to use Amplify Env Variables option.

If this is not the appropriate way of loading API Secrets and keys to a Front End Application, then what is ?

var AWS = require('aws-sdk'),
    region = "us-east-2",
    secretName = "MNTSWP",
    secret,
    decodedBinarySecret;

// Create a Secrets Manager client
var client = new AWS.SecretsManager({
    region: region
});



client.getSecretValue({SecretId: secretName}, function(err, data) {
    if (err) {
        if (err.code === 'DecryptionFailureException')

            throw err;
        else if (err.code === 'InternalServiceErrorException')

            throw err;
        else if (err.code === 'InvalidParameterException')

            throw err;
        else if (err.code === 'InvalidRequestException')

            throw err;
        else if (err.code === 'ResourceNotFoundException')

            throw err;
    }
    else {

        if ('SecretString' in data) {
            secret = data.SecretString;
        } else {
            let buff = new Buffer(data.SecretBinary, 'base64');
            decodedBinarySecret = buff.toString('ascii');
        }
    }
    
    // Your code goes here. 
});

Upvotes: 4

Views: 8028

Answers (3)

Pyae Phyoe Shein
Pyae Phyoe Shein

Reputation: 13827

That's you may need to save your credentials information into Secret Manager first, then fetch as follow:

var AWS = require('aws-sdk'),
  region = "ap-southeast-1",
  secretName = `my-secret`, rds_username, rds_password;

var awsSecretClient = new AWS.SecretsManager({
  region: region
});

let result = await awsSecretClient.getSecretValue({ SecretId: secretName }).promise();
rds_username = Buffer.from(JSON.parse(result.SecretString).rds_username, 'base64').toString();
rds_password = Buffer.from(JSON.parse(result.SecretString).rds_password, 'base64').toString();

Upvotes: 1

Geoffrey Wiseman
Geoffrey Wiseman

Reputation: 5637

Because your front end runs in a web browser, because the code can easily be examined by moderately technical users, you cannot keep credentials (such as your AWS credentials) there safely. If you do that, not only are your secrets exposed, but your AWS credentials are exposed, and an attacker can do a lot of damage with those (and there are tools to scan for AWS keys).

Honestly there aren't really solid ways to protect credentials in a front-end application, so you can:

  • Use a back-end API which holds the credential securely
    • But are you just pushing the problem around? Now do you need to verify that the user should have access to the back-end API?
  • Have the user supply credentials
    • This is the most common approach -- the user provides username and password and you use that to control access
    • This may still require a back-end API or something that can parse the credentials (e.g. AWS API Gateway + Authorizer)
  • Work out complicated rules to protect back-end resources even when some level of key is exposed (e.g. see Firebase Security Rules).

Upvotes: 2

Jason Wadsworth
Jason Wadsworth

Reputation: 8887

In order for this to even work, you'd have to have some credentials on the client that had permission to access the secret. If they are truly secret then you should not do this. Anything that you request via your app is no longer secret. If you are trying to provide secure access to backend resources you should use something like Cognito and pass along a JWT.

Upvotes: 3

Related Questions