Reputation: 57
I would like to intercept each and every web request coming to the api, during each request I would like to call a function I have written that would tell me of the user has a valid non expired license key. A couple things I will need is one to be able to identify the user, I could do that by unwrapping the JWT token I will need access to that token, also I will need to be able to call methods from one of my classes which is already registered for injection using autofac. I know that there are action filters, and middleware I can tie into, but I haven't had much experience using either of these, I am looking for the best way to do this maybe even point me to some example. Oh and I'm also going to have to be able to know the route, there are a couple API methods which are exempt from this check. If the check feels I'm obviously going to want to throw the request, maybe throw 401 error or something.
Upvotes: 2
Views: 3752
Reputation: 1050
I highly recommend Neil Cummings’ Udemy course Build an App with ASPNET Core and Angular From Scratch
The sample solution includes a MIT license.
This 28 hour course and related solution utilizes:
The following sections are directly related to what you are trying to accomplish:
3.26 Creating the Concrete Auth Repository and Register Method
3.27 Creating the Login Repository method
3.29 Creating the Register Method in our Auth Controller
3.32 Token Authentication
The client sends the token to the server. The server does not utilize the database to validate the user, it validates the token itself.
3.33 Creating the Login Method in the API
Claims are added to the token here:
AuthController.cs
public class AuthController : ControllerBase
{
[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
…
return Ok(new {
token = GenerateJwtToken(appUser).Result,
user = userToReturn});}
}
private async Task<string> GenerateJwtToken(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName)
};
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var key = new SymmetricSecurityKey(Encoding.UTF8
.GetBytes(_config.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
3.34 Using the Authentication Middleware
JwtBearerDefaults.AuthenticationScheme
is registered with DI here:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
}
4.39 Introduction to Angular Services
The user’s token is stored to local storage in the browser upon successful login:
auth.service.ts
export class AuthService {
login(model: any) {
return this.http.post(this.baseUrl + ‘login’, model).pipe(
map((response: any) => {
const user = response;
if(user) { localStorage.setItem(‘token’, user.token);}}));}}
6.55 Using the Angular JWT Library to Decode Tokens
Adds a property for the decoded token to authService.ts
13.134 Using Action Filters
You could:
validate the license key via a Claim in the Action Filter
Determine the current API route via ActionExecutingContext
Here is an example of retrieving the user claims as well as resolving services from within an Action Filter:
public class LogUserActivity : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var resultContext = await next();
var userId = int.Parse(resultContext.HttpContext.User
.FindFirst(ClaimTypes.NameIdentifier).Value);
var repo = resultContext.HttpContext.RequestServices.GetService<IDatingRepository>();
var user = await repo.GetUser(userId, true);
user.LastActive = DateTime.Now;
await repo.SaveAll();
}
}
Upvotes: 1