❔ Callback Url Always Null

Here's the two functions involved
public IActionResult ExternalLogin(string provider, string returnurl = null)
{
var redirect = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnurl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirect);
return Challenge(properties, provider);
}

public async Task<IActionResult> ExternalLoginCallback(string returnurl = null, string remoteError = null)
{
if(remoteError != null)
{
ModelState.AddModelError(string.Empty, "Error from external provider");
return View("Login");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if(info == null)
{
return RedirectToAction("Login");
}
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(returnurl);
}
else
{
ViewData["ReturnUrl"] = returnurl;
ViewData["ProviderDisplayName"] = info.ProviderDisplayName;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLoginConfirmation", new ExternalLoginViewModel { Email = email });
}
}
public IActionResult ExternalLogin(string provider, string returnurl = null)
{
var redirect = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnurl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirect);
return Challenge(properties, provider);
}

public async Task<IActionResult> ExternalLoginCallback(string returnurl = null, string remoteError = null)
{
if(remoteError != null)
{
ModelState.AddModelError(string.Empty, "Error from external provider");
return View("Login");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if(info == null)
{
return RedirectToAction("Login");
}
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(returnurl);
}
else
{
ViewData["ReturnUrl"] = returnurl;
ViewData["ProviderDisplayName"] = info.ProviderDisplayName;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLoginConfirmation", new ExternalLoginViewModel { Email = email });
}
}
I don't know why but the returnurl is always null.
8 Replies
BigggMoustache
BigggMoustacheOP2y ago
This is pretty much copied from the docs
Saber
Saber2y ago
well I'm going to assume theres some case sensitivity, so you should probably use returnUrl in all the places to be consistent
BigggMoustache
BigggMoustacheOP2y ago
I'll look at that right now How would that make it function differently when the only use of that variable is in those particular methods? because it is functioning now
Saber
Saber2y ago
your generating a url here var redirect = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnurl }); passing ReturnUrl as the expected parameter, but string returnurl = null won't match if it requires case sensitivity
BigggMoustache
BigggMoustacheOP2y ago
ReturnUrl is referencing the ViewModel iirc, and returnurl is referencing local variable, which is what I changed to returnUrl as it's what I used the whole way through before this. so I just changed casing to match rest of controller, left the ReturnUrl as is, and it's working. catshrug imagine I'm misunderstanding your help here lol. maybe the confirmation function that follows these two looks for returnUrl to be passed to it specifically? Here's that function if you wouldn't mind taking a look.
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string? returnurl = null)
{
returnurl = returnurl ?? Url.Content("~/");
if(ModelState.IsValid)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if(info == null)
{
return View("Error");
}
var user = new AppUser { UserName = model.Name, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if(result.Succeeded)
{
//await _userManager.AddToRoleAsync(user, "user");
result = await _userManager.AddLoginAsync(user, info);
if(result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(returnurl);
}
}
ModelState.AddModelError("Email", "User already exists.");
}
ViewData["ReturnUrl"] = returnurl;
return View(model);
}
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string? returnurl = null)
{
returnurl = returnurl ?? Url.Content("~/");
if(ModelState.IsValid)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if(info == null)
{
return View("Error");
}
var user = new AppUser { UserName = model.Name, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if(result.Succeeded)
{
//await _userManager.AddToRoleAsync(user, "user");
result = await _userManager.AddLoginAsync(user, info);
if(result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(returnurl);
}
}
ModelState.AddModelError("Email", "User already exists.");
}
ViewData["ReturnUrl"] = returnurl;
return View(model);
}
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
BigggMoustache
BigggMoustacheOP2y ago
I understand now. It is expecting returnUrl because that was the name in original instance.
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server