Skip to content

Commit 84bc4b5

Browse files
committed
jwt working without policy
1 parent fcdd76d commit 84bc4b5

File tree

14 files changed

+153
-204
lines changed

14 files changed

+153
-204
lines changed
Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,30 @@
1-
using Microsoft.AspNetCore.Authorization;
2-
using Microsoft.AspNetCore.Http;
3-
using Microsoft.AspNetCore.Mvc;
4-
using System;
5-
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Threading.Tasks;
8-
using Xero.Demo.Api.Xero.Demo.Domain.Models;
1+
using Microsoft.AspNetCore.Mvc;
2+
using Xero.Demo.Api.Domain;
3+
using Xero.Demo.Api.Domain.Extension;
4+
using Xero.Demo.Api.Xero.Demo.Domain.Services;
5+
using static Xero.Demo.Api.Domain.Models.CONSTANTS;
96

107
namespace Xero.Demo.Api.Endpoints.Common
118
{
12-
[Route("api/[controller]")]
13-
[ApiController]
14-
public class UsersController : ControllerBase
9+
[ApiVersion(ApiVersionNumbers.V1)]
10+
[ApiVersion(ApiVersionNumbers.V2)]
11+
public class UsersController : BaseApiController
1512
{
16-
private readonly IUserService _user;
13+
private readonly IUserService _userService;
1714

18-
public UsersController(IUserService user)
15+
public UsersController(IUserService userService)
1916
{
20-
this._user = user;
17+
this._userService = userService;
2118
}
2219

2320
[HttpPost("authenticate")]
24-
public IActionResult Authenticate(AuthenticateRequest model)
21+
public IActionResult Authenticate(string culture = "en-US")
2522
{
26-
var response = _user.Authenticate(model);
23+
var response = _userService.Authenticate();
2724

28-
if (response == null)
29-
return BadRequest(new { message = "Username or password is incorrect" });
25+
if (response == null) return BadRequest(ModelState.GetErrorMessages());
3026

3127
return Ok(response);
3228
}
33-
34-
[Authorize]
35-
[HttpGet]
36-
public IActionResult GetAll()
37-
{
38-
var users = _user.GetAll();
39-
return Ok(users);
40-
}
4129
}
4230
}

src/Api/Endpoints/V1/Products/Create.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Xero.Demo.Api.Domain;
88
using Xero.Demo.Api.Domain.Extension;
99
using Xero.Demo.Api.Domain.Models;
10+
using Xero.Demo.Api.Xero.Demo.Domain.Models;
1011
using static Xero.Demo.Api.Domain.Models.CONSTANTS;
1112

1213
namespace Xero.Demo.Api.Endpoints.V1.Products
@@ -26,7 +27,7 @@ public ProductsController(Database db)
2627
/// <param name="product">Enter the product</param>
2728
/// <param name="culture">Enter the culture</param>
2829
/// <returns></returns>
29-
[Authorize("ShouldContainRole")]
30+
[Authorize]
3031
[FeatureGate(Features.PRODUCT)]
3132
[ApiVersion(ApiVersionNumbers.V1)]
3233
[HttpPost("", Name = RouteNames.PostAsync)]

src/Api/Product.db

0 Bytes
Binary file not shown.

src/Api/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"environmentVariables": {
2323
"ASPNETCORE_ENVIRONMENT": "Development"
2424
},
25-
"applicationUrl": "https://localhost:5001;http://localhost:5000"
25+
"applicationUrl": "http://localhost:5000"
2626
}
2727
}
2828
}

src/Api/Xero.Demo.Domain/Models/AuthenticateResponse.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ namespace Xero.Demo.Api.Xero.Demo.Domain.Models
88
public class AuthenticateResponse
99
{
1010
public int Id { get; set; }
11-
public string FirstName { get; set; }
12-
public string LastName { get; set; }
11+
public string Name { get; set; }
1312
public string Username { get; set; }
1413
public string Token { get; set; }
14+
public string Role { get; set; }
1515

16-
public AuthenticateResponse(User user, string token)
16+
public AuthenticateResponse(User user, string token, string role)
1717
{
1818
Id = user.Id;
19-
FirstName = user.FirstName;
20-
LastName = user.LastName;
19+
Name = user.Name;
2120
Username = user.Username;
2221
Token = token;
22+
Role = role;
2323
}
2424
}
2525
}

