It turned out that the callback was redirecting the user to the authorization page because the request wasn't being completed. I fixed the issue by calling context.Response.CompleteAsync()
.
Let me know if this is the proper way of doing this.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I am implementing OAuth2 authorization in my application with an external provider. When the user is redirected back to my application from the authorization server, my application will just redirect the user back despite using the Redirect()
method to specify the URL.
Program.cs
builder.Services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "ExternalProvider";
})
.AddCookie()
.AddOAuth("ExternalProvider", options =>
{
...
options.CallbackPath = new PathString("/auth/callback");
...
options.Events.OnCreatingTicket = async context =>
{
HttpRequestMessage req = new(HttpMethod.Get, context.Options.UserInformationEndpoint);
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
HttpResponseMessage res = await context.Backchannel.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
res.EnsureSuccessStatusCode();
var user = JsonDocument.Parse(await res.Content.ReadAsStringAsync()).RootElement;
context.RunClaimActions(user);
// Save user to database if it doesn't exist
ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
int userId = int.Parse(user.GetString("sub"));
// Check if user exists
bool userExists = (await dbContext.Users.FirstOrDefaultAsync(u => u.Id == userId)) is not null;
if (!userExists)
{
// Save the user
string username = user.GetString("preferred_username");
string profilePicture = user.GetString("picture");
dbContext.Users.Add(new ApplicationUser()
{
Id = userId,
Username = username,
ProfilePicture = profilePicture
});
await dbContext.SaveChangesAsync();
}
context.Response.Redirect("/Home/Index"); // User is still redirected to /auth/login
};
});
AuthController.cs
using Microsoft.AspNetCore.Mvc;
namespace Frontend.Controllers
{
public class AuthController : Controller
{
public IActionResult Login()
{
return Challenge("ExternalProvider");
}
}
}
HomeController.cs
using Microsoft.AspNetCore.Mvc;
namespace Frontend.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
I want to return a MVC view after the authorization process is completed and I'm attempting to do it by redirecting the user to the home controller but with no success since the user will just be redirected back to the authorization.
It turned out that the callback was redirecting the user to the authorization page because the request wasn't being completed. I fixed the issue by calling context.Response.CompleteAsync()
.
Let me know if this is the proper way of doing this.