Estoy tratando de descubrir cómo configurar un inicio de sesión a través de Discord Oauth2 mientras uso Dapper como mi ORM.
Microsoft tiene una guía aquí que he seguido para configurar todas mis tiendas. De hecho, puedo llamar al método CreateAsync() y se crea un usuario en mi base de datos, por lo que creo que ese lado de las cosas está completamente configurado.
Mis problemas se encuentran dentro del inicio de sesión externo. A continuación encontrará lo que he probado.
Programa.cs:
//omitted code that binds interfaces and classes - this code works and is fully tested. it is not related to problem at hand. builder.Services.AddIdentity<User, Role>() .AddDefaultTokenProviders(); builder.Services.AddAuthentication() .AddCookie(options => { options.LoginPath = "/signin"; options.LogoutPath = "/signout"; }) .AddDiscord(options => { options.ClientId = "some id"; options.ClientSecret = "some secret"; options.ClaimActions.MapCustomJson("urn:discord:avatar:url", user => string.Format( CultureInfo.InvariantCulture, "https://cdn.discordapp.com/avatars/{0}/{1}.{2}", user.GetString("id"), user.GetString("avatar"), user.GetString("avatar")!.StartsWith("a_") ? "gif" : "png")); }); builder.Services.AddRazorPages(); var app = builder.Build(); app.UseDeveloperExceptionPage(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); app.Run();Aquí está el código del controlador de cuenta:
public class AccountController : Controller { private readonly ISignInService _signInService; private readonly IUserService _userService; public AccountController(ISignInService signInService, IUserService userService) { _signInService = signInService; _userService = userService; } [HttpGet("~/signin")] public async Task<IActionResult> SignIn() => View("SignIn", await HttpContext.GetExternalProvidersAsync()); [HttpPost("~/signin")] public async Task<IActionResult> SignIn([FromForm] string provider, string returnUrl) { if (string.IsNullOrWhiteSpace(provider)) { return BadRequest(); } if (!await HttpContext.IsProviderSupportedAsync(provider)) { return BadRequest(); } var redirectUrl = Url.Action(nameof(LoginCallback), "Account", new { returnUrl }); var properties = _signInService.ConfigureExternalAuthenticationProperties(provider, redirectUrl, null); properties.Items.Add("XsrfKey", "Test"); return Challenge(properties, provider); } [HttpGet("~/signout")] [HttpPost("~/signout")] public IActionResult SignOutCurrentUser() { return SignOut(new AuthenticationProperties {RedirectUri = "/"}, CookieAuthenticationDefaults.AuthenticationScheme); } //[HttpGet("~/Account/LoginCallback")] [HttpGet] public async Task<IActionResult> LoginCallback(string returnUrl = null, string remoteError = null) { if (remoteError != null) { return RedirectToAction("Index", "Home"); } var info = await _signInService.GetExternalLoginInfoAsync("Test"); if (info == null) { return RedirectToAction("Index", "Home"); } var result = await _signInService.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); if (result.Succeeded) { return RedirectToLocal(returnUrl); } if (result.IsLockedOut) { return RedirectToAction("Index", "Home"); } else { // If the user does not have an account, then ask the user to create an account. ViewData["ReturnUrl"] = returnUrl; ViewData["LoginProvider"] = info.LoginProvider; var email = info.Principal.FindFirstValue(ClaimTypes.Email); return RedirectToAction("Index", "Home"); } } private IActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction(nameof(HomeController.Index), "Home"); } } }Esto es lo que sucede:
var info = await _signInService.GetExternalLoginInfoAsync("Test"); esa línea siempre es nula.He estado luchando para descubrir lo que he pasado por alto en mi configuración, ya que no tengo ningún error sobre nada.