I'm new to AWS and I really need help with this. I have an existing RDS Schema with Users table and also with my own Users authentication algorithm/system using JWT. Everything was fine until I reached working on uploading files to S3. I discovered that when uploading to S3. We cannot pass extra parameters but only the body, key, contentType and to which bucket. I wanted to pass extra parameters like the current logged in user's access token (for user validation security), user_id, photo title and caption. But it's not possible.
What should I do? Should I use AWS Cognito User Pools instead of using an RDS Users? If I use Cognito User Pools, is it possible to do a SQL Query like joing a Cognito User and another RDS Table? I'm so confused. I'm sorry if I sound like an idiot. But I really need some help about this.
I hope somebody can. I would really appreciate it. Thank you very much in advance.
I am assuming your upload logic is in Lambda. In this case you can just do your authorization for the upload in the Lambda function. Allow the Lambda function to upload data to S3 by attaching an IAM policy to the IAM role that Lambda uses.
If you upload to S3 directly from a client, then you can either do that without authentication/authorization or use Federated Identities. In this case you can either export all your users to a Cognito User Pool (and keep them in sync) OR create your own Identity Provider and register your users for a Cognito Identity Pool.
The cleanest, but probably also hardest, way is to keep your authentication, integrate with the Cognito Identity Pool via OpenID, SAML or your own method (see http://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html).
You should go that way only if a) your authentication is really good and b) you have verified that having the user in a Cognito Identity Pool actually meets your requirements/business rules.
Related
I'm trying to make a simple (React) website where a user signs in and it gets their data from a MySQL database and displays it in a table on the website. The flow is like this:
Home Page -> Sign In -> App
I want to show the user's data that is stored in a AWS RDS (MySQL) when they log into the App.
I have the domain and static hosting set up. I have a user pool set up in AWS Cognito. I set up an API Gateway with authorization and connected a basic lambda function to it. When the user signs in the are redirected to the App page with a JWT token in the header. I don't know where to go from here.
This is what I'm thinking:
User logs in, redirected to callback URL with JWT token in header.
Get the JWT token, decode it and get the user email
In my Lambda function, connect to the database instance (AWS RDS)
To query user data, select user data from a table whose name is the
users email
I don't know how to do any of the above though (apart from SQL queries). Are these even the correct steps?
How do I get the JWT token in my code? From what I know it has to be passed with every API call? I have my invoke URL from API Gateway, how do I send a request with the JWT token?
What would the database instance look like? Would it be a collection of tables that each represent a user?
How do I do this with and without AWS Amplify?
I've been trying for a few weeks but there's so much info and I feel like I'm over complicating something that is very simple to implement.
Another approach is to use the AWS SDK for JavaScript to query data on the backend and a React front end that displays the data.
This use case is located in the AWS Code Lib here:
Create an Aurora Serverless work item tracker
This example shows how to use the AWS SDK for JavaScript (v3) to create a web application that tracks work items in an Amazon Aurora database and emails reports by using Amazon Simple Email Service (Amazon SES). This example uses a front end built with React.js to interact with an Express Node.js backend.
Services used in this example
AWS Services used in this example:
Aurora
Amazon RDS
Amazon RDS Data Service
Amazon SES
Note that this example focuses on the AWS SDK, such as the RDSDataClient) and not stuff like JWT tokens, Amplify etc
I have multi-tenant application, which exposes some API for our customers to use. I would like to expose it using Azure API Management. Mostly to provide Development Portal to our customers, which I find very useful, and maybe use some other features.
If I understand correctly, our customers will set up their own subscription keys for authentication, which API Management proxy will validate.
Question: How can I link and identify user/subscription to the tenant of my application, to ensure that only data from this tenant are returned.
One direction I can see to explore is to use delegated sign up, which I guess will help me to link subscription to the tenant. But then still the question is how to get user id in my backend API?
Any direction to documentation or samples is very appreciated
You could create separate groups in APIM to represent your tenants and then put users into those groups using delegation hookups. Withing APIM policy in expressions you can reference context.User.Groups to list groups user making the call belongs to and forward that information to backend.
Alternatively you could use Note field to store tenant name and access it as context.User.Note. Or if you're willing to store mapping on your side the just take an id context.User.Id.
All of above could be passed as a header using set-header policy like:
<set-header name="userId">
<value>#(context.User.Id)</value>
</set-user>
All scenarios would require you to have delegation setup to fill this information automatically for every new user created.
I am trying to work out an application using
Dotnet Core 1.0
MySQL as the data store
Authetication and Authorization
Entity Framework
Ubuntu 16 machine
I have succeeded in creating a sample API to fetch data from MySQL database using entity framework. Now I want to introduce Authentication using email as username and Password.
I tried several method from different blogs but unable to achieve this.
What I am trying to achieve is Custom Authentication for the api where user will send username and password to login Api. The login Api will return an access token and refresh token. Using this access token, the user can call other APIs.
Later on I want to add Google and Facebook Authentication too.
Is there a way to do this?
Everything you want to achieve is possible. However there are some caveats.
Yes you can do this. You will need to use the resource owner grant which is turned off in identityserver 4 by default. I suspect the reason for this is because passing user credentials into an application is an anti-pattern, it is there to typically support legacy systems, also it does not authenticate users in the explicit sense because the credentials could come from an un-trusted source (as an example). You can read up about the grant's generic value here. You can find samples here.
The safer pattern is to use something like Implicit Flow which is good practice if you cannot guarantee trust between clients and your API.
As for social logins this is possible. There are tonnes of samples online but here are the official docs.
There is a project on github, https://github.com/diogodamiani/IdentityServer4.MongoDB and a corresponding nuget package that will send you in the right direction. It's obviously MongoDb, but the same premise applies.
I want some guidance as to how to go about this:
I want to have some objects in my S3 bucket by accessible only be a few users (users from my web app). I looked through the AWS docs and it seems as though I need to give each of my users AWS access keys(?).
Obviously I don't want to do this, so is there any way in my app to lock out some users and let other in? I'm using Node.JS and MySQL (to store my users) if that makes a difference.
Thanks a lot for the help.
The very simple description of the S3 access / permission scheme is...Access to S3, like most other AWS resources is based on IAM-centric access controls. So, you can either grant access to your S3 buckets by either granting users access to it (setting it on S3) or granting S3 access to a user (setting it in IAM as a policy). So, whatever or whomever is accessing S3 must be authenticated to AWS. Again, that is a very high-level description and meant to simply point out that access is based on user/role authentication.
Now, assuming your web-app is running on AWS (EC2?), than your EC2 instance has been (hopefully) assigned an IAM role. Once that IAM Role has been assigned the permissions to do so, the application running on the EC2 instance can now access any AWS resource via that Role.
But, you don't want ALL of your webapp users to access S3, so my two thoughts are:
1) Check the users credentials within your app (assuming the user needs to authenticate somehow with your application) and make the determination of whether or not to call S3 based on the users credentials. You would then use the IAM Role assigned to the EC2 instance (an EC2 instance can only have 1 IAM Role assigned to it) and access S3 or not.
This second idea is a pretty bad one and smells bad to me. I'm pointing it out merely as a possibility and to highlight how the use of IAM Users / Roles works.
2) This suggestion would not utilize the IAM Role assigned to the EC2 instance, though I would always advocate for assigning a Role to the instance, you can always lock down that role and deny access to all AWS resources, but you can't add a role to the instance after launched.
Have two IAM Users (S3Granted and S3Denied, each of which obviously have appropriate policies for accessing S3). Each user of your webapp (e.g. Hillary Clinton, Donald Trump, Bernie Sanders and Ted Cruz) would then each map to one of the two IAM Users based on whether or not they should have access to S3. This would be a field in your MySQL database. You wouldn't bother checking the credentials up-front (because then you would just be performing Option #1 and would proceed with the S3 call regardless of the user and S3 will either grant or deny access based on the IAM User account your webapp user is associated with. You technically wouldn't need the S3Denied User (you could just have no user), but I figured it would be cleaner to specify the IAM User.
e.g.:
WebAppUser/Bernie Sanders --> IAMUser/S3Granted
WebAppUser/Hillary Clinton --> IAMUser/S3Denied
WebAppUser/Ted Cruz --> IAMUser/S3Granted
WebAppUser/Donald Trump --> IAMUser/S3Denied
For Option #2, you would then need to store the Access keys for both IAM Users m(S3Granted and S3Denied) somewhere so that you could properly authenticate.
Also, you would need to do a bit of exception handling so that you could properly notify your users that they have been denied access.
Overall, #2 is just a bad idea. It would be much cleaner if you simply had a field in your MySQL database that specified whether or not they can access S3 and either make the S3 call via the IAM Role or refuse to do so within your webapp. Don't leave it to S3 to grant or deny access.
I have an iPhone application that needs to collect data from an online MySQL database. I've written a PHP web service so I collect the data with JSON. The problem is that everyone can see the data if they go to the URL now. How do i secure the data transfer properly?
Thanks for your suggestions.
Typically, if you are showing data private to a particular user, then each user will generally have an account (user id and password). The app will pass the user's credentials to the server before the server will provide the user's data.
You can also do something similar using SSO integration, or OAuth (ala Facebook).
In some cases, your app may only pass the username/password on the initial call and receive a session ID, which the app passes on remaining calls. This allows the server to store session data.
Even if the data isn't private to a particular user, you can use accounts to restrict access and privileges for a publicly reachable web API.
In all of the above cases encryption such as SSL (HTTPS) must be used to protect the authentication mechanisms and data transfer.
I'm assuming your data is public for all users of your app, in other words, you don't want to implement a login mechanism for your users. If you just want to make sure you return the data only to users of your app and not to anyone who happens to enter the right URL in their browser, you will need to sign your requests, so that only requests from your app are accepted by your server.
I use a secret key that my app uses to create a hash/digest of the request which the server verifies (it knows the secret key as well). Also I make sure requests cannot be replayed if they are intercepted by adding a timestamp and a nonce. The timestamp is checked to be within 10 minutes of the server's timestamp (relaxed sync) and the nonce must be unique (server keeps the last 10 minutes of nonces). This way no-one can copy the same request, the server will just serve an error if they try.
This post explains how to sign your requests in a bit more detail:
http://www.naildrivin5.com/blog/2008/04/21/rest-security-signing-requests-with-secret-key-but-does-it-work.html