private async Task <bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions) { if (autoLinkOptions == null) { return(false); } if (autoLinkOptions.ShouldAutoLinkExternalAccount(UmbracoContext, loginInfo) == false) { return(true); } //we are allowing auto-linking/creating of local accounts if (loginInfo.Email.IsNullOrWhiteSpace()) { ViewData.SetExternalSignInProviderErrors( new BackOfficeExternalLoginProviderErrors( loginInfo.Login.LoginProvider, new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." })); } else { //Now we need to perform the auto-link, so first we need to lookup/create a user with the email address var autoLinkUser = UserManager.FindByEmail(loginInfo.Email); if (autoLinkUser != null) { try { //call the callback if one is assigned autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo); } catch (Exception ex) { var msg = "Could not link login provider " + loginInfo.Login.LoginProvider + "."; Logger.Error <BackOfficeController>(ex, msg); ViewData.SetExternalSignInProviderErrors( new BackOfficeExternalLoginProviderErrors( loginInfo.Login.LoginProvider, new[] { msg + " " + ex.Message })); return(true); } await LinkUser(autoLinkUser, loginInfo); } else { if (loginInfo.Email.IsNullOrWhiteSpace()) { throw new InvalidOperationException("The Email value cannot be null"); } if (loginInfo.ExternalIdentity.Name.IsNullOrWhiteSpace()) { throw new InvalidOperationException("The Name value cannot be null"); } var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo)); autoLinkUser = BackOfficeIdentityUser.CreateNew( loginInfo.Email, loginInfo.Email, autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo)); autoLinkUser.Name = loginInfo.ExternalIdentity.Name; foreach (var userGroup in groups) { autoLinkUser.AddRole(userGroup.Alias); } //call the callback if one is assigned try { autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo); } catch (Exception ex) { var msg = "Could not link login provider " + loginInfo.Login.LoginProvider + "."; Logger.Error <BackOfficeController>(ex, msg); ViewData.SetExternalSignInProviderErrors( new BackOfficeExternalLoginProviderErrors( loginInfo.Login.LoginProvider, new[] { msg + " " + ex.Message })); return(true); } var userCreationResult = await UserManager.CreateAsync(autoLinkUser); if (userCreationResult.Succeeded == false) { ViewData.SetExternalSignInProviderErrors( new BackOfficeExternalLoginProviderErrors( loginInfo.Login.LoginProvider, userCreationResult.Errors)); } else { await LinkUser(autoLinkUser, loginInfo); } } } return(true); }
private async Task<bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions) { if (autoLinkOptions == null) return false; if (autoLinkOptions.ShouldAutoLinkExternalAccount(UmbracoContext, loginInfo) == false) return true; //we are allowing auto-linking/creating of local accounts if (loginInfo.Email.IsNullOrWhiteSpace()) { ViewData.SetExternalSignInError(new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." }); } else { //Now we need to perform the auto-link, so first we need to lookup/create a user with the email address var foundByEmail = Services.UserService.GetByEmail(loginInfo.Email); if (foundByEmail != null) { ViewData.SetExternalSignInError(new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider }); } else { if (loginInfo.Email.IsNullOrWhiteSpace()) throw new InvalidOperationException("The Email value cannot be null"); if (loginInfo.ExternalIdentity.Name.IsNullOrWhiteSpace()) throw new InvalidOperationException("The Name value cannot be null"); var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo)); var autoLinkUser = BackOfficeIdentityUser.CreateNew( loginInfo.Email, loginInfo.Email, autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo)); autoLinkUser.Name = loginInfo.ExternalIdentity.Name; foreach (var userGroup in groups) { autoLinkUser.AddRole(userGroup.Alias); } //call the callback if one is assigned if (autoLinkOptions.OnAutoLinking != null) { autoLinkOptions.OnAutoLinking(autoLinkUser, loginInfo); } var userCreationResult = await UserManager.CreateAsync(autoLinkUser); if (userCreationResult.Succeeded == false) { ViewData.SetExternalSignInError(userCreationResult.Errors); } else { var linkResult = await UserManager.AddLoginAsync(autoLinkUser.Id, loginInfo.Login); if (linkResult.Succeeded == false) { ViewData.SetExternalSignInError(linkResult.Errors); //If this fails, we should really delete the user since it will be in an inconsistent state! var deleteResult = await UserManager.DeleteAsync(autoLinkUser); if (deleteResult.Succeeded == false) { //DOH! ... this isn't good, combine all errors to be shown ViewData.SetExternalSignInError(linkResult.Errors.Concat(deleteResult.Errors)); } } else { //sign in await SignInManager.SignInAsync(autoLinkUser, isPersistent: false, rememberBrowser: false); } } } } return true; }