src/Api/Xero.Demo.Domain/Models/AppSettings.cs renamed to src/Api/Xero.Demo.Domain/Models/JwtSettings.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
namespace Xero.Demo.Api.Xero.Demo.Domain.Models
77
{
8-
public class AppSettings
8+
public class JwtSettings
99
{
10-
public string Secret { get; set; }
10+
public string SecretKey { get; set; }
11+
public string Issuer { get; set; }
12+
public string Audience { get; set; }
1113
}
1214
}
Lines changed: 8 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,21 @@
1-
using Microsoft.Extensions.Options;
2-
using Microsoft.IdentityModel.Tokens;
3-
using System;
4-
using System.Collections.Generic;
5-
using System.IdentityModel.Tokens.Jwt;
6-
using System.Linq;
7-
using System.Security.Claims;
8-
using System.Text;
1+
using System.Collections.Generic;
2+
using static Xero.Demo.Api.Domain.Models.CONSTANTS;
93

104
namespace Xero.Demo.Api.Xero.Demo.Domain.Models
115
{
126
public class User
137
{
14-
public string FirstName { get; set; }
158
public int Id { get; set; }
16-
public string LastName { get; set; }
9+
public string Name { get; set; }
1710
public string Password { get; set; }
1811
public string Username { get; set; }
19-
}
20-
21-
public interface IUserService
22-
{
23-
AuthenticateResponse Authenticate(AuthenticateRequest model);
24-
25-
IEnumerable<User> GetAll();
26-
27-
User GetById(int id);
28-
}
12+
public string Role { get; set; }
2913

30-
public class UserService : IUserService
31-
{
32-
private List<User> _users = new List<User>
14+
public static List<User> Users = new List<User>
3315
{
34-
new User {Id= 1,FirstName= "FirstName",LastName ="LastName", Username="string", Password="string" }
16+
new User {Id= 1,Name= "Xero", Username="Admin", Password="Password",Role=Roles.Admin },
17+
new User {Id= 2,Name= "Azy", Username="Editor", Password="Password",Role=Roles.Editor},
18+
new User {Id= 2,Name= "Azy", Username="Reader", Password="Password",Role=Roles.Reader}
3519
};
36-
37-
private readonly AppSettings _appSettings;
38-
39-
public UserService(IOptions<AppSettings> appSettings)
40-
{
41-
_appSettings = appSettings.Value;
42-
}
43-
44-
public AuthenticateResponse Authenticate(AuthenticateRequest model)
45-
{
46-
var user = _users.SingleOrDefault(x => x.Username == model.Username && x.Password == model.Password);
47-
48-
if (user == null) return null;
49-
50-
var token = generateJwtToken(user);
51-
52-
return new AuthenticateResponse(user, token);
53-
}
54-
55-
public IEnumerable<User> GetAll()
56-
{
57-
return _users;
58-
}
59-
60-
public User GetById(int id)
61-
{
62-
return _users.FirstOrDefault(x => x.Id == id);
63-
}
64-
65-
private string generateJwtToken(User user)
66-
{
67-
// generate token that is valid for 7 days
68-
var tokenHandler = new JwtSecurityTokenHandler();
69-
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
70-
var tokenDescriptor = new SecurityTokenDescriptor
71-
{
72-
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()), new Claim(ClaimTypes.Role, "Admin") }),
73-
Expires = DateTime.UtcNow.AddDays(7),
74-
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
75-
};
76-
var token = tokenHandler.CreateToken(tokenDescriptor);
77-
return tokenHandler.WriteToken(token);
78-
}
7920
}
8021
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using Microsoft.Extensions.Options;
2+
using Microsoft.IdentityModel.Tokens;
3+
using System;
4+
using System.IdentityModel.Tokens.Jwt;
5+
using System.Linq;
6+
using System.Security.Claims;
7+
using System.Text;
8+
using Xero.Demo.Api.Xero.Demo.Domain.Models;
9+
10+
namespace Xero.Demo.Api.Xero.Demo.Domain.Services
11+
{
12+
public interface IUserService
13+
{
14+
AuthenticateResponse Authenticate();
15+
16+
User GetById(int userId);
17+
}
18+
19+
public class UserService : IUserService
20+
{
21+
private readonly JwtSettings _jwtSettings;
22+
23+
public UserService(IOptions<JwtSettings> jwtSettings)
24+
{
25+
_jwtSettings = jwtSettings.Value;
26+
}
27+
28+
public AuthenticateResponse Authenticate()
29+
{
30+
var user = User.Users.First();
31+
32+
return new AuthenticateResponse(user, GenerateJWTToken(user), user.Role);
33+
}
34+
35+
public User GetById(int userId)
36+
{
37+
return User.Users.FirstOrDefault(u => u.Id == userId);
38+
}
39+
40+
private string GenerateJWTToken(User userInfo)
41+
{
42+
var token = new JwtSecurityToken(
43+
issuer: _jwtSettings.Issuer,
44+
audience: _jwtSettings.Audience,
45+
claims: new[]
46+
{
47+
new Claim("id", userInfo.Id.ToString()),
48+
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Username),
49+
new Claim("Name", userInfo.Name+userInfo.Name.ToString()),
50+
new Claim("Role",userInfo.Role),
51+
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
52+
},
53+
expires: DateTime.Now.AddMinutes(10),
54+
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)), SecurityAlgorithms.HmacSha256)
55+
);
56+
return new JwtSecurityTokenHandler().WriteToken(token);
57+
}
58+
}
59+
}

