Condition based access to amazon lamda results? - javascript

Wondering if it's possible to have a webapp upload a file (userid.input.json) to Amazon S3, which triggers a lambda function that reads the file, does some processing, and saves the result as another (userid.output.json).
However userid.output.json should not be immediately accessible to the web application. The webapplication has to complete a Stripe payment and once the payment completes, the web application can access the (userid.output.json) file on amazon s3.
Before I ask how, I figured I'd first ask if this this scenario can be facilitated / architected on AWS?
Approach
Note that this is an update to the question based on more research. It looks like Amazon Cognito will be the perfect tool for signing in users and tying their user credentials to an IAM role that can read and write to S3 buckets.
So once the user is signed in through Amazon Cognito and has the proper credentials then their files can be uploaded to an S3 bucket and processed by a lambda. The result is then written to the same bucket.
Now earlier I suggested writing to a sealed bucket and having a Stripe webhook trigger moving the result from the sealed bucket to an accessible bucket. But it seems this is necessary, per the indication in the answer provided by #Snickers3192.
Once the stripe payment completes the webapp can set a boolean that is used to control access to the output and that completes the cycle?
Part of the rational for having a hidden bucket was that someone might pull the credentials out of the browser and execute them in a different script. I assume this is impossible (Famous last words :) ), but just in case I wrote a follow up question here.
In other words the credentials that are pulled into the client post signin with Amazon Cognito cannot be used to executed scripts outside of the application context?
Approach Part 2
Per my follow up questions it does not appear that relying on state within the webapp for making security decisions is good enough, as someone can probably figure out a way to get the token authentication token and manipulate the applications API directly using a client other than the core app.
So now I'm thinking about it like this:
1) Write the result to the sealed bucket (Processing Lambda)
2) Have the Stripe webhook update the users a transaction record in the users profile indicating payment paid = true (Stripe Lambda)
3) Create another lambda that has access rights to the sealed bucket but will return results only if paid=true. (Access Result Lambda)
So since Stripe is tied to an IAM user that is allowed to update the Application user profile and set paid=true and the sealed bucket can only be accessed by lambda that first checks if paid=true before returning the result, I believe that should guarantee security.
If anyone has a simpler approach please let me know.

This really is more a question of where you want to put the security, which in AWS there are many options, in your application logic which could mean:
Lambda/Webapp
S3 policies
IAM roles/groups
These decisions are usually dictated by where your identity store is kept, and also if you want to keep the notion of AWS users VS. users of your app. My preference is to keep these two pools separate, in that security logic like this is kept in the webapp/lambda and AWS security only deals with what rights developers have to the environment as well as what rights applications themselves have.
This means the webapp can always access the input and output buckets, but it keeps a record in a database somewhere (or makes use of your payment system API) who has paid and who hasn't paid and uses that information to deny or grant access to users. IMO this is a more modular design, and it enables you to lock down your AWS account better and is more clear to developers where security is located. In addition if you do go with IAM/S3 it will be more difficult to run and debug locally.
EDIT: After all your comments and additional security concerns you may also want to consider emailing a short lived URL link to the processed file, so that a user needs both email access as well as knowing their credentials to the application. This will mean even if your access token is stolen at the browser level, without the email access a hacker still can't get the processed file. If you want to be EXTREME SECURITY CORE, have the link that not only is authentication required, but also MFA so that they need to enter in a code which is constantly refreshing as you should have setup for your AWS account when you login.
I'm by no means a security expert but just follow best practices and do your due diligence and you will meet security expectations.

Related

What is the best way to connect two applications using APIS? (An E-commerce and a chatbot)

