source: Farmatiko/Controllers/LoginController.cs@ db484c9

Last change on this file since db484c9 was db484c9, checked in by DimitarSlezenkovski <dslezenkovski@…>, 22 months ago

Fix bugs

  • Property mode set to 100644
File size: 8.8 KB
Line 
1using System;
2using System.ComponentModel.DataAnnotations;
3using System.Security.Claims;
4using System.Text.Json.Serialization;
5using System.Threading.Tasks;
6using FarmatikoData.Models;
7using FarmatikoServices.Auth;
8using FarmatikoServices.FarmatikoServiceInterfaces;
9using FarmatikoServices.Infrastructure;
10using Microsoft.AspNetCore.Authentication;
11using Microsoft.AspNetCore.Authorization;
12using Microsoft.AspNetCore.Http;
13using Microsoft.AspNetCore.Mvc;
14using Microsoft.Extensions.Logging;
15using Microsoft.IdentityModel.Tokens;
16
17namespace Farmatiko.Controllers
18{
19 [ApiController]
20 public class LoginController : ControllerBase
21 {
22 private readonly ILogger<LoginController> _logger;
23 private readonly IAuthService _authService;
24 private readonly IJwtAuthManager _jwtAuthManager;
25 private readonly IPHService _pHService;
26
27 public LoginController(ILogger<LoginController> logger, IAuthService authService, IJwtAuthManager jwtAuthManager, IPHService pHService)
28 {
29 _logger = logger;
30 _authService = authService;
31 _jwtAuthManager = jwtAuthManager;
32 _pHService = pHService;
33 }
34
35 [AllowAnonymous]
36 [HttpPost("api/pharmacyhead/login")]
37 public ActionResult Login([FromBody] LoginRequest request)
38 {
39 if (!ModelState.IsValid)
40 {
41 return BadRequest();
42 }
43
44 if (!_authService.IsValidUserCredentials(request.UserName, request.Password))
45 {
46 return Unauthorized();
47 }
48
49 var role = _authService.GetUserRole(request.UserName);
50 var claims = new[]
51 {
52 new Claim(ClaimTypes.Name,request.UserName),
53 new Claim(ClaimTypes.Role, role)
54 };
55
56 var jwtResult = _jwtAuthManager.GenerateTokens(request.UserName, claims, DateTime.Now);
57 _logger.LogInformation($"User [{request.UserName}] logged in the system.");
58 return Ok(new LoginResult
59 {
60 UserName = request.UserName,
61 Role = role,
62 AccessToken = jwtResult.AccessToken,
63 RefreshToken = jwtResult.RefreshToken.TokenString,
64 Head = _pHService.GetPharmacyHead(request.UserName)
65 });
66 }
67
68 [HttpGet("api/pharmacyhead/user")]
69 [Authorize]
70 public ActionResult GetCurrentUser()
71 {
72 return Ok(new LoginResult
73 {
74 UserName = User.Identity.Name,
75 Role = User.FindFirst(ClaimTypes.Role)?.Value ?? string.Empty,
76 OriginalUserName = User.FindFirst("OriginalUserName")?.Value
77 });
78 }
79
80 [HttpPost("api/pharmacyhead/logout")]
81 [Authorize]
82 public ActionResult Logout()
83 {
84 var userName = User.Identity.Name;
85 _jwtAuthManager.RemoveRefreshTokenByUserName(userName);
86 _logger.LogInformation($"User [{userName}] logged out the system.");
87 return Ok();
88 }
89
90 [HttpPost("api/pharmacyhead/refresh-token")]
91 [Authorize]
92 public async Task<ActionResult> RefreshToken([FromBody] RefreshTokenRequest request)
93 {
94 try
95 {
96 var userName = User.Identity.Name;
97 _logger.LogInformation($"User [{userName}] is trying to refresh JWT token.");
98
99 if (string.IsNullOrWhiteSpace(request.RefreshToken))
100 {
101 return Unauthorized();
102 }
103
104 var accessToken = await HttpContext.GetTokenAsync("Bearer", "access_token");
105 var jwtResult = _jwtAuthManager.Refresh(request.RefreshToken, accessToken, DateTime.Now);
106 _logger.LogInformation($"User [{userName}] has refreshed JWT token.");
107 return Ok(new LoginResult
108 {
109 /*UserName = userName,
110
111 Role = User.FindFirst(ClaimTypes.Role)?.Value ?? string.Empty,
112 AccessToken = jwtResult.AccessToken,
113 RefreshToken = jwtResult.RefreshToken.TokenString*/
114
115 UserName = userName,
116 Role = User.FindFirst(ClaimTypes.Role)?.Value ?? string.Empty,
117 AccessToken = jwtResult.AccessToken,
118 RefreshToken = jwtResult.RefreshToken.TokenString,
119 Head = _pHService.GetPharmacyHead(userName)
120 });
121 }
122 catch (SecurityTokenException e)
123 {
124 return Unauthorized(e.Message); // return 401 so that the client side can redirect the user to login page
125 }
126 }
127
128 [HttpPost("api/pharmacyhead/impersonation")]
129 [Authorize(Roles = UserRoles.Admin)]
130 public ActionResult Impersonate([FromBody] ImpersonationRequest request)
131 {
132 var userName = User.Identity.Name;
133 _logger.LogInformation($"User [{userName}] is trying to impersonate [{request.UserName}].");
134
135 var impersonatedRole = _authService.GetUserRole(request.UserName);
136 if (string.IsNullOrWhiteSpace(impersonatedRole))
137 {
138 _logger.LogInformation($"User [{userName}] failed to impersonate [{request.UserName}] due to the target user not found.");
139 return BadRequest($"The target user [{request.UserName}] is not found.");
140 }
141 if (impersonatedRole == UserRoles.Admin)
142 {
143 _logger.LogInformation($"User [{userName}] is not allowed to impersonate another Admin.");
144 return BadRequest("This action is not supported.");
145 }
146
147 var claims = new[]
148 {
149 new Claim(ClaimTypes.Name,request.UserName),
150 new Claim(ClaimTypes.Role, impersonatedRole),
151 new Claim("OriginalUserName", userName)
152 };
153
154 var jwtResult = _jwtAuthManager.GenerateTokens(request.UserName, claims, DateTime.Now);
155 _logger.LogInformation($"User [{request.UserName}] is impersonating [{request.UserName}] in the system.");
156 return Ok(new LoginResult
157 {
158 UserName = request.UserName,
159 Role = impersonatedRole,
160 OriginalUserName = userName,
161 AccessToken = jwtResult.AccessToken,
162 RefreshToken = jwtResult.RefreshToken.TokenString,
163 Head = _pHService.GetPharmacyHead(userName)
164 });
165 }
166
167 [HttpPost("api/pharmacyhead/stop-impersonation")]
168 public ActionResult StopImpersonation()
169 {
170 var userName = User.Identity.Name;
171 var originalUserName = User.FindFirst("OriginalUserName")?.Value;
172 if (string.IsNullOrWhiteSpace(originalUserName))
173 {
174 return BadRequest("You are not impersonating anyone.");
175 }
176 _logger.LogInformation($"User [{originalUserName}] is trying to stop impersonate [{userName}].");
177
178 var role = _authService.GetUserRole(originalUserName);
179 var claims = new[]
180 {
181 new Claim(ClaimTypes.Name,originalUserName),
182 new Claim(ClaimTypes.Role, role)
183 };
184
185 var jwtResult = _jwtAuthManager.GenerateTokens(originalUserName, claims, DateTime.Now);
186 _logger.LogInformation($"User [{originalUserName}] has stopped impersonation.");
187 return Ok(new LoginResult
188 {
189 UserName = originalUserName,
190 Role = role,
191 OriginalUserName = null,
192 AccessToken = jwtResult.AccessToken,
193 RefreshToken = jwtResult.RefreshToken.TokenString,
194 Head = _pHService.GetPharmacyHead(userName)
195 });
196 }
197 }
198
199 public class LoginRequest
200 {
201 [Required]
202 [JsonPropertyName("username")]
203 public string UserName { get; set; }
204
205 [Required]
206 [JsonPropertyName("password")]
207 public string Password { get; set; }
208 }
209
210 public class LoginResult
211 {
212 [JsonPropertyName("userName")]
213 public string UserName { get; set; }
214
215 [JsonPropertyName("role")]
216 public string Role { get; set; }
217
218 [JsonPropertyName("originalUserName")]
219 public string OriginalUserName { get; set; }
220
221 [JsonPropertyName("accessToken")]
222 public string AccessToken { get; set; }
223
224 [JsonPropertyName("refreshToken")]
225 public string RefreshToken { get; set; }
226 [JsonPropertyName("head")]
227 public object Head { get; set; }
228 }
229
230 public class RefreshTokenRequest
231 {
232 [JsonPropertyName("refreshToken")]
233 public string RefreshToken { get; set; }
234 }
235
236 public class ImpersonationRequest
237 {
238 [JsonPropertyName("userName")]
239 public string UserName { get; set; }
240 }
241}
242
Note: See TracBrowser for help on using the repository browser.