src/Api/Xero.Demo.Infrastructure/Extensions/AddAuthorizationExtension.cs

Lines changed: 19 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,83 +10,42 @@
1010
using System.Text;
1111
using Xero.Demo.Api.Domain.Security;
1212
using Xero.Demo.Api.Xero.Demo.Domain.Models;
13+
using Xero.Demo.Api.Xero.Demo.Domain.Services;
14+
using static Xero.Demo.Api.Domain.Models.CONSTANTS;
1315

1416
namespace Xero.Demo.Api.Domain.Infrastructure
1517
{
1618
public static partial class AddAuthorizationExtension
1719
{
18-
public static IServiceCollection AddRolesAndPolicyAuthorization(this IServiceCollection services)
20+
public static IServiceCollection AddSecurity(this IServiceCollection services)
1921
{
20-
services.AddScoped<IUserService, UserService>();
21-
services.AddAuthorization(
22-
config =>
23-
{
24-
config.AddPolicy("ShouldBeAnAdmin", options =>
25-
{
26-
options.RequireAuthenticatedUser();
27-
options.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
28-
options.Requirements.Add(new ShouldBeAnAdminRequirement());
29-
});
30-
31-
config.AddPolicy("ShouldBeAnEditor", options =>
32-
{
33-
options.RequireClaim(ClaimTypes.Role);
34-
options.RequireRole("Reader");
35-
options.RequireAuthenticatedUser();
36-
options.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
37-
options.Requirements.Add(new ShouldBeAReaderRequirement());
38-
});
39-
40-
config.AddPolicy("ShouldBeAReader", options =>
41-
{
42-
options.RequireClaim(ClaimTypes.Role);
43-
options.RequireRole("Reader");
44-
options.RequireAuthenticatedUser();
45-
options.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
46-
options.Requirements.Add(new ShouldBeAReaderRequirement());
47-
});
48-
49-
config.AddPolicy("ShouldContainRole", options =>
50-
options.RequireClaim(ClaimTypes.Role));
51-
});
52-
5322
return services;
5423
}
5524

5625
public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, IConfiguration configuration)
5726
{
58-
services.AddAuthentication(x =>
59-
{
60-
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
61-
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
62-
})
63-
.AddJwtBearer(x =>
27+
services.AddScoped<IUserService, UserService>();
28+
29+
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
30+
.AddJwtBearer(options =>
6431
{
65-
x.RequireHttpsMetadata = false;
66-
x.SaveToken = true;
67-
x.TokenValidationParameters = new TokenValidationParameters
32+
options.RequireHttpsMetadata = false;
33+
options.SaveToken = true;
34+
options.TokenValidationParameters = new TokenValidationParameters
6835
{
36+
ValidateIssuer = true,
37+
ValidateAudience = true,
38+
ValidateLifetime = true,
6939
ValidateIssuerSigningKey = true,
70-
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("hdftasdvjrlvfvfjyvwevfcmdfkjsdnhvzfmbnsdfvm")),
71-
ValidateIssuer = false,
72-
ValidateAudience = false
40+
ValidIssuer = configuration["Jwt:Issuer"],
41+
ValidAudience = configuration["Jwt:Audience"],
42+
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecretKey"])),
43+
ClockSkew = TimeSpan.Zero
7344
};
7445
});
75-
return services;
76-
}
77-
}
7846

79-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
80-
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
81-
{
82-
public void OnAuthorization(AuthorizationFilterContext context)
83-
{
84-
var user = (User)context.HttpContext.Items["User"];
85-
if (user == null)
86-
{
87-
// not logged in
88-
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
89-
}
47+
services.AddAuthorization();
48+
return services;
9049
}
9150
}
9251
}

0 commit comments

Comments
 (0)