Advertisement
Guest User

Untitled

a guest
Jan 18th, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.32 KB | None | 0 0
  1. // Configure authentication with JWT (Json Web Token).
  2. public void ConfigureJwtAuthService(IServiceCollection services)
  3. {
  4. // Enable the use of an [Authorize(AuthenticationSchemes =
  5. // JwtBearerDefaults.AuthenticationScheme)]
  6. // attribute on methods and classes to protect.
  7. services.AddAuthentication().AddJwtBearer(cfg =>
  8. {
  9. cfg.RequireHttpsMetadata = false;
  10. cfg.SaveToken = true;
  11. cfg.TokenValidationParameters = new TokenValidationParameters()
  12. {
  13. IssuerSigningKey = JwtController.SecurityKey,
  14. ValidAudience = JwtController.Audience,
  15. ValidIssuer = JwtController.Issuer,
  16. // When receiving a token, check that we've signed it.
  17. ValidateIssuerSigningKey = true,
  18. // When receiving a token, check that it is still valid.
  19. ValidateLifetime = true,
  20. // This defines the maximum allowable clock skew when validating
  21. // the lifetime. As we're creating the tokens locally and validating
  22. // them on the same machines which should have synchronised time,
  23. // this can be set to zero.
  24. ClockSkew = TimeSpan.FromMinutes(0)
  25. };
  26. });
  27. }
  28.  
  29. using System;
  30. using Autofac;
  31. using ExpertCodeBlogWebApp.Controllers;
  32. using ExpertCodeBlogWebApp.Domain;
  33. using ExpertCodeBlogWebApp.Domain.Interfaces;
  34. using Microsoft.AspNetCore.Builder;
  35. using Microsoft.AspNetCore.Hosting;
  36. using Microsoft.AspNetCore.SpaServices.Webpack;
  37. using Microsoft.Extensions.Configuration;
  38. using Microsoft.Extensions.DependencyInjection;
  39.  
  40. using Microsoft.IdentityModel.Tokens;
  41.  
  42. namespace ExpertCodeBlogWebApp
  43. {
  44. public class Startup
  45. {
  46. public Startup(IConfiguration configuration)
  47. {
  48. Configuration = configuration;
  49. }
  50.  
  51. public IConfiguration Configuration { get; }
  52.  
  53. // This method gets called by the runtime. Use this method to add
  54. // services to the container.
  55. public IServiceProvider ConfigureServices(IServiceCollection services)
  56. {
  57. services.AddMvc();
  58.  
  59. // Configure jwt autenticazione
  60. ConfigureJwtAuthService(services);
  61.  
  62. // Repositories
  63. services.AddScoped<IUserRepository, UserRepository>();
  64.  
  65. // Create the Autofac container builder for dependency injection
  66. var builder = new ContainerBuilder();
  67.  
  68. // Add any Autofac modules or registrations.
  69. builder.RegisterModule(new AutofacModule());
  70.  
  71. // Return ServiceProvider
  72. var serviceProvider = services.BuildServiceProvider();
  73. return serviceProvider;
  74. }
  75.  
  76. // Configure authentication with JWT (Json Web Token).
  77. public void ConfigureJwtAuthService(IServiceCollection services)
  78. {
  79. // Enable the use of an [Authorize(AuthenticationSchemes =
  80. // JwtBearerDefaults.AuthenticationScheme)]
  81. // attribute on methods and classes to protect.
  82. services.AddAuthentication().AddJwtBearer(cfg =>
  83. {
  84. cfg.RequireHttpsMetadata = false;
  85. cfg.SaveToken = true;
  86.  
  87. cfg.TokenValidationParameters = new TokenValidationParameters()
  88. {
  89. IssuerSigningKey = JwtController.SecurityKey,
  90. ValidAudience = JwtController.Audience,
  91. ValidIssuer = JwtController.Issuer,
  92. // When receiving a token, check that we've signed it.
  93. ValidateIssuerSigningKey = true,
  94. // When receiving a token, check that it is still valid.
  95. ValidateLifetime = true,
  96. // This defines the maximum allowable clock skew when validating
  97. // the lifetime.
  98. // As we're creating the tokens locally and validating them on the
  99. // same machines which should have synchronised time, this can be
  100. // set to zero.
  101. ClockSkew = TimeSpan.FromMinutes(0)
  102. };
  103. });
  104. }
  105.  
  106. // This method gets called by the runtime. Use this method to configure
  107. // the HTTP request pipeline.
  108. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  109. {
  110. if (env.IsDevelopment())
  111. {
  112. app.UseDeveloperExceptionPage();
  113. app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
  114. {
  115. HotModuleReplacement = true
  116. });
  117. }
  118. else
  119. {
  120. app.UseExceptionHandler("/Home/Error");
  121. }
  122.  
  123. app.UseStaticFiles();
  124.  
  125. app.UseMvc(routes =>
  126. {
  127. routes.MapRoute(
  128. name: "default",
  129. template: "{controller=Home}/{action=Index}/{id?}");
  130.  
  131. routes.MapSpaFallbackRoute(
  132. name: "spa-fallback",
  133. defaults: new { controller = "Home", action = "Index" });
  134. });
  135. }
  136. }
  137.  
  138. // For dependency injection.
  139. public class AutofacModule : Module
  140. {
  141. // Dependency Injection with Autofact
  142. protected override void Load(ContainerBuilder builder)
  143. {
  144. builder.RegisterType<UserRepository>().As<IUserRepository>()
  145. .SingleInstance();
  146. }
  147. }
  148. }
  149.  
  150. using System;
  151. using System.IdentityModel.Tokens.Jwt;
  152. using System.Security.Claims;
  153. using System.Security.Principal;
  154. using System.Text;
  155. using System.Threading.Tasks;
  156. using AutoMapper;
  157. using ExpertCodeBlogWebApp.Domain;
  158. using ExpertCodeBlogWebApp.Domain.Interfaces;
  159. using ExpertCodeBlogWebApp.Domain.Models;
  160. using ExpertCodeBlogWebApp.ViewModels;
  161. using Microsoft.AspNetCore.Mvc;
  162. using Microsoft.Extensions.Logging;
  163. using Microsoft.IdentityModel.Tokens;
  164. using Newtonsoft.Json;
  165.  
  166. namespace ExpertCodeBlogWebApp.Controllers
  167. {
  168.  
  169. [Route("api/[controller]")]
  170. public class JwtController : Controller
  171. {
  172. #region Private Members
  173. // JWT-related members
  174. private TimeSpan TokenExpiration;
  175. private SigningCredentials SigningCredentials;
  176. // EF and Identity members, available through DI
  177. private MyDbContext DbContext;
  178. private IUserRepository _userRepository;
  179. private readonly ILogger _logger;
  180. #endregion Private Members
  181.  
  182. #region Static Members
  183. private static readonly string PrivateKey = "my_PrivateKey";
  184. public static readonly SymmetricSecurityKey SecurityKey =
  185. new SymmetricSecurityKey(Encoding.ASCII.GetBytes(PrivateKey));
  186. public static readonly string Issuer = "my_Issuer";
  187. public static readonly string Audience = "my_Audience";
  188. #endregion Static Members
  189.  
  190. #region Constructor
  191. // I have used Autofac in the Startup.cs for dependency injection)
  192. public JwtController(
  193. MyDbContext dbContext,
  194. IUserRepository userRepository,
  195. ILogger<JwtController> logger)
  196. {
  197. _logger = logger;
  198. _userRepository = userRepository;
  199. // Instantiate JWT-related members
  200. TokenExpiration = TimeSpan.FromMinutes(10);
  201. SigningCredentials = new SigningCredentials(SecurityKey,
  202. SecurityAlgorithms.HmacSha256);
  203. // Instantiate through Dependency Injection with Autofact
  204. DbContext = dbContext;
  205. }
  206. #endregion Constructor
  207.  
  208. #region Public Methods
  209. // Manages the request for a new authentication or the refresh of an
  210. // already established one
  211. [HttpPost("token")]
  212. public async Task<IActionResult>
  213. Authentication([FromBody]JwtRequestViewModel jwt)
  214. {
  215. if (ModelState.IsValid)
  216. {
  217. string grantType = jwt.GrantType;
  218. if (grantType == "password")
  219. {
  220. string userName = jwt.UserName;
  221. string password = jwt.Password;
  222.  
  223. // Password check required
  224. var user = await
  225. _userRepository.GetUserInfoWithCheckPwd(userName, password);
  226.  
  227. // Check if user is expired (check the ExpireDate property)
  228. if (UserExpired(user))
  229. return BadRequest($"Account of {user.Name} expired!");
  230.  
  231. if (UserEnabled(user))
  232. return await GenerateToken(user);
  233. else
  234. return BadRequest("User name or password invalid.");
  235. }
  236. }
  237. else if (grantType == "refresh_token")
  238. {
  239. string userName = jwt.UserName;
  240.  
  241. // Refresh token (no password check required)
  242. var user = await _userRepository.GetUserInfoByName(userName);
  243.  
  244. // Check if user is expired (check the ExpireDate property)
  245. if (UserExpired(user))
  246. return BadRequest($"Account of {user.Name} expired!");
  247.  
  248. string token = jwt.Token;
  249. if (token == user.Token)
  250. {
  251. // Generate token and send it via a json-formatted string
  252. return await GenerateToken(user);
  253. }
  254. else
  255. {
  256. return BadRequest("User token invalid.");
  257. }
  258. }
  259. else
  260. return BadRequest("Authentication type invalid.");
  261. }
  262. else
  263. return BadRequest("Request invalid.");
  264. }
  265. #endregion Public Methods
  266.  
  267. #region Private Methods
  268. private bool UserExpired(Users utente)
  269. {
  270. if (utente != null)
  271. return utente.ExpireDate.CompareTo(DateTime.Now) < 0;
  272. return true;
  273. }
  274.  
  275. private bool UserEnabled(Users utente)
  276. {
  277. if (utente != null)
  278. return utente.Enabled == true;
  279. return false;
  280. }
  281.  
  282. private JsonSerializerSettings DefaultJsonSettings
  283. {
  284. get
  285. {
  286. return new JsonSerializerSettings()
  287. {
  288. Formatting = Formatting.Indented
  289. };
  290. }
  291. }
  292.  
  293. private async Task<IActionResult> GenerateToken(Users user)
  294. {
  295. try
  296. {
  297. if (user != null)
  298. {
  299. var handler = new JwtSecurityTokenHandler();
  300. DateTime newTokenExpiration = DateTime.Now.Add(TokenExpiration);
  301.  
  302. ClaimsIdentity identity = new ClaimsIdentity(
  303. new GenericIdentity(user.Name, "TokenAuth"),
  304. new[] { new Claim("ID", user.Id.ToString())}
  305. );
  306.  
  307. var securityToken = handler.CreateToken(new SecurityTokenDescriptor
  308. {
  309. Issuer = JwtController.Issuer,
  310. Audience = JwtController.Audience,
  311. SigningCredentials = SigningCredentials,
  312. Subject = identity,
  313. Expires = newTokenExpiration
  314. });
  315. string encodedToken = handler.WriteToken(securityToken);
  316.  
  317. // Update token data on database
  318. await _userRepository.UpdateTokenData(user.Name, encodedToken,
  319. newTokenExpiration);
  320. // Build the json response
  321. // (I use Automapper to maps an object into another object)
  322. var jwtResponse = Mapper.Map<JwtResponseViewModel>(user);
  323. jwtResponse.AccessToken = encodedToken;
  324. jwtResponse.Expiration = (int)TokenExpiration.TotalSeconds;
  325. return Ok(jwtResponse);
  326. }
  327. return NotFound();
  328. }
  329. catch(Exception e)
  330. {
  331. return BadRequest(e.Message);
  332. }
  333. }
  334. #endregion
  335. }
  336. }
  337.  
  338. login(userName: string, password: string)
  339. {
  340. return this.getLoginEndpoint(userName, password)
  341. .map((response: Response) => this.processLoginResponse(response));
  342. }
  343.  
  344. getLoginEndpoint(userName: string, password: string): Observable<Response>
  345. {
  346. // Body
  347. // JwtRequest is a model class that I use to send info to the controller
  348. let jwt = new JwtRequest();
  349. jwt.GrantType = "password";
  350. jwt.UserName = userName;
  351. jwt.Password = password;
  352. jwt.ClientId = "my_Issuer";
  353. // Post requiest (I use getAuthHeader that attach to the header the
  354. // authentication token, but it can also be omitted because it is ignored
  355. // by the JwtController
  356. return this.http.post(this.loginUrl, JSON.stringify(jwt),
  357. this.getAuthHeader(true))
  358. }
  359.  
  360. protected getAuthHeader(includeJsonContentType?: boolean): RequestOptions
  361. {
  362. // Hera I use this.authService.accessToken that is a my service where
  363. // I have store the token received from the server
  364. let headers = new Headers({
  365. 'Authorization': 'Bearer ' + this.authService.accessToken });
  366.  
  367. if (includeJsonContentType)
  368. headers.append("Content-Type", "application/json");
  369.  
  370. headers.append("Accept", `application/vnd.iman.v01+json,
  371. application/json, text/plain, */*`);
  372. headers.append("App-Version", "01");
  373.  
  374. return new RequestOptions({ headers: headers });
  375. }
  376.  
  377. private processLoginResponse(response: Response)
  378. {
  379. // process the response..
  380. }
  381.  
  382. [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement