I'm trying to arrange being able to login with a social network (initially LinkedIn, but it could be any other, or self-generated from FosUserBundle), and then adding new connections to the same user, via Twitter, FB, Github, etc.
The difficulty is connecting the multiple account connections within FosUser and the HWIOauthBundles. In order to collect as much data as I can, and be able to easily add additional connections to services, I'd really like to have each new connection as a one-to-many record. IE: The initial login with LinkedIn creates a FosUser record, and a new row in a 'socialLogin' table, the next (say login with Twitter) adds a new row to the 'socialLogin' table, that refers back to the fosUser.id.
How can I use the currently logged in (Fos)user as part of the new record that HWIOauth would generate? The end result would be, being able to login with any known user to get into the same account.
The solution is actually easy. First check out Symfony2: How to login using OAuth (HWIOAuthBundle) + custom roles (by default and loaded from DB) which is a great how-to for HwiOAuthBundle, and then scroll down and carefully look at public function loadUserByOAuthUserResponse(){ ... } section.
From there, your workflow will be checking the provider name from the response object. And then based on the provider name, you can update your user (use email for searching). However, with twitter you may have problem because twitter doesn't supply user email. So you need to ask your user for that email address and after you get that, you may need to merge current user account (for twitter based reg, consider it as a temporary a/c) with previous user account with this email.
Otherwise, if your user is already logged in using form/other-social-login (before connecting with twitter) you can add his twitter details once he connects with it. But you need to store user's currently logged in details in session (so that you can fetch it after user comes back with twitter token)
Hope it helps
First step would be to create the relation between the user entity and the social_data table and the rest is all about overriding the custom user provider FOSUBUserProvider.php, which I believe you already have started doing as you have FOSUserBundle and HWIOAuthBundle working together.
I will make some edits with actual code later, but I had to answer this to get you on the track until then.
Related
What I want
I have a list of people with all their personal information (name, first name, date of birth, email, etc.). I created an account for each of these people using their email/phone + a password I generated for them.
I want to send to each of these people an email/SMS with a link allowing them, once clicked :
to be directly connected on our website, without having to type a password or using a third party as Google/Facebook/etc.
and I want the link not to expire after the first use. The user must be able to click on it several times and be connected to our website each time.
What I tried
This is what I tried so far, unsuccessfully :
Passwordless Auth with email link: using both backend and frontend. Doesn't fit my needs because the signin link works only once by design.
Create a custom token with Firebase: as I understood, the token will expire 3600 seconds after creation, which is not useful for me.
Implement anonymous auth: it still need the user to type email+password at some point if you want to convert the anonymous account to a permanent account (because I don't want to use Google/Facebook/etc auth). Plus, it will need consequent changes in all my website code to work.
At this point I realized that Firebase doesn't have a solution that fits my needs. I started to fiddled around as best I could.
The idea
It works as the following:
First I create an account for the user in Firebase + a unique document in a collection in Firestore. That document contains 3 fields: magic_token, email, password.
Then, I create a link to our website with a unique token as a parameter in it. I store the token as magic_token in the document I described above. I send the link to the user.
The user clicks on the link, get redirected to my website. In the front, I detect the presence of the token in the parameters of the URL, I retrieve the document in Firestore with the corresponding token.
Using the email and password stored in this document I call: signInWithEmailAndPassword() to login the user.
PROS:
it fits my needs.
it is easy to implement
CONS:
the user password is visible in Firestore.
it's not very secure.
The question
Is there a proper way to implement a Magic Link that fit my needs? If not, how can I improve my own custom token authentication ?
I've been trying to find a way to figure out if a user is already created with the same email in Firebase, and it doesn't seem like it is possible.
This basically means I will need to save the email for every user and check in the Firebase database if the email is there already.
Is there really no other way?
I see all these posts with... how to link a user with another auth provider, but there is no way to know if the user with the specific mail exists already...
You cannot link an existing account to another account. You can only link a new account to an existing one. If you wish to check if an email of a new account already exists before either creating it or linking it to the existing account.
You can call https://firebase.google.com/docs/reference/js/firebase.auth.Auth#fetchProvidersForEmail
If the email provided already exists, it will return an array of the provider ids. You then sign in the user to the existing account and link the new account to it.
fetchProvidersForEmail will work as expected when multiple accounts per email is disabled in Firebase Console(default behavior unless you are migrating from Firebase v2).
Here is my problem if i can call it that way.I have implemented authentification with custom memebership provider in asp.net mvc 2.0.Everything works well but i have one problem.When user log in he provides its username and password and i check this through databse in MSSQL then i validate user and pass and use FormsAuthentication to set only UserName as profile information.
But when that user wants to create new item(lets say for sale or something) that belongs only to him and can be listed with other items that user created i can use this username(in FormsAuthentication) check it in database and connect that item to appropriate user with foreign key but that works if username is unique so i need additional informations like ID column from database table "user" to store and use it later so what is the most secure and "best practice" way to store additional information of user and use it later because username as i mentioned must be unique in database and it is not enough information about logged user.
Couldn't you store the User object (or whatever additional info you have) in the Session? or using a cookie at the client side (if you need to persist the login state even after the user closes his browser etc)? Let me know if you need specific examples.
EDIT: After reading your comments, if you are looking for a "secure cookie" solution have a look at this: http://www.codeproject.com/Articles/13665/HttpSecureCookie-A-Way-to-Encrypt-Cookies-with-ASP
I use it to store the user's id (only his id). When I retrieve this cookie I load the user given his id. Some in-memory caching allows me to avoid loading the user on each request.
But just wanted to clarify that the session object seems great for what you are trying to do + you dont have to worry about security (for the average app that is).
I have 2 different websites
-> webgrants.com
->calgrants.com can be accessed directly or from webgrants
there is link provided for calgrants.com in Webgrants.com
so how can i validate the credentials of user when they click on the link provided. how can i do this .urgent please
There might be better ways to do it, but off the top of my head you can do this:
Assuming they have access to the same(or a common) database you create a table of userId and ticket.
Whenever a user wants a redirection to other website, you create a random value(ticket) and assign that value to the user and store this pair into the database.
You add this ticket to address of the other website, as a parameter. Other website checks the table for that 'ticket' and authenticates the user.
I am writing a web app for a client. Users will have a one-time key that they will use to initially identify themselves to the app. Once the app verifies that the key is valid it will take them to a page where they can create a normal account to use for all subsequent logins. The create-account page should only be accessible after entering the key and shouldn't be accessible otherwise. I.e, it shouldn't be accessible to users logged in with a normal account.
This is asp.net 3.0 using a custom membership provider.
My plan is to create a temporary account based on the key and authenticate the user with that account. This allows them access to the create-user page (which is protected with a location tag ) where they can create the formal account. I then authenticate them with their new account and delete the temporary account.
The flow is: the user goes to a page where they enter the key. If the key is valid I create the temporary account, call FormsAuthentication.SetAuthCookie, and redirect to the create-account page. This all works, although it seems a little complicated.
The problem is that the create-user page is available to any authenticated user; I only want it available during the time between entering the key and creating the formal account. So I thought I'd create a special role for the temporary account and make the create-user page accessible only to that role and none other. I created my own Principal object with a special role and tried setting it when I authenticate the temporary account but I can't get that to work.
I'm really hoping I don't have to write a custom role provider just to do this.
How can I make this work? There's gotta be a simpler way!
Why not simply create the real account when they enter the key. Assign it some random name and then let them change the name and other details. Then you don't need the create user page, just the enter key page and an account details editing page. If you're concerned about getting the account details filled in, you could set it up (perhaps via code on a MasterPage) so that incomplete accounts always get redirected to the edit details page until the details are entered.
Or, you could have them enter the required details in addition to the key code on the enter key page and simply use those details when creating the account.
My advice would be to avoid the use of temporary accounts when validating the user. Instead, generate your own logic for validating the sign-up key. Then, at the head of the page, you can check whether the user is an authenticated user (SetAuthCookie has been called) and jump to a different page if this is true.
You may even be able to change the page access to forbid this page to authenticated users (I know you can disable accounts for unauthenticated users but I'm not sure if you can go the other direction).
The key, though, is to avoid relying on the membership provider when, in fact, the user is not yet a member!
Assign an "incomplete" role when authenticating against the temporary token, then restrict access to only that role... when the account is created, send them to a re-login page (terminating the authentication token). This will simplify your security model.