AWS: Authorize users to specific clients - javascript

So I have the following setup on AWS Cognito:
AWS Cognito User Pool: UserPool_1
Under this User Pool I have 3 users defined: Mike, Sarah, John
I have 3 App Clients under thhis user pool:
WebClient_1
WebClient_2
WebClient_3
I want Mike to be able to access: WebClient_1, WebClient_2, and WebClient_3
I want Sarah to have access only to: WebClient_3
And John to have access only to WebClient_2
Currently all users are able to access all 3 web apps defined under this user pool, that's not what I want.
How do I restrict users in the user pool to have access to specific app clients?
So let's say Sarah tries to access WebClient_1, I want her to get a message saying: "User not authorized"
How do I achieve this?

The way I would solve this is with the Cognito Pre Authentication Lambda. When a user requests authentication, the Cognito trigger runs a custom Lambda script. In your Lambda script you will receive an event with some common parameters. You can take the parameters callerContext.clientId and userName and do some processing. For a few users you could just keep the user-client mapping in the script, but more likely you will want to look up the mapping in a database like DynamoDB.
Edit: To accept the authentication you do callback(null, event); and to reject it you do callback("you are not coming in", null);

I was able to solve this by utilising multiple pieces:
User Migration Trigger
Pre Authentication Trigger
Attempting to utilise just the Pre-Authentication trigger results in an incomplete and insecure solution. The trigger only runs when a user attempts to authenticate against the user pool. This means that after a user has been authenticated for an app client they have permissions for, given the URL for any other app client, the user will be able to access it.
As a workaround, I decided to go for a different setup where I have a separate user pool for each app client and one general pool to store all my users. This obviously can get annoying when it comes to creating the same accounts in each user pool, so I mitigated that by using a migration trigger.
For example, on Sarah's first sign-in attempt to WebClient3, the migration trigger runs and imports her data to the new user pool while also preserving her password. You can combine the functionality for the pre-authentication trigger into the migration trigger such that if a user shouldn't have access to that app client then the migration fails.
A caveat here is that if the user is created by an admin with a temporary password, then they would need to first reset the password using the first pool's client before the migration can work. Also, after the migration process, the user's account is now independent of the general pool which may lead to inconsistencies if not managed properly.

Related

How to write firestore rules for one to one chat app?

I made a one to one chat app for a website using firebase and firestore. Now I want to write the firebase firestore rules for the same. The app works this way ...first if the user is sandeyshc#gmail.com then the user gets the chatids and friends gmails...then the user checks in the messages tab with chatids and get all the chat related details. Now I want to implement firestore rules for this app. How to implement it?
The best way to solve that is to use a combination of firestore rules and cloud functions.
First of all both users should have the same chat stored on different locations.
With the firestore rules you should restrict for each user to only change his own chat and only to be able to write his own messages in that chat.
When he writes his own message a cloud function should be triggered that sends a push notification to the other user and also writes that message to the chat of the other user by using admin rights in the cloud function.
That way both users have the same chat in different locations. You could do it also by giving them access to a single chat but consider in future the use case that one user can delete chats or messages. You probably don't want that one user can delete the messages from the other one.
Also one importand note: awoid saving users under they're email. You should store them always under the Application Auth User Uid. Emails can have chars that are not supported as database keys and you can get in other different bugs in future by using the email.
Here is an example of a open source chat app made in react and firebase. It uses the realtime database but you can easyly reuse the concept. You can see there how the functions are written and how to use it on the frontend.

Use separate server for centralized users database

