I have a stored procedure that updates status. Depending on the role of the user the stored procedure has code that may or may not allow the status change. For this reason I need to pass a role name into a stored procedure. My role name is stored on the client in my javascript code but of course I need a second check on the server. Each user has only one of three roles and when requesting an update of status I can call one of three methods depending on the role that the client has. Here's what I tried.
I am using WebApi with bearer Token based authentication and ASP.NET Identity 2.1 and the application always runs in a browser. My users have been set up with the appropriate roles.
I put in place some code to get the userId and then go to the AspNetUserRoles table to get the role at the start of a method. However I noticed this takes around 500 milliseconds to run. As an alternative I am considering the following:
[HttpPut]
[Authorize(Roles = "Admin")]
[Route("AdminUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
public async Task<IHttpActionResult> AdminUpdateStatus(int userTestId, int userTestStatusId)
{
return await UpdateStatusMethod(userTestId, userTestStatusId, "Admin");
}
[HttpPut]
[Authorize(Roles = "Student")]
[Route("StudentUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
public async Task<IHttpActionResult> StudentUpdateStatus(int userTestId, int userTestStatusId)
{
return await UpdateStatusMethod(userTestId, userTestStatusId, "Student");
}
[HttpPut]
[Authorize(Roles = "Teacher")]
[Route("TeacherUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
public async Task<IHttpActionResult> TeacherUpdateStatus(int userTestId, int userTestStatusId)
{
return await UpdateStatusMethod(userTestId, userTestStatusId, "Teacher");
}
private async Task<IHttpActionResult> UpdateStatusMethod(int userTestId, int userTestStatusId, string roleName)
{
// Call the stored procedure here and pass in the roleName
}
Is this an efficient way to do this or is there perhaps another more clean way. What I am rather unclear on is if the front or back end caches the users role. I assume that this is done or there is some setting that will allow this to be done.
Note I am using claims to send the Role information to my client here:
public static AuthenticationProperties CreateProperties(
string userName,
ClaimsIdentity oAuthIdentity,
string firstName,
string lastName,
int organization)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName},
{ "firstName", firstName},
{ "lastName", lastName},
{ "organization", organization.ToString()},
{ "roles",string.Join(":",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}
};
return new AuthenticationProperties(data);
}
However my question here relates to the server and how I can check in my method if a user is in a certain role without going to the database. Maybe there's a way to do this securely with claims but I don't know how to do that.
Any help and advice would be much appreciated.