I have two applications settled up. One is a E-commerce (TrayCommerce) that has itself an Api (Oauth), from which I can get order, clients, products information, etc. The other one is a chatbot (Take Blip).
My goal is to make the chatbot retrieve information from the e-commerce's API so I can send it to final user.
I thought in two ways of doing it:
Hosting a javascript code inside the bot, so I can call the API whenever user requests data. However, I don't know how to implement the authentication flow on this approach and how I would, in the future, set up a system to receive notifications from the API to send information each time it is updated, since I can only host one js file per action.
Creating a NodeJS API, which will be hosted on a third party, and that will return the information I want, in a formatted way, to the chatbot. I don't know if this is over-engineering, because I already have an API from the e-commerce.
I am sorry if it is a dumb question, I am new to web development, but any information would be valuable for me to choose a workflow for this integration.
To be able to answer, the right question to ask yourself is the sensitiveness of the data inside the e-commerce; and the power granted to the generated token in the auth implementation.
Typically, a chatbot (assuming a web one) is a piece of Javascript held in the client (browser). This piece of code is perfectly readable by the user, thus you have to assume the generated token could be used to perform a request that you didn't intended him to perform.
So as a simple answer :
If — and only if — the implemented OAuth mecanism lets you limit the scope of authorization to the customer, then you can make the customer authenticate directly with TrayCommerce and the appropriate scopes (and use his token to perform on the API). Said differently, if typically TrayCommerce lets you register your Chatbot as a "client" (this is an OAuth keyword), and generate Auth journeys with appropriate 3-parties flows, granting only something like "orders:view:self" for customers, it's OK.
If the TrayCommerce API is more like a "management API"; with auth implemented in a way that you (yourself, not the customer) have to authenticate on it; then this auth mecanism is not suitable for your use-case. You then have to make an API like you described, that would act like a proxy to TrayCommerce. With considerations (see below).
In the case of you making a "Proxy API" to TrayCommerce; you are basically hiding the TrayCommerce Authentication on your server-side, and shifting that responsibility from TrayCommerce to yourself. In such a case, you have to implement your own authentication (+ authorization) mecanism on this API, to be able not to expose TrayCommerce data to the world.

How can Firebase Authentication securely authenticate a user with only client-side code?

There is plenty of tutorials and articles on this precise question but each one contradict the previous one,
I'm trying to make a signup and login reactJs pages with Firebase js sdk on the frontend, that's what I found most of youtubers devs do,
And then I found that is not secure (doing the authentication on client side).
You should use the Firebase Admin SDK (firebase.google.com/docs/admin/setup) on Firebase Cloud Functions or a self-hosted server in that case. Everything else would just be a dirty hack – PRSHL source
It's not recommended to create admin accounts on the front end as anyone could look into the code and action it themselves. source
I really want to understand if it is not secure to use it on the client side, Why does firebase provided it in the first place ?? or is there another way to properly write the auth using firebase js sdk on the frontend ? of course without using admin sdk
Or should I use firebase js sdk on the backend with express ?
I only want clear and detailed answers please !!
My best guess is that you're confused between authenticating a user client-side and the fact that Firebase provides a client-side SDK for authenticating users.
Though all you have to do to use Firebase Authentication in your app is implement its client-side SDK, there are many more parts involved in the process - and quite a few of them run on secured servers.
It's just that Firebase (and the authentication providers it supports) have implemented the server-side of the authentication process for you already and made the variables parts of the process part of the configuration that you provide either in the Firebase console, the provider's web interface, and/or in the configuration that you specify when you initialize the Firebase SDK in your client-side application code.
From the comments you now added, the second is correct and explains exactly what the risk is:
It's not recommended to create admin accounts on the front end as anyone could look into the code and action it themselves.
So while you can safely create a user account on the client (a process known as authentication), marking them as an admin (a process known as authorization) has to happen in a trusted environment as otherwise any user could make themselves an admin.

Run computation on user AWS account

