Чтобы вернуть страницу входа для своего пользовательского поставщика удостоверений, необходимо вызвать метод SignInManager.ConfigureExternalAuthenticationProperties () . Этот метод позволяет вам определить redirectUrl и провайдера (вы назвали своего провайдера "facebook").
Я написал это так:
[Controller]
[Route("web/v2/[controller]")]
public class AccountController : Controller
{
private IAccountService accountService;
public AccountController(IAccountService accountService)
{
this.accountService = accountService;
}
// GET: web/Account/connect/{provider}
[AllowAnonymous]
[HttpGet("connect/{medium}/{provider}", Name = "web-v2-account-external-connect-challenge")]
public async Task<ActionResult> ExternalLogin([FromRoute]string medium, [FromRoute]string provider)
{
//var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { medium, provider });
var redirectUrl = Url.RouteUrl("web-v2-account-external-connect-callback", new { medium, provider });
var properties = await accountService.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
// GET: web/Account/connect/{provider}/callback
[HttpGet("connect/{medium}/{provider}/callback", Name = "web-v2-account-external-connect-callback")]
public async Task<ActionResult> ExternalLoginCallback([FromRoute]string medium, [FromRoute]string provider)
{
try
{
var login_result = await accountService.PerfromExternalLogin();
if (login_result.Status)
{
var model = new LoginResultVM
{
Status = true,
Medium = medium,
Platform = login_result.Platform
};
return View(model);
}
else
{
var model = new LoginResultVM
{
Status = false,
Medium = medium,
Platform = login_result.Platform,
Error = login_result.Error,
ErrorDescription = login_result.ErrorDescription
};
return View(model);
}
}
catch (OtherAccountException otherAccountEx)
{
var model = new LoginResultVM
{
Status = false,
Medium = medium,
Platform = provider,
Error = "Could not login",
ErrorDescription = otherAccountEx.Message
};
return View(model);
}
catch (Exception ex)
{
var model = new LoginResultVM
{
Status = false,
Medium = medium,
Platform = provider,
Error = "Could not login",
ErrorDescription = "There was an error with your social login"
};
return View(model);
}
}
}
Хотя мой AccountRepository выглядит следующим образом:
internal interface IAccountRepository
{
...
}
internal class AccountRepository : IAccountRepository
{
private MintPlayerContext mintplayer_context;
private UserManager<Entities.User> user_manager;
private SignInManager<Entities.User> signin_manager;
private JwtIssuerOptions jwtIssuerOptions;
public AccountRepository(UserManager<Entities.User> user_manager, SignInManager<Entities.User> signin_manager, MintPlayerContext mintplayer_context, IOptions<JwtIssuerOptions> jwtIssuerOptions)
{
this.user_manager = user_manager;
this.signin_manager = signin_manager;
this.mintplayer_context = mintplayer_context;
this.jwtIssuerOptions = jwtIssuerOptions.Value;
}
public async Task<Tuple<User, string>> Register(User user, string password)
{
...
}
public async Task<LoginResult> LocalLogin(string email, string password, bool createCookie)
{
...
}
public async Task<IEnumerable<AuthenticationScheme>> GetExternalLoginProviders()
{
var providers = await signin_manager.GetExternalAuthenticationSchemesAsync();
return providers.ToList();
}
public Task<AuthenticationProperties> ConfigureExternalAuthenticationProperties(string provider, string redirectUrl)
{
var properties = signin_manager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Task.FromResult(properties);
}
public async Task<LoginResult> PerfromExternalLogin()
{
var info = await signin_manager.GetExternalLoginInfoAsync();
if (info == null)
throw new UnauthorizedAccessException();
var user = await user_manager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
if (user == null)
{
string username = info.Principal.FindFirstValue(ClaimTypes.Name);
string email = info.Principal.FindFirstValue(ClaimTypes.Email);
var new_user = new Entities.User
{
UserName = username,
Email = email,
PictureUrl = null
};
var id_result = await user_manager.CreateAsync(new_user);
if (id_result.Succeeded)
{
user = new_user;
}
else
{
// User creation failed, probably because the email address is already present in the database
if (id_result.Errors.Any(e => e.Code == "DuplicateEmail"))
{
var existing = await user_manager.FindByEmailAsync(email);
var existing_logins = await user_manager.GetLoginsAsync(existing);
if (existing_logins.Any())
{
throw new OtherAccountException(existing_logins);
}
else
{
throw new Exception("Could not create account from social profile");
}
}
else
{
throw new Exception("Could not create account from social profile");
}
}
await user_manager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.ProviderDisplayName));
}
await signin_manager.SignInAsync(user, true);
return new LoginResult
{
Status = true,
Platform = info.LoginProvider,
User = ToDto(user)
};
}
public async Task<IEnumerable<UserLoginInfo>> GetExternalLogins(ClaimsPrincipal userProperty)
{
...
}
public async Task AddExternalLogin(ClaimsPrincipal userProperty)
{
...
}
public async Task RemoveExternalLogin(ClaimsPrincipal userProperty, string provider)
{
...
}
public async Task<User> GetCurrentUser(ClaimsPrincipal userProperty)
{
var user = await user_manager.GetUserAsync(userProperty);
return ToDto(user);
}
public async Task Logout()
{
await signin_manager.SignOutAsync();
}
#region Helper methods
private string CreateToken(Entities.User user)
{
...
}
#endregion
#region Conversion methods
internal static Entities.User ToEntity(User user)
{
...
}
internal static User ToDto(Entities.User user)
{
...
}
#endregion
}