TLDR вы должны пройти через все сценарии вручную в вашей ExternalLoginConfirmation
функции, и есть таблица базы данных, чтобы иметь возможность соответствовать членской идентификатор пользователя с OAuth идентификатором пользователя. Таким образом, вы можете «связывать» несколько учетных записей OAuth с одной локальной учетной записью.
Ниже приведен фрагмент кода из одного из наших проектов - мы надеемся, что это достаточно ясно
public ActionResult ExternalLoginCallback()
{
var returnUrl = HttpContext.Request.QueryString["returnUrl"];
var result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (result.IsSuccessful == false)
{
return this.View("ExternalLoginFailure", result);
}
// Login user if provider represents a valid already registered user
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return this.RedirectToLocal(returnUrl);
}
// If the current user is logged in already - add new account
if (User.Identity.IsAuthenticated)
{
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
return this.RedirectToLocal(returnUrl);
}
var membershipUser = Membership.GetUser(result.UserName);
// so user is new - then create new membership account
if (membershipUser == null)
{
MembershipCreateStatus createStatus;
membershipUser = Membership.CreateUser(username: result.UserName, password: this.GetTempPassword(), email: result.UserName, status: out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
this.emailService.SendWelcome(this, (Guid)membershipUser.ProviderUserKey);
// Associate social network account with created membership account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, result.UserName);
OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false);
return this.RedirectToLocal(returnUrl);
}
// The problem occured while creating membership account
this.ViewBag.Error = MembershipErrorNameProvider.FromErrorCode(createStatus);
return this.View("CreateMembershipAccountFailure");
}
// If membership account already exists -> Associate Social network account with exists membership account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, result.UserName);
OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false);
return this.RedirectToLocal(returnUrl);
}
и OAuthWebSecurity
является вспомогательным классом, который занимается всеми провайдерами вы поддерживаете:
public static class OAuthWebSecurity
{
....
public static bool Login(string providerName, string providerUserId, bool createPersistentCookie)
{
var context = new HttpContextWrapper(HttpContext.Current);
var provider = GetOAuthClient(providerName);
var securityManager = new OpenAuthSecurityManager(context, provider, OAuthDataProvider);
return securityManager.Login(providerUserId, createPersistentCookie);
}
public static void CreateOrUpdateAccount(string openAuthProvider, string openAuthId, string userName)
{
var user = UserRepository.FindByName(userName);
if (user == null)
{
throw new MembershipUserNotFoundException();
}
var userOAuthAccount = UserOAuthAccountRepository.Find(openAuthProvider, openAuthId);
if (userOAuthAccount == null)
{
UserOAuthAccountRepository.InsertOrUpdate(new UserOAuthAccount
{
OAuthProvider = openAuthProvider,
OAuthId = openAuthId,
UserId = user.Id
});
}
else
{
userOAuthAccount.UserId = user.Id;
}
UserOAuthAccountRepository.Save();
}
}
Разве это не боль в прикладе, что MS играла это так упрощенно, даже с небольшим упоминанием о существующих пользователях? А для новых пользователей вместо любых регистрационных данных, которые вы обычно собираете, MS default просто получает имя пользователя/адрес электронной почты. Он должен перенаправляться на «Регистрация» для новых пользователей. – ProfK
хорошо, каждый вариант использования отличается - я предпочитаю думать, что они создали структуру, которую вы относительно легко распространяете на свои нужды :) – avs099