I am using Meteor 1.10 + mongodb.
I have multiple mobile chat & information applications.
These mobile application are natively developed using Meteor DDP libraries.
But I have same users base for all the apps.
Now I want to create a separate meteor instance on separate individual server to keep the users base centralized.
I need suggestions that how can I acheive this architecture with meteor.
Keeping reactivity and performance in mind.
For a centralized user-base with full reactive functionality you need an Authorization Server which will be used by your apps (= Resource Servers) in order to allow an authenticated/authorized request. This is basically the OAuth2 3-tier workflow.
See:
https://www.rfc-editor.org/rfc/rfc6749
https://www.oauth.com/
Login Service
You will also have to write your own login handler (Meteor.loginWithMyCustomAuthServer) in order to avoid DDP.connect because you would then have to manage two userbases (one for the app itself and one for the Authorization Server) and this will get really messy.
This login handler is then retrieving the user account data after the Oauth2 authorization request has been successful, which will make the Authorization Server's userbase the single point of truth for any of your app that is registered (read on Oauth2 workflow about clientId and secret).
Subcribing to users
The Auth server is the single point of truth where you create, updat or delete your users there and on a successfull login your local app will always get the latest user data synced from this accounts Auth Server (this is how Meteor does it with loginWith<Service> too)
You then subscribe to your users to the app itself without any ddp remote connection. This of course works only if the user data you want to get is actually for online users.
If you want to subscribe for any user (where the data might have not been synced yet) you still need a remote subscription to a publication on the Authorizazion server.
Note, that in order to authenticate users with this remote subscription you need an authenticated DDP request (which is also backed by the packages below).
Implementation
Warning - the following is an implementation by myself. This is due to I have faced the same issue and found no other implementation before mine.
There is a full working Accounts server (but constantly work in progress)
https://github.com/leaonline/leaonline-accounts
it uses an Oauth2 nodejs implementation, which has been wrapped inside a Meteor package:
https://github.com/leaonline/oauth2-server
and the respective login handler has also been created:
https://github.com/leaonline/meteor-accounts-lea
So finally I got a work around. It might not be the perfect way to handle this, but to my knowledge it worked for me so well. But yes I still open for suggestions.
Currently I have 4 connecting applications which are dependent on same users base.
So I decided to build SSO (Centralized Server for managing Users Database)
All 4 connecting applications ping SSO for User-Authentication and getting users related data.
Now those 4 connecting applications are developed using Meteor.
Main challenge here was to make things Reactive/Realtime.
E.g Chat/Messaging, Group Creations, Showing users list & listeners for newly registered users.
So in this scenario users database was on other remote server (SSO), so on connecting application I couldn't just:
Meteor.publish("getUsers")
So on connecting applications I decided to create a Temporary Collection called:
UserReactiveCollection
With following structure:
UserReactiveCollection.{
_id: 1,
userId: '2',
createdAt: new Date()
}
And I published subscription:
Meteor.publish("subscribeNewUserSso", function () {
return UserReactiveCollection.find({});
});
So for updating UserReactiveCollection I exposed Rest Api's on each connecting application respectively.
Those apis receive data from SSO and updates in UserReactiveCollection.
So on SSO side when ever a new user is registered. I ping those Apis (on connecting applications) and send the inserted userId in the payload.
So now those connecting applications receives onDataChanged ping from the subscription and gets userId.
Using that userId the connecting applications pings back to SSO and get user details of that specific userId and prepends to the users list.
Thats how I got it all working so for now I am just marking my answer accepted but as I mentioned above that: "It might not be the perfect way to handle this, but to my knowledge it worked for me so well. But yes I still open for suggestions."
And special thanks to #Jankapunkt for helping me out.

Can Custom Authentication be made in Firebase

I am trying to use a 6 digit code to log-in a user.
The code is available for 20 seconds and is unique to every user.
Briefly explained:
User is already logged in on a mobile app
User press the button "Get Unique Code"
Then, user enter the code on a WebPage on his PC
If the code is correct, show data for that user
What am I asking is if there is way to properly authenticate the user who introduces that code correctly given that I have the userID and all the informations about the user?
I can try and "fake log-in" (display all the information for that user when the code is correct) but there are some issues with this and I would like to avoid it.
I am using Firebase Authentication and Firebase Firestore. JavaScript is used for Web.
You can implement any authentication scheme you want by creating a custom provider for Firebase Authentication.
See Authenticate with Firebase in JavaScript Using a Custom Authentication System and Creating Custom Tokens with the Admin SDK.
In this flow you:
Sign in the users yourself.
Create a custom token for those users in a trusted environment, such as a server you control, or Cloud Functions.
Pass that custom token to Firebase Authentication, which can then use it to identify the user, and secure access to Firestore, Storage, and Realtime Database.

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

Integrating Auth0 authentication with existing user database

I've a requirement to integrate Auth0 in our project (Reactjs/Hapijs/MySQL). I checked the documentation and they have many examples and that is great, however, I can't find any related to how exactly do I use my existing user database.
In my application I have users and those users can have one or more projects. With the authorization that we currently use, a user logs in, I check what projects does he own and send it to the React application.
I am missing a document that explains me how to use Auth0 and still be able to check in my database what projects user owns.
My idea on how that should work (I might be wrong):
User sends username and password to our server
Our server makes request to Auth0 (with provided credentials)
Auth0 replies back to our server with some token
We look in users table in our database and try to verify the existence of that user
If it is a match then we simply look (as we already do) for user projects.
Is this how it is supposed to work?
There are a few options available for scenarios where you want to integrate Auth0 with applications that already have existing user databases. You can either:
continue to use your existing store
progressively migrate your users from your custom store to the Auth0 store
You don't mention it explicitly, but judging from your expected flow it seems you would be wanting to implement the first option. There is specific documentation that you can follow that explain how you can setup your custom database connection, see Authenticate Users with Username and Password using a Custom Database. It mentions MySQL, but others database servers are supported and there are many templates that will allow you to quickly setup things.
When you complete this the final flow will be the following:
Using either Auth0 authentication libraries (Lock) or your custom UI you'll ask the user for their credentials
Either Lock or your custom UI submits the credentials to Auth0 authentication API
Auth0 authentication API validates the credentials by calling scripts that execute against your custom database (these scripts were provided by you when you configured the database connection)
If the credentials are valid the Authentication API will return a token to the calling application that will have user information and proves the users is who he say he is.
The scripts you need to provide are the following, but only one is mandatory:
Login script (executed each time a user attempts to login) (mandatory)
Create user script
Verify email script
Change password script
Delete user script
The optional scripts are only required when you want to provide the associated functionality through Auth0 libraries, if only need the login to work then you can skip them. The login script, in the case of a valid user, is also where you return the profile information of the user, for example, you could in theory include their owned projects in the user profile.

Categories

Resources