My main question is what is the typical way mobile apps authenticate users? I know that AmazonCognito is used to sync userdata once you receive a token, but that token is simply a set of access rules, right? Which has nothing to do with a particular user (just the fact that they are an authenticated user in general).
But before even that, there needs to be a way to authenticate a username/pass that the user signed up for so that you can retrieve the token. In almost all of the documentation, they use Facebook/Google/etc as examples of third party providers, and there IS an example of setting up your own 3rd party provider, but this all requires your own backend to service that. C
onsidering that there may be many users trying to user the app and authenticate, does it not seem like a bad idea to set up a backend somewhere else? And is there a way to integrate this part into AWS as well so that there is no custom backend work? How is this typically done?
Site node: I'm using Android SDK at the moment.
Thanks :)
AWS Cognito has two different purposes. One is to synchronize data as you described in your question.
The other one is to help to manage user identities and create the glue between external Identity Providers (your own, Facebook, Google or Amazon) and AWS.
Here is the workflow at high level. Details are available at http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html
Using AWS Console, create a Cognito Identity Pool
Associate two IAM Policies to your Cognito Identity Pool. One for the unauthenticated users and one for authenticated users. Best practices is to grant least privileges to both category of users. The AWS Console will help you to go through these steps and will propose reasonable default values.
In your code, initialize your CognitoCredentialsProvider object as this
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
myActivity.getContext(), // get the context for the current activity
"AWS_ACCOUNT_ID",
"COGNITO_IDENTITY_POOL",
"arn:aws:iam::AWS_ACCOUNT_ID:role/UNAUTHENTICATED_ROLE",
"arn:aws:iam::AWS_ACCOUNT_ID:role/AUTHENTICATED_ROLE",
Regions.US_EAST_1
);
In your code, proceed as usual to authenticate your users (using your own provider or Facebook, Google or Amazon)
When you will receive the token issued by the Identity Provider, associate it to Cognito. The Cognito SDK will transparently trade this token for a temporary AWS Access Key, Secret Key that service clients can use.
Give the credentials provider to your service client object, such as
AmazonDynamoDB client = new AmazonDynamoDBClient(credentialsProvider);
This approach allows you to avoid to deploy your own backend as broker to AWS services. Most service calls can be made directly from the mobile app, allowing a good level of scalability at a low cost.
Backend of your own is only required to offload some computing task of your mobile devices or if you want to implement your own Identity provider and make it interact with Cognito (see detailed workflow at http://mobile.awsblog.com/post/Tx2FL1QAPDE0UAH/Understanding-Amazon-Cognito-Authentication-Part-2-Developer-Authenticated-Ident)
Related
I have an android app which communicates with Google cloud api services like speech to text, translation, NLP etc. The application is using a service account to do this and the private key file is stored in the application itself. I understand that is a bad practice as anyone can see it using dissembler but I am not sure where else to store it for an android device.
The following post suggests to store this file on a build server:
https://brightinventions.pl/blog/securing-your-google-service-account-key-in-builds/
However, I think that it does not fix the issue as the service credential file is getting included in the publish package.
Please let me know if you can think of a solution.
Do not embed service account credentials in applications. Service Account credentials have a permanent lifetime which means you will be breached. You can delete service account credentials, but then you will have to re-release your application.
You have several options:
Implement Google OAuth so that your users authenticate with Google Accounts. When authenticating use the correct Google OAuth Scopes to provide temporary permissions.
Implement temporary access tokens. Your users will connect to your website, authenticate and your code will give them a temporary access token created from service account credentials. This access token will expire. The default is 3600 seconds but you can control this.
You users will make all requests thru your website API's. You control authentication of the users. Your website code then makes the API requests on behalf of the users. This is not an ideal solution as all traffic goes thru your website (Compute Engine, App Engine, etc.) and you will pay for that bandwidth.
I want to create an android application and use AWS s3 as a storage service to allow the user to upload and download files. I have studied something about S3 REST service, which can help me achieve the same, after configuration of IAM Role for Bucket etc.
Now thing is, I want only the registered users of my application/ with access control configured at my web server(username/password) should be allowed to upload/download the file and not anyone with only app access should be allowed.
Look the link below as well, to have some idea about AWS S3 upload file using REST
http://www.tothenew.com/blog/file-upload-on-amazon-s3-server-via-rest-api-call/
Putting simply, in addition to that described in the link above, I just need the answer to the following questions:
1) How to allow only registered users?
2) Is it good practice to hard code AWS S3 secretKey etc in the production application.
3) Does hardcoding these values in my app could lead to a scenario where even an unregistered user of my application could be able to upload/download the file to aws s3?
All suggestions are welcome, if-if they solve part of the puzzle, as I am completely unaware of the solution
It would be very helpful...,
Thanks in advance,
For sure it is not best practice to hard code secret keys inside your codes..
Now if you want to separate the authorized and the unauthorized users one AW services that does this job and more is AWS Cognito . You can find a lot in the aws documentation https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-console.html
A few things for Cognito :
You have Amazon Cognito User Pools tha provides :
Sign-up and sign-in services.
A built-in, customizable web UI to sign in users.
Social sign-in with Facebook, Google, and Login with Amazon, as well as sign-in with SAML identity providers from your user
pool.
User directory management and user profiles.
Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover
protection, and phone and email verification.
You have Amazon Cognito Identity Pools (Federated Identities) that provides :
Users in an Amazon Cognito user pool
Users who authenticate with external identity providers such as
Facebook, Google, or a SAML-based identity provider
Users authenticated via your own existing authentication process
This how it works in my application
Ask user register/login using aws cognito
deploy an api via api gateway that acts as proxy for S3 services
For the api , apply AWS cognito as Authorizer in api gateway
This however has a limitation on size of object
The option I have tried is use signed urls, and this is spit out by back end application upon registered users access requests.
My implementation includes below
1. Client requests signed urls using an api with a lambda implementation
2. Lambda generates signed urls and passes on the response.
3. while creating signed urls, key/id are used from a parameter store (see EC2 parameter store) secured against role and with a KEY.
I think from your use case , EC2 parameter store (instead of database) should be sufficient to securely keep secretes.
I am creating a native Android app which currently uses Firebase Auth to handle user authentication. I have a MySQL database behind a PHP site and I'm building a RESTful API to access those services. I would like users who are authorized to be able to access limited features and data.
In this scenario, what would be the approach to handling the permissions on the backend server? I'm new to Auth techniques such as OAuth etc, but I get the feeling that might be part of this solution, so feel free to talk to me like I'm an idiot. :)
[edit]
My backend has similar permissions to Facebook; such as content is visible as either private, friends or public.
Regards
It depends on your security design.
The easiest way is to have a role-based security - use OAuth2/OpenID Connect just for authentication (ask for an ID token, not access token). Then you must get a list of roles for an authenticated user. The roles could be part of the ID token or the API server could get them from another source (e.g. its database). If the role retrieval is an expensive operation, you could consider issuing your own token (JWT) containing all the info you need.
If you wanted to delegate just some of user's permissions to the mobile app, you could register the API scopes (permissions) to the OAuth2 server and the app could ask the user for some of them. As an example, if your application wants to access Google services on behalf of its user, the application asks for an access token with specific scopes (e.g. reading GMail inbox). But this is probably not what you want.
Edit:
If the objects you deal with have access rights defined on themselves (private, public, friends visible), then just get a user identity (ID token) from the OAuth2 server and check the permissions when someone requests such an object by your API. OAuth2 itself cannot help you with that.
And for your Android app, use the Authorization Code Grant Flow as described in the OAuth2 for native apps RFC.
I would like to discuss a common scenario: An app wants to authorize users using multiple OAUTH providers, such as Facebook, Google+ or Twitter.
Essentially this question has been asked two years ago here Mobile API Authentication Using Existing Web App with Multiple OAuth Providers and stays unanswered, so I will elaborate a bit further. (I will use Facebook as an example for the OAUTH2 provider, so this does not become too generic.)
Essentially, user registration works like this: OAUTH/OAUTH2 providers typically provide a workflow where a (mostly short-lived) token is obtained from a provider either via the AccountManager on the mobile device or a login dialog such as the "Login with Facebook" button. The token is then shipped to App Engine by calling a REST endpoint (either in the body or as an additional header, never in the URL).
The provider's AppId and AppSecret (here: Facebook) are store on App Engine and App Engine adds these to the token, then ships it back to Facebook in exchange for a (long-lived) token.
At this point both, client app and App Engine app have certainty that the user has been previously authenticated by Facebook. Also, if Endpoints Authentication is used to authenticate the call, App Engine probably has the Google credentials of the user and/or the ClientId of the app, and Google guarantees that the request has been made from the correct client app.
At this point, we can try to find the user in our datastore and let registration fail (or silently sign in the user) if it already exists, or otherwise create a record.
Until here I am pretty sure I'm on the right track. Now comes the problem:
Let's look at the datastore for this. Let's assume we have two entities:
User entity, where each user in our own system is registered under a unique user id.
Account entity, where each account is registered and where a userId field points to the User entity.
In relational database terms, we would say we have a 1:n relationship between User and Account.
For each User in our system, we keep a User record. In above example, we may have two accounts: Facebook and Google, which both point to the user and where the unique Facebook or Google id/email is used as account identifier.
Technically it would now be possible that the app uses the Facebook or Google account on subsequent requests. But we would have to store and look up the 3rd-party token on each request because we cannot decrypt it ourselves. We could ask the provider to do this, but that wouldn't make much sense either. Plus we would have to translate the provider's Account id to our own User id on each request.
To solve this problem I would most probably either create our own token or set up our own OAUTH provider which creates a token signed by our own system, and where the unique User id is used as identifier, and only use that token during subsequent requests.
Is this a good approach? Is anybody using a different better workflow? Does anybody see security flaws with this design?
Essentially it works around Google's endpoints system, but Google can only authenticate against their own systems, so if we want to offer sign-in using further providers, we will need to work around this, except if anybody knows a workflow where we can keep both, but then we have the problem that we can/should only add a single token in the "Authorization" header and REST principles discourage us to use custom headers to ship more tokens.
When your app authenticates a user, store an object in a session which contains an oauth provider that has been used to access the app and, optionally, a token to be used for subsequent requests.
Now you can check for this object in every call to the server. If the object is not present - a user is not authenticated, redirect to the login page. If an object is present, take a token and use it.
I use a similar approach for multiple authentication options, not only oauth. Except I don't need to store a token after a user is authenticated - I have no use for it within the app.
How to access DynamonDB of Amazon Web Service from Android SDK without through Token Vending Machine?
There are a few options, including one that was introduced by AWS very recently.
One option is to use Web identity Federation. Here, you put code in your app to have users log in with an identity provider like Login with Amazon, Google, or Facebook login, and as a result, your application gets temporary AWS credentials, when can be restricted to particular items or attributes in your DynamoDB tables using Fine-grained access control.
The new option is a service called Amazon Cognito, which is a simple user identity and data synchronization service geared toward mobile apps. I encourage you to take a look at this service and watch the short intro video to see if it suits your needs. Even if you don't use the data synchronization component, you can still use the user identity management component, and have the same fine-grained access control capabilities as the other solution, but with additional login and user management capabilities like unauthenticated guest access.