I am having a Node.js and Vue.js project, where a user is going to provide his AWS credentials, a pointer to some online resource (which stores a large amount of data), and some algorithm on this data is going to be run on user's AWS account that he/she provided.
For this purpose, I am having two difficulties and I would like to ask for some help.
Firstly, I want to deploy some simple javascript code in the cloud, to test that everything works. What is the easiest way to do that? How can the npm packages aws-sdk and aws-lambda help me? Do I necessarily need to give my debit card details to make use of AWS just for quick testing purpose?
The second thing is, is there an authorization library/tool that AWS offers, like Facebook, for example, so the user just needs to input his username and password into a window, and he/she is automatically authorized (with OAuth, probably that's what they are using).
In addition, I would appreciate any general advice on how to approach this problem, how can I run code on huge amount of data on cloud user accounts? Maybe another cloud platform is more appropriate? Thank you!
This is a big question. so I'll provide some pointers for you to do further reading on:
to start with, decide if you want your webapp to be server-based (EC2, Node.js, and Express) or serverless (CloudFront, API Gateway, Lambda, and S3)
learn how to use Cognito as a way to get AWS credentials associated with a social provider login (such as Facebook or Google)
to operate in another user's AWS account, you should leverage cross-account IAM roles (they create a role and give you permission to assume it)
on the question of running code against large amounts of data, the repository for this data will typically be S3 or perhaps Redshift in some situations, and the compute environment could be any one of Lambda (short lifetime, serverless), EMR (clustered Hadoop, Spark etc.), EC2 (vanilla VM), Athena (SQL queries over content in S3), or ECS (containers). You haven't given enough information to help decide which might be more suitable.
The simplest option to test things out is likely to be S3 (for storage) and EC2 (use t2.micro instances in Free Tier, deploy your web application just like you would on any other Linux environment).
Yes, to use AWS you need an account and to get an account you need to supply a credit card. There is a substantial Free Tier in your first year, however.

In the AWS Javascript SDK, is there a way to test credentials?

I'm writing a web app to layer some tools on top of our AWS account. I want to limit access to this web app to only those who have the appropriate access. I'm not really sure what to check (maybe which group they're in?) and how to check it (short of submitting dry-run calls to "test" their credentials?)
The flow would be something like..
User navigates to this page
Specifies what they want to do (via some prewritten scripts)
The page prompts them for a user/password associated with their AWS account
Execute the script (which will have access to do everything from start/stop EC2 to creating new ECS task definitions, modifying Route53, etc.)
What's the best way to validate that the user hitting my web app actually has permissions to execute these calls? Is there a SDK option to pass in credentials with calls, or create a credential object of some sort and test that?
A specific example of the SDK that I want to use is http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ECS.html#registerTaskDefinition-property
AWS Cognito lets you specify separate roles for anonymous and authenticated users, with the policies you define for accessing other services: http://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html
In this broadcast we went through implementing a javascript example: https://www.twitch.tv/videos/132010411

Securing JS client-side SDKs

I'm working on a React-Redux web-app which integrates with AWS Cognito for user authentication/data storage and with the Shopify API so users can buy items through our site.
With both SDKs (Cognito, Shopify), I've run into an issue: Their core functionality attaches data behind the scenes to localStorage, requiring both SDKs to be run client-side.
But running this code entirely client-side means that the API tokens which both APIs require are completely insecure, such that someone could just grab them from my bundle and then authenticate/fill a cart/see inventory/whatever from anywhere (right?).
I wrote issues on both repos to point this out. Here's the more recent one, on Shopify. I've looked at similar questions on SO, but nothing I found addresses these custom SDKs/ingrained localStorage usage directly, and I'm starting to wonder if I'm missing/misunderstanding something about client-side security, so I figured I should just ask people who know more about this.
What I'm interested in is whether, abstractly, there's a good way to secure a client-side SDK like this. Some thoughts:
Originally, I tried to proxy all requests through the server, but then the localStorage functionality didn't work, and I had to fake it out post-request and add a whole bunch of code that the SDK is designed to take care of. This proved prohibitively difficult/messy, especially with Cognito.
I'm also considering creating a server-side endpoint that simply returns the credentials and blocks requests from outside the domain. In that case, the creds wouldn't be in the bundle, but wouldn't they be eventually scannable by someone on the site once that request for credentials has been made?
Is the idea that these secret keys don't actually need to be secure, because adding to a Shopify cart or registering a user with an application don't need to be secure actions? I'm just worried that I obviously don't know the full scope of actions that a user could take with these credentials, and it feels like an obvious best practice to keep them secret.
Thanks!
Can't you just put the keys and such in a .env file? This way nobody can see what keys you've got stored in there. You can then access your keys through process.env.YOUR_VAR
For Cognito you could store stuff like user pool id, app client id, identity pool id in a .env file.
NPM package for dotenv can be found here: NPM dotenv
Furthermore, what supersecret stuff are you currently storing that you're worried about? By "API tokens", do you mean the OpenId token which you get after authenticating to Cognito?
I can respond to the Cognito portion for this. Your AWS Secret Key and Access Key are not stored in the client. For your React.js app, you only need the Cognito User Pool Id and the App Client Id in your app. Those are the only keys that are exposed to the user.
I cover this in detail in a comprehensive tutorial here - http://serverless-stack.com/chapters/login-with-aws-cognito.html

Categories

Resources