generate auth0Sub id by email - authentication

Hi there I am new to the Auth0 thing we are creating an app where we use passwordless auth0 user only has to put an email in our app then the auth0 link will send in the user email when the user clicks it will open out the app also the same time the user is created in our user database with
auth0Sub id, this case in staging and dev environment but now in a production environment we only allowed few users for login/signup this time client requirement he has the bulk of user JSON file where user email and information store so my team leader said I have to find an Auth0 related script where I can send(pass) our user JSON file and based on user email I will get
auth0Sub id as a response so that further I can manually store user data with
auth0Sub id in user collection of production environment however I searched google but was not able to find the correct answer

Related

NextAuth - OAuthAccountNotLinked - Imported data from another website - Autolinking

I have OneLogin setup in my application and is working fine. Am using MongoDB database for storing the sessions, accounts and users.
And now, I imported user data from my old WordPress website(which doesn't uses OneLogin, but the native WordPress login).
So basically I imported the user data from WordPress and populated the users collection using the email_id, name, etc. When I login with the OneLogin into my application, it throws the error saying OAuthAccountNotLinked. When researched I can see that you are not recommending the auto-linking of user accounts for safety reasons. But in my case, it's a OneLogin provider that my client's organization that has now started using. And new OneLogin user registrations are manually approved by the admin. So security wise it won't be a problem. We are only using OneLogin as auth provider!
How can I setup auto-linking in this scenario? Because I have 10,000s of Users in my MongoDB collection(imported from old WordPress website). And each User is being requested to manually register at OneLogin using the same email id they were using before in the old WordPress website and is manually approved within the OneLogin.
Thanks
Quote right from the original site
Automatic account linking on sign in is not secure between arbitrary providers - with the exception of allowing users to sign in via an email addresses as a fallback (as they must verify their email address as part of the flow).
When an email address is associated with an OAuth account it does not necessarily mean that it has been verified as belonging to account holder — how email address verification is handled is not part of the OAuth specification and varies between providers (e.g. some do not verify first, some do verify first, others return metadata indicating the verification status).
With automatic account linking on sign in, this can be exploited by bad actors to hijack accounts by creating an OAuth account associated with the email address of another user.
For this reason it is not secure to automatically link accounts between arbitrary providers on sign in, which is why this feature is generally not provided by authentication service and is not provided by NextAuth.js.
Automatic account linking is seen on some sites, sometimes insecurely. It can be technically possible to do automatic account linking securely if you trust all the providers involved to ensure they have securely verified the email address associated with the account, but requires placing trust (and transferring the risk) to those providers to handle the process securely.
Examples of scenarios where this is secure include with an OAuth provider you control (e.g. that only authorizes users internal to your organization) or with a provider you explicitly trust to have verified the users email address.
Automatic account linking is not a planned feature of NextAuth.js, however there is scope to improve the user experience of account linking and of handling this flow, in a secure way. Typically this involves providing a fallback option to sign in via email, which is already possible (and recommended), but the current implementation of this flow could be improved on.
Providing support for secure account linking and unlinking of additional providers - which can only be done if a user is already signed in already - was originally a feature in v1.x but has not been present since v2.0, is planned to return in a future release.
You probably need to write your own implementation to handle such a situation. And call that implementation on each provider call back. Like a check, the email already exists in DB, through an extra level of verification like OTP etc. Finally, when everything passes, let the user in and store some extra info in the DB for future reference.
Since I wasn't able to find a straight forward solution, I come up with a workaround. It's not a perfect solution, but does the job. Maybe someone else will post a better solution here.
So what I did is, I have all the old user data imported to the users collection in my MongoDB database. And NextAuth uses this users, accounts and session collections to store the User and related data. Btw am storing the session data in database.
In my case, we have sent unique OneLogin registration URLs(created from the OneLogin Admin Dashboard) to our existing users for them to create a new account in OneLogin. Then when the User registers an account at OneLogin, the admin approves/rejects the User. If they are approved, they will be eligible to login to our app using their OneLogin credentials.
What I noticed is that, when a User tries to login, NextAuth checks the email field in users collection to find a matching record. Since we imported the Users from WordPress database, we only have records in users collection and nothing on the accounts collection. In accounts collection, NextAuth is storing the access_token, user_id (mapping to users collection), provider details, etc.
So during login, the NextAuth does the internal checks and finds the existing email in the users collection, but it fails to identify the user as there's no info about the provider(OneLogin) details.
Record from accounts collection:
So what I did is, updated all records in users collection by appending a _TEMP to the email field's values. For example, if there's a record with the value abc#abc.com, it will become abc#abc.com_TEMP
Then what I did is, I wrote an API route(/api/check_old_account) in my NextJS application, where it does the following:
gets the currently logged in User's email id (from NextAuth session)
searches the users collection for the same email id with a "_TEMP" at the end
if there exists a _TEMP version of the currently logged in User, then return a response saying an old account exists
Then in the HOME page, I wrote the code to call the above mentioned api (/api/check_old_account) if the User is logged in. This call is made only once in the HOME page, when everything is loaded. Here the login using OneLogin works without errors because we renamed the existing email id in users collection by appending _TEMP. So when User logins, the users collection inserts a new record with their email and related data to the accounts collection also. Basically there would be two records in users collection for that User now. One is their original email id record that got inserted now when the logged in (eg: abc#abc.com) and their old imported account (eg: abc#abc.com_TEMP). The reason why I wrote the code to call the API in the HOME page only is because, after User logs in, they will be redirected to the HOME page. So thought it won't be necessary to write the code globally or somewhere else.
So, if the above API response says that there's an old account that exists, I display a warning popup to the User saying that there's an old account existing in the database and asks whether they want to link that old account. If the User presses YES button, I make an API call to /api/link_old_account. In this API route, the code is written to perform this:
if there's a _TEMP version email of the currently logged in user in users collection, find the respective record _id that has mappings in the accounts collection.
then change the value of the userId field of that respective record(currently logged in user id) in accounts collection, with the user id of the record with the _TEMP version email.
then delete the record with the _id of the currently logged in user
then update the email field by removing the _TEMP from it
then deletes the records that matches the currently logged in user in the userId field of sessions collection. So that the currently logged in sessions of this User would be invalidated.
then redirects the user back to the HOME page using res.redirect(307, '/')
The solution seems to be working fine so far.

How do you store user information in firestore if they don't have an account?

I am trying to create an app using firebase auth and firestore where new users can be invited via email to work on a project. The problem is, I do not know the best way to store the temporary user project permissions before they have a uid. I want the user that got invited via email to get access to the project upon opening the link sent to them.
I had tried two different ways
Having a sub collection doc for every user in the project
/project/{projectId}/users/{userId}
When a new user is invited, the userId was set to their email, having a cloud function that triggered when a new user was created to send the invite email to the user. Once the user opened the link, it deleted their user document and a cloud function ran that created a new doc with the users id now that they had once since they were authenticated.
This worked, but left a 10 second period where the user can't interact with the project because the cloud function for making the new user doc is running. Also it just seemed like a bad way to do it.
Having a single document with all of the user information
/project/{projectId}/users/users
users:{
roles: {
users_id: 'admin',
new_user_email: 'admin',
}
}
This one I was not able to get to work as firestore does not let you create a key with a period in it, but if there was a way around this, it would work as well. I had also set up firestore security rules which made it so they could only edit fields where the key was there uid or their email if they were not an editor/admin.
Consider creating an anonymous account in Firebase Authentication first, which requires no input from the user. It will receive a UID that you can use to store data for that account. Then, you can convert that account to a normal account after the signup or login succeeds.
Since you didn't say which mobile platform you're using, I linked you to the web docs, but the procedure is generally the same for each one.

External Login Account vs. Native Login Account

I am brand new to Visual Studio 2012 and MVC 4, and I've been working with the SimpleMembershipProvider via the WebMatrix.WebData library.
I'd like to integrate Facebook as an external login source down the road, but it's not a requirement as of right now. However, to get a decent feel for what it would take, I've been following the tutorial and guide found here - http://www.asp.net/mvc/tutorials/mvc-4/using-oauth-providers-with-mvc.
My question :
If a user has already been created using :
WebSecurity.CreateUserAndAccount(model.Email, model.Password);
WebSecurity.Login(model.Email, model.Password);
Can they be "upgraded" to an oAuthMemebership account in the future, if they choose to use their Facebook credentials instead of the email and password they created when first signing up?
I couldn't find a clear answer to this question in the guide, or elsewhere, so I'm hoping someone can clarify how that process may work.
The SimpleMembership setup allows for a local and multiple OAuth logins all sharing the same UserProfile - so a single user can login with either a local password, or FacebOogLiveWitter.
(I should state, that I'm assuming in this answer that the OAuth provider does not send back a matching piece of information for a local account. If they do then the principles of actually performing the merge are the same, but the complexity and steps are vastly reduced.)
The OAuth registration process will refuse the user if they use an existing user name, rather than try and merge two accounts. Therefore this isn't simple, you'll have to build the functionality yourself. The process is complex as there are many directions the user can approach this from (so you could simplify by only supporting one or two), and you need to enforce security as well in case someone tries to merge into an account they don't own.
I will assume you are comfortable with the link you've posted, and you've followed the Facebook help at (for example) Facebook Login and The Login Flow for Web (without JavaScript SDK) so you have a working test application.
Your general process has to have multiple user journey approaches to make sense to a user:
for a logged in user (with a local account)
let them login to facebook and associate the accounts
let them merge an existing account on your site which uses a facebook login
for a logged-in user (with a facebook account)
let them create a local account
let them merge an existing local account on your site
for a non logged in user who tries to register a local account
let them merge this new account with a facebook login that is already registered, and do that as part of the registration process
for a non logged in user who tries to register (or log in for the first time with) a facebook account
let them link this with an existing local account as part of the registration process
etc.
ASK PERMISSION
(You can skip this if the OAuth provider has sent back a matching identifying piece of information, such as an email address).
You should enforce confirmation security, usually through email confirmation sent to the target account of the merge. Otherwise:
someone can login to your site with facebook for the first time
during that process say they "own" the email address or username of a local account (remember, facebook won't necessarily confirm what their email is for you)
and therefore gain access to the existing local account
So, once the merge "request" is made, you need to ask for permission to proceed from the target account of the merge.
The MVC 4 AccountController
I will use Facebook as our OAuth example. To compare what happens when you register a user on your local authentication framework vs. OAuth:
Local: creates an entry in webpages_Membership and an entry with the same UserId in UserProfile (assuming you are using the default tables for the MVC 4 application template)
OAuth: creates an entry in webpages_OAuthMembership and an entry with the same UserId in UserProfile
Now let's look at what happens when a user signs in using Facebook for the first time:
They click on Login using Facebook (or whatever your button says)
they get taken to facebook to login
they succeed (let's assume that, and ignore the failure case)
they then get sent, invisibly to them, to /Account/ExternalLoginCallback
OAuthWebSecurity.SerializeProviderUserId is called, passing the OAuth details to that Action
They get redirected to /Account/ExternalLoginConfirmation and asked to provide a username for their new presence on your site
If that user name is available then UserProfile and webpages_OAuthMembership entries are created
This process is your chance to "join" the accounts by matching some unique piece of information. As long as you end up with the same UserId in UserProfile, webpages_Membership and webpages_OAuthMembership you should be ok. So we have to intercept the process at the point of /Account/ExternalLoginConfirmation.
If the OAuth provider has sent back a matching identifying piece of information, such as an email address, this becomes simple, test for this in the ExternalLoginConfirmation action, and auto-merge using a similar process to the one outlined below.
However, I think you can't/shouldn't assume that the user uses the same email address for your site and OAuth, (nor should you for many reasons). Also, probably in the T&Cs for something like FacebOogLiveWitter it stops you asking for the email of their account anyway, and if they don't currently they might in future.
So instead, you could link the accounts based on alternatives, like username or email address, or phone number. Either way you are going to need them to input some identifying piece of information that is unique against an account, and will pull back the target account.
Wrapping up
So to put this all together: In the first part of this answer I outlined how you will need to consider multiple user journeys to merge accounts. I will use the example 4.1.
Your process will need to:
(Assumption - when a user first registers with a local account, you ask them for an email address and validate it or assume it is valid)
Let the user login with facebook for the first time
at Account/ExternalLoginConfirmation ask them if they want to
Create a new account with you
Use their facebook login to access an existing account
Assuming the latter, then you log a request in a new table (maybe "MergeAccountRequests") with:
The facebook account UserId
The target merge local account UserId
An authorisation code to use in the email you need to send
(From this point on, if they login without confirming that merge, they will have to get sent to a page to ask them to confirm, rather than create objects in other db tables which you have to worry about later)
You then send an email to the address of the target merge (local) account asking for permission to complete the merge (a standard confirmation email, with a link)
When they click on that link, or enter the code you sent them (you could use SMS as well as email) then you need to merge the two accounts
Choose the "new" and "target accounts (in this case "new" is the facebook account as you don't have data associated with it yet)
Delete the UserProfile of the "new" account
Change the UserId of the "new" account webpages_OAuthMembership table to the same as the "target" account
Log the user out (so there are no complications depending on which account they are currently logged in with)
Display a message to the user telling them the merge is almost complete and that they can now log in with either account to confirm and complete the merge
Rather than send them to a login page, i would give them the login options alongside the confirmation message.

Binding custom register and facebook login for SQL database

I am trying to create an app with SQL database connection. Like other apps, user should have the option of both custom register(email,password) and facebook login.
If user choose custom login thats fine, but if user choose facebook login my app would be able to retrieve email from facebook yet no password.
In most apps if you choose facebook login, after login with facebook you never deal with register and logging again (Single sign on, and access token).
But How other apps let user register without choosing a password? Do they let password field null in database (that doesnt seem feasible)? Or do they create a random password for user and save it to users device? What if user logs out or delete their facebook account and wants to login to my app, how would they login without password since in first place they have chosen facebook login?
I know multiple question but they are all related and I am having a difficult time understanding that simple task.
Thanks
M. Fustang
In general if you allow people to register using Facebook, you can force them to set their username and password for this website on first time they log in. And simply store user's id from Facebook as a column in users' table together with username and password provided by user. And then allow them to login using this user/pass data for your website or using Facebook. This will allow your users to log in even after Facebook's account removal.

facebook one-login authentication

Im adding facebook one-login to my website. Just wanted to get some feedback from people who have already implemented it.
At the moment im allowing user to login to my site using fb:login, providing they have a valid account on fb and login successfully, if the same email address thats returned from fb matches my email address I hold in my own database, they will automatically be logged in to my site.
The problem I have is, im finding hard having just the email as my main authentication between the user and the my site. For those who have already implmented this, could you please share some of you loggic (theory) on how you autenticate the user when you're logging them onto your site.
I had the same problem than you. I had users in my database with their name and email address and I wanted to add the Facebook connect plugin.
Now, on the login page, I let users choose between standard and Facebook login. If one choose Facbook login I retrieve his Facebook ID with the Facebook PHP SDK (see on github) :
$facebook = new Facebook(...);
$id = $facebook->getUser();
If I have this Facebook ID in my records, I log the user in.
If not, I retrieve his email adress :
$profile = $facebook->api('/me');
$email = $profile['email'];
If I have this email in my database, I store the facebook ID in that record (for the next time) and I log the user in.
If not, I create a new record with the Facebook ID and the email. After that, the user can set a password in his settings to be able to log in with the standard login (without Facebook).
You may want to check the example of the Facebook PHP SDK out to better understand how the flow works.
Hope that helps.
I have also done this. I have now understood that you do you want to match the email address that if user changes his email address you want to update it. Its simple solution is that store the user information in your database. What I have done, I store the user profile id returned by the facebook as user name and by converting into md5 I store the same profile ID as password and email adress returned by the user. Now every facebook user has its unique id in my database. Whenever user comes to my site and logins with facebook, There are two cases
1- I compare the profile id with my database and if record found I always update the email address in that particular field returned by facebook.. Now I can have the latest email address of the user. 2- if the user is not in my database then I insert the record by applying the above method.
Hope it will help you