This is the attribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class MyAuthorize : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (!IsAuthorized(context))
{
context.Result = new RedirectResult("/Account/Login", true);
}
}
private bool IsAuthorized(AuthorizationFilterContext context)
{
return Current.IsAuthenticated;
}
}
The following are a few snippets showing how the attribute is applied on Action methods in different controllers
//MergerController
[MyAuthorize]
[HttpGet]
public IActionResult ChooseSemester()
{
return View();
}
//SessionController
[MyAuthorize]
public async Task<IActionResult> EditGroups(bool firstSemester)
{
var response = await wrapper.Session.GetGroups();
var groups = await response.Content.ReadFromJsonAsync<List<Lecture>>();
return View("Groups", groups);
}
//HomeController
[MyAuthorize]
public IActionResult Profile()
{
return View(Current.User);
}
[MyAuthorize]
[HttpPost]
[ActionName("Profile")]
public async Task<IActionResult> UpdateProfile(string id, string action, string newValue)
{
var user = Current.User;
switch (id)
{
case "username": user.UserName = newValue; break;
case "email": user.Email = newValue; break;
case "mergeKey": user.MergeKey = newValue; break;
}
var result = await wrapper.User.Update(user);
if (result.IsSuccessStatusCode)
TempData["Message"] = "Your account detail(s) have successfully been updated";
else
TempData["Message"] = "Failed to update account detail(s)";
return action == "mergeKey" ? RedirectToAction("Index") : RedirectToAction("Profile");
}
I am able to successfully login with the following code
[AllowAnonymous]
public IActionResult Login(string returnUrl)
{
return RedirectToAction("SignIn", new { returnUrl = returnUrl });
}
[AllowAnonymous]
public IActionResult SignIn(string returnUrl)
{
return View(new LoginViewModel
{ ReturnUrl = returnUrl }
);
}
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel loginModel)
{
if (ModelState.IsValid)
{
//login to the API
var response = await _wrapper.Authorization.Login(loginModel);
if (response.IsSuccessStatusCode)
{
var user = await response.Content.ReadFromJsonAsync<BongoUser>();
Response.Cookies.Append("Notified", user.Notified.ToString().ToLower(),
new CookieOptions { Expires = DateTime.Now.AddDays(90) });
Current.User = user;
if (Current.User.SecurityQuestion != default)
return RedirectToAction("Index", "Home");
else
return RedirectToAction("SecurityQuestion", new { sendingAction = "LogIn" });
}
else
{
ModelState.AddModelError("", "Something went wrong. Please try again and if the problem persists contact us.");
goto OnError;
}
}
ModelState.AddModelError("", "Invalid email or password");
OnError:
return View("SignIn", loginModel);
}
My goal here is to use an API, I am using the _wrapper object to do that using the repository pattern. I have since then disconnected the application from the database completely and it only connects to the API for any activities that require database connection and hence I removed the default [Authorize] attribute of ASP .Net Core because I cannot use User.IsAuthenticated and User.Identity.Name if I am not using userManager on the application itself to sign in.
Initially, I could not connect to the API and was having some issues. I have now kind of embedded the API into the appliction so I can work with it in that way to test the application. For reference, if you have time you can check the project on my github at https://github.com/MpofuO/Bongo4Students and the API at https://github.com/MpofuO/BongoAPI