Create Token with user credential & roles and authorize action methods based on role in Web API is the topic we will cover in this article. We would need to pass token in every request and decorate action methods with [Authorize(Roles = "Admin, Manager") etc. that's only the code we will need to complete our role based authentication.
Check my previous article OAuth Web API token based authentication with custom database because I don't want to repeat the same code here again.
Let's create the user service which will have different methods to get users. For testing purpose we will create a list of user by using the for loop rather than database. I am planning to use the same project for Unit Test in future to let's create a IUserService Interface:
public interface IUserService
{
User Validate(string email, string password);
List<User> GetUserList();
User GetUserById(int id);
List<User> SearchByName(string name);
}
It has three method to validate user by email and password, get list of records and get user by user id. Let's implement this interface:
public class UserService: IUserService
{
private List<User> userList = new List<User>();
public UserService()
{
for (var i = 1; i <= 10; i++)
{
userList.Add(new User
{ Id = i, Name = $"User {i}", Password = $"pass{i}",
Email = $"user{i}@dummy.com",
Roles = new string[] { i% 2 == 0 ? "Admin" : "User"}
});
}
}
public User Validate(string email, string password)
=> userList.FirstOrDefault(x => x.Email == email && x.Password == password);
public List<User> GetUserList() => userList;
public User GetUserById(int id)
=> userList.FirstOrDefault(x => x.Id == id);
public List<User> SearchByName(string name)
=> userList.Where(x => x.Name.Contains(name)).ToList();
}
Except the constructor which we try to run the for loop and create a list of 10 users, every user will have a role. If i is divisible by 2 then Admin otherwise User.
All the three methods have only one line of code so we use here arrow function.
Now let's change the Custom OAuthProvider which you already saw in previous article. Here we need to manage the roles in claims, after adding different properties into claims we need to add the roles also into claims like this
foreach (var role in user.Roles)
claims.Add(new Claim(ClaimTypes.Role, role));
If you noticed in our UserService Roles is an array of string, but we add only one admin or user, if you want you can add more than one role to a user, that's why we are trying to add the roles in claims in a for loop. So it will work in both case, whether we will have one role or more than one.
If you want to return user name and roles after authentication then add these lines so it they can also return with token:
var data = new Dictionary<string, string>
{
{ "userName", user.Name },
{ "roles", string.Join(",", user.Roles)}
};
var properties = new AuthenticationProperties(data);
Let me copy the complete GrantResourceOwnerCredentials method to avoid the confusion:
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
return Task.Factory.StartNew(() =>
{
var userName = context.UserName;
var password = context.Password;
var userService = new UserService();
var user = userService.Validate(userName, password);
if (user != null)
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Sid, Convert.ToString(user.Id)),
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Email, user.Email)
};
foreach (var role in user.Roles)
claims.Add(new Claim(ClaimTypes.Role, role));
var data = new Dictionary<string, string>
{
{ "userName", user.Name },
{ "roles", string.Join(",", user.Roles)}
};
var properties = new AuthenticationProperties(data);
ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims,
Startup.OAuthOptions.AuthenticationType);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
}
else
{
context.SetError("invalid_grant", "The user name or password is incorrect");
}
});
}
Next we will create a UserController with different methods, Let's see the code first then we can see what those methods are one by one, here is the complete code for user api controller:
public class UserController : ApiController
{
IUserService _userService;
public UserController()
=> _userService = new UserService();
public UserController(IUserService userService)
=> _userService = userService;
[HttpGet, Authorize(Roles = "Admin, User"), Route("api/user/GetAll")]
public async Task<IHttpActionResult> GetAll()
=> Ok( await Task.Run(()=> _userService.GetUserList()));
[HttpGet, Authorize(Roles = "Admin"), Route("api/user/GetById")]
public async Task<IHttpActionResult> GetById(int id)
=> Ok(await Task.Run(() => _userService.GetUserById(id)));
[HttpGet, Authorize(Roles = "Admin"), Route("api/user/search")]
public async Task<IHttpActionResult> Search(string name)
=> Ok(await Task.Run(() => _userService.SearchByName(name)));
}
We are done, time to test the methods, try any user controller action method without providing the token, we will get the error
Means our authorization working as it should be.
Let's create the token by providing first user information, if you noticed every user email will be like user[N]@dummy.com and passwor: pass[N], so for first user which is a user and not admin: email: user1@dummy.com, password: pass1
Open your fidler/postman or Chrome Advance Rest Client, I am using chrome ARC, see the image and provide all the information accordingly, note the token method is a post method and click send/post
We got the token so we can pass it and call the different methods and check whether role base validation is working or not:
Let's try to get the list of all users, current user have role user:
Note the space between Bearer and Token string, let me add the image one more time for this request, so it will be clear how we can pass the token:
This request work becuase User role have the permission to see the list of users, let's try to get the detail for any user, and that method is only allowed for Admin:
Change the URL to : http://localhost:9786/api/user/getbyid?id=3
It will return something like: "Authorization has been denied for this request." with status code 401: Unauthorized
Let's try to call search action method by providing any name, change the URL to: http://localhost:9786/api/user/search?name=User
Again we will get the same error of 401: Unauthorized.
Let's try to login and generate a new token with user 2, email: user2@dummy.com password: pass2
We will get a new token, copy this new token and try to pass and try to call previous search URL this time, it will work smooth.
So we successfully completed our role base authentication with Web API 2, OAuth Token generation, Use Role to protect our methods, pass token in header to authorize user with role.
Angular 6 Web API 2 Bearer Token Authentication add to header with HttpInterceptor
![]() |
Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
|
By Ali Adravi On 04 Oct, 18 Viewed: 6,519 |
Token base authentication with custom database by using OAuth in Web API is not complicated but documents are not very clear, many people try it and ended up with scratching their head, but you are on the right page so you will not be one of them. It is not required to create an empty project... By Ali Adravi On 11 Sep 2017 Viewed: 17,570
Token base authentication expires over a fixed time, to overcome on it we need to use the refresh token. We will try to create the token as well as the refresh token after successful login, refresh token will be used to generate a new token if current token is already expired and it is not too... By Ali Adravi On 08 Oct 2018 Viewed: 17,748
Upload file with data by clicking on button or by drag and drop, is the topic of this article. We will try to create an image gallery by uploading files and save data into database and images into a folder. We will try to create a component in a way that it can be used anywhere in entire... By Ali Adravi On 24 Sep 2017 Viewed: 41,050
What is ASP.Net Web API, what is RESTFul service, What is the difference between WCF and Web API and when to use over other. These are the main points which we going to discuss in this starting article, then we will create our own Web API project and look each and every single type of methods... By Ali Adravi On 13 Jul 2017 Viewed: 1,382
I found most of .Net developer whether they are ASP.Net developer or MVC developer, they face to start and how to create the Angularjs application structure. In this article we will start from an empty project with Web API 2.0. First of all we will create very simple application with three... By Ali Adravi On 18 Jul 2015 Viewed: 3,838