I want to allow users to sign up to my website using Facebook. I already use the JS SDK on the client side for authentication and authorization and the C# sdk on the server side to get all the information I need to complete the user profile.
My issue is that I order to allow the user to login with his facebook account, I need to create a username and password for him in my membership provider.
I already decided I'll use the Facebook email as the username, but what can I do about the password? How can I later authenticate him?
Thank you!
Edit: What I am actually asking is: Once the user authenticates via Facebook for the first time and I have all his info, how would I go about maping that info to a membership user (in terms of username and password) and how would I go about loging him back in (sending him a memebrship cookie in the response) the next time he wants to login with his already created user. I know I need to authenticate via facebook each time, but I'm considering how I deal with the asp.net membership side, not the Facebook side of things. Sorry if I was unclear before :)
Facebook uses OAuth 2.0. The only way you can authenticate a user is by sending the user to a Facebook login page, and redirecting back using their OAuth implementation. This essentually provides you with a user specific time limited access_token
.
It isn't really a good fit for MembershipProviders, although it is possible to request offline_access permission which allows you perform authorized requests on behalf of the user at any time. The user has to agree to this. Facebook T&Cs are that you can't deny the user access to your site for not agreeing to extended permissions, so this again breaks the model.
I'm not saying it's not possible, it just doesn't seem worth the effort. You would be better off just using the forms authentication parts without membership. Setting up auth cookie & validating auth cookie based on facebook access_token
.
For authentication with Facebook look at open source .NET OAuth libraries. I also wrote an article of Facebook integration which shows some integration techniques (and opinions) here.
Update based on you amended question:
Use Forms authentication cookie to store the unique identifier of your choosing (Facebook username for instance). You can also store the current access_token
in the cookie.
if (OAuth.ValidateUser(username, user_access_token))
{
// store the user access token to make it available on each request
string userData = user_access_token;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // ticket version
username, // authenticated username
DateTime.Now, // issueDate
DateTime.Now.AddMinutes(30), // expiryDate
isPersistent, // true to persist across browser sessions
userData, // can be used to store additional user data
FormsAuthentication.FormsCookiePath); // the path for the cookie
// Encrypt the ticket using the machine key
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Add the cookie to the request to save it
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket));
// Your redirect logic
Response.Redirect(FormsAuthentication.GetRedirectUrl(username, isPersistent));
}
Then override authenticate request to read the cookie and retrieve the user details.
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookie[FormsAuthentication.FormsCookieName];
if(authCookie != null)
{
//Extract the forms authentication cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
// If caching roles in userData field then extract
string user_access_token = authTicket.UserData;
// Create the IIdentity instance, maybe use a custom one
// possibly retrieve extra data from database or whatever here
IIdentity id = new FacebookIdentity( authTicket, user_access_token );
// Create the IPrinciple instance
IPrincipal principal = new GenericPrincipal(id, new string[]{});
// Set the context user
Context.User = principal;
}
}
Then in your code on each request:
var username = Context.User.Identity.Username;
// implement as an extension method on IIdentity which types to
// FacebookIdentity to get user_access_token
var user_access_token = Context.User.Identity.Access_Token;
1 option: You should generate a password and send it by email to the user, for example:
Welcome to my superwebsite.com, login: foo@foo.com password:dhyfd46
Then if you see that the password is the original (generated) ask the user to change it for another one.
2nd option: you will never use a password, for you an account is a tuple (facebookID,email) (you will get it from the facebook Api) and if it will match this (the user will click om 'login with facebook', you will be able to create the user session
After the Edit:
Why not using the tuple (userId,facebookId) and if you have the fb Id you know the userId?