Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Configure authentication with JWT (Json Web Token).
- public void ConfigureJwtAuthService(IServiceCollection services)
- {
- // Enable the use of an [Authorize(AuthenticationSchemes =
- // JwtBearerDefaults.AuthenticationScheme)]
- // attribute on methods and classes to protect.
- services.AddAuthentication().AddJwtBearer(cfg =>
- {
- cfg.RequireHttpsMetadata = false;
- cfg.SaveToken = true;
- cfg.TokenValidationParameters = new TokenValidationParameters()
- {
- IssuerSigningKey = JwtController.SecurityKey,
- ValidAudience = JwtController.Audience,
- ValidIssuer = JwtController.Issuer,
- // When receiving a token, check that we've signed it.
- ValidateIssuerSigningKey = true,
- // When receiving a token, check that it is still valid.
- ValidateLifetime = true,
- // This defines the maximum allowable clock skew when validating
- // the lifetime. As we're creating the tokens locally and validating
- // them on the same machines which should have synchronised time,
- // this can be set to zero.
- ClockSkew = TimeSpan.FromMinutes(0)
- };
- });
- }
- using System;
- using Autofac;
- using ExpertCodeBlogWebApp.Controllers;
- using ExpertCodeBlogWebApp.Domain;
- using ExpertCodeBlogWebApp.Domain.Interfaces;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.AspNetCore.SpaServices.Webpack;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.IdentityModel.Tokens;
- namespace ExpertCodeBlogWebApp
- {
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
- public IConfiguration Configuration { get; }
- // This method gets called by the runtime. Use this method to add
- // services to the container.
- public IServiceProvider ConfigureServices(IServiceCollection services)
- {
- services.AddMvc();
- // Configure jwt autenticazione
- ConfigureJwtAuthService(services);
- // Repositories
- services.AddScoped<IUserRepository, UserRepository>();
- // Create the Autofac container builder for dependency injection
- var builder = new ContainerBuilder();
- // Add any Autofac modules or registrations.
- builder.RegisterModule(new AutofacModule());
- // Return ServiceProvider
- var serviceProvider = services.BuildServiceProvider();
- return serviceProvider;
- }
- // Configure authentication with JWT (Json Web Token).
- public void ConfigureJwtAuthService(IServiceCollection services)
- {
- // Enable the use of an [Authorize(AuthenticationSchemes =
- // JwtBearerDefaults.AuthenticationScheme)]
- // attribute on methods and classes to protect.
- services.AddAuthentication().AddJwtBearer(cfg =>
- {
- cfg.RequireHttpsMetadata = false;
- cfg.SaveToken = true;
- cfg.TokenValidationParameters = new TokenValidationParameters()
- {
- IssuerSigningKey = JwtController.SecurityKey,
- ValidAudience = JwtController.Audience,
- ValidIssuer = JwtController.Issuer,
- // When receiving a token, check that we've signed it.
- ValidateIssuerSigningKey = true,
- // When receiving a token, check that it is still valid.
- ValidateLifetime = true,
- // This defines the maximum allowable clock skew when validating
- // the lifetime.
- // As we're creating the tokens locally and validating them on the
- // same machines which should have synchronised time, this can be
- // set to zero.
- ClockSkew = TimeSpan.FromMinutes(0)
- };
- });
- }
- // This method gets called by the runtime. Use this method to configure
- // the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
- {
- HotModuleReplacement = true
- });
- }
- else
- {
- app.UseExceptionHandler("/Home/Error");
- }
- app.UseStaticFiles();
- app.UseMvc(routes =>
- {
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
- routes.MapSpaFallbackRoute(
- name: "spa-fallback",
- defaults: new { controller = "Home", action = "Index" });
- });
- }
- }
- // For dependency injection.
- public class AutofacModule : Module
- {
- // Dependency Injection with Autofact
- protected override void Load(ContainerBuilder builder)
- {
- builder.RegisterType<UserRepository>().As<IUserRepository>()
- .SingleInstance();
- }
- }
- }
- using System;
- using System.IdentityModel.Tokens.Jwt;
- using System.Security.Claims;
- using System.Security.Principal;
- using System.Text;
- using System.Threading.Tasks;
- using AutoMapper;
- using ExpertCodeBlogWebApp.Domain;
- using ExpertCodeBlogWebApp.Domain.Interfaces;
- using ExpertCodeBlogWebApp.Domain.Models;
- using ExpertCodeBlogWebApp.ViewModels;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Logging;
- using Microsoft.IdentityModel.Tokens;
- using Newtonsoft.Json;
- namespace ExpertCodeBlogWebApp.Controllers
- {
- [Route("api/[controller]")]
- public class JwtController : Controller
- {
- #region Private Members
- // JWT-related members
- private TimeSpan TokenExpiration;
- private SigningCredentials SigningCredentials;
- // EF and Identity members, available through DI
- private MyDbContext DbContext;
- private IUserRepository _userRepository;
- private readonly ILogger _logger;
- #endregion Private Members
- #region Static Members
- private static readonly string PrivateKey = "my_PrivateKey";
- public static readonly SymmetricSecurityKey SecurityKey =
- new SymmetricSecurityKey(Encoding.ASCII.GetBytes(PrivateKey));
- public static readonly string Issuer = "my_Issuer";
- public static readonly string Audience = "my_Audience";
- #endregion Static Members
- #region Constructor
- // I have used Autofac in the Startup.cs for dependency injection)
- public JwtController(
- MyDbContext dbContext,
- IUserRepository userRepository,
- ILogger<JwtController> logger)
- {
- _logger = logger;
- _userRepository = userRepository;
- // Instantiate JWT-related members
- TokenExpiration = TimeSpan.FromMinutes(10);
- SigningCredentials = new SigningCredentials(SecurityKey,
- SecurityAlgorithms.HmacSha256);
- // Instantiate through Dependency Injection with Autofact
- DbContext = dbContext;
- }
- #endregion Constructor
- #region Public Methods
- // Manages the request for a new authentication or the refresh of an
- // already established one
- [HttpPost("token")]
- public async Task<IActionResult>
- Authentication([FromBody]JwtRequestViewModel jwt)
- {
- if (ModelState.IsValid)
- {
- string grantType = jwt.GrantType;
- if (grantType == "password")
- {
- string userName = jwt.UserName;
- string password = jwt.Password;
- // Password check required
- var user = await
- _userRepository.GetUserInfoWithCheckPwd(userName, password);
- // Check if user is expired (check the ExpireDate property)
- if (UserExpired(user))
- return BadRequest($"Account of {user.Name} expired!");
- if (UserEnabled(user))
- return await GenerateToken(user);
- else
- return BadRequest("User name or password invalid.");
- }
- }
- else if (grantType == "refresh_token")
- {
- string userName = jwt.UserName;
- // Refresh token (no password check required)
- var user = await _userRepository.GetUserInfoByName(userName);
- // Check if user is expired (check the ExpireDate property)
- if (UserExpired(user))
- return BadRequest($"Account of {user.Name} expired!");
- string token = jwt.Token;
- if (token == user.Token)
- {
- // Generate token and send it via a json-formatted string
- return await GenerateToken(user);
- }
- else
- {
- return BadRequest("User token invalid.");
- }
- }
- else
- return BadRequest("Authentication type invalid.");
- }
- else
- return BadRequest("Request invalid.");
- }
- #endregion Public Methods
- #region Private Methods
- private bool UserExpired(Users utente)
- {
- if (utente != null)
- return utente.ExpireDate.CompareTo(DateTime.Now) < 0;
- return true;
- }
- private bool UserEnabled(Users utente)
- {
- if (utente != null)
- return utente.Enabled == true;
- return false;
- }
- private JsonSerializerSettings DefaultJsonSettings
- {
- get
- {
- return new JsonSerializerSettings()
- {
- Formatting = Formatting.Indented
- };
- }
- }
- private async Task<IActionResult> GenerateToken(Users user)
- {
- try
- {
- if (user != null)
- {
- var handler = new JwtSecurityTokenHandler();
- DateTime newTokenExpiration = DateTime.Now.Add(TokenExpiration);
- ClaimsIdentity identity = new ClaimsIdentity(
- new GenericIdentity(user.Name, "TokenAuth"),
- new[] { new Claim("ID", user.Id.ToString())}
- );
- var securityToken = handler.CreateToken(new SecurityTokenDescriptor
- {
- Issuer = JwtController.Issuer,
- Audience = JwtController.Audience,
- SigningCredentials = SigningCredentials,
- Subject = identity,
- Expires = newTokenExpiration
- });
- string encodedToken = handler.WriteToken(securityToken);
- // Update token data on database
- await _userRepository.UpdateTokenData(user.Name, encodedToken,
- newTokenExpiration);
- // Build the json response
- // (I use Automapper to maps an object into another object)
- var jwtResponse = Mapper.Map<JwtResponseViewModel>(user);
- jwtResponse.AccessToken = encodedToken;
- jwtResponse.Expiration = (int)TokenExpiration.TotalSeconds;
- return Ok(jwtResponse);
- }
- return NotFound();
- }
- catch(Exception e)
- {
- return BadRequest(e.Message);
- }
- }
- #endregion
- }
- }
- login(userName: string, password: string)
- {
- return this.getLoginEndpoint(userName, password)
- .map((response: Response) => this.processLoginResponse(response));
- }
- getLoginEndpoint(userName: string, password: string): Observable<Response>
- {
- // Body
- // JwtRequest is a model class that I use to send info to the controller
- let jwt = new JwtRequest();
- jwt.GrantType = "password";
- jwt.UserName = userName;
- jwt.Password = password;
- jwt.ClientId = "my_Issuer";
- // Post requiest (I use getAuthHeader that attach to the header the
- // authentication token, but it can also be omitted because it is ignored
- // by the JwtController
- return this.http.post(this.loginUrl, JSON.stringify(jwt),
- this.getAuthHeader(true))
- }
- protected getAuthHeader(includeJsonContentType?: boolean): RequestOptions
- {
- // Hera I use this.authService.accessToken that is a my service where
- // I have store the token received from the server
- let headers = new Headers({
- 'Authorization': 'Bearer ' + this.authService.accessToken });
- if (includeJsonContentType)
- headers.append("Content-Type", "application/json");
- headers.append("Accept", `application/vnd.iman.v01+json,
- application/json, text/plain, */*`);
- headers.append("App-Version", "01");
- return new RequestOptions({ headers: headers });
- }
- private processLoginResponse(response: Response)
- {
- // process the response..
- }
- [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement