Integration of Facebook and asp.net membership

2020-05-24 16:40发布

问题:

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 :)

回答1:

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;


回答2:

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?