Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

AuthenticationServiceTests.cs 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. using AutoMapper;
  2. using Diligent.WebAPI.Business.MappingProfiles;
  3. using Diligent.WebAPI.Business.Services;
  4. using Diligent.WebAPI.Business.Settings;
  5. using Diligent.WebAPI.Contracts.DTOs;
  6. using Diligent.WebAPI.Contracts.DTOs.Auth;
  7. using Diligent.WebAPI.Contracts.Models;
  8. using Diligent.WebAPI.Data.Entities;
  9. using Microsoft.AspNetCore.Identity;
  10. using Microsoft.AspNetCore.WebUtilities;
  11. using Microsoft.EntityFrameworkCore;
  12. using Microsoft.Extensions.Logging;
  13. using Microsoft.Extensions.Options;
  14. using NSubstitute.ReturnsExtensions;
  15. using System.Text;
  16. namespace Diligent.WebAPI.Tests.Services
  17. {
  18. public class AuthenticationServiceTests
  19. {
  20. private readonly List<User> _users;
  21. private readonly List<RefreshToken> _tokens;
  22. private readonly IUserStore<User> _mockStore;
  23. private readonly UserManager<User> _mockUserManager;
  24. private readonly IEmailer _emailer = Substitute.For<IEmailer>();
  25. private readonly IMapper _mapper;
  26. private readonly ILogger<AuthenticationService> _logger = Substitute.For<ILogger<AuthenticationService>>();
  27. private readonly IHttpClientService _httpClient = Substitute.For<IHttpClientService>();
  28. public AuthenticationServiceTests()
  29. {
  30. _mockStore = Substitute.For<IUserStore<User>>();
  31. _mockUserManager = Substitute.For<UserManager<User>>(_mockStore, null, null, null, null, null, null, null, null);
  32. _tokens = new List<RefreshToken>
  33. {
  34. new RefreshToken
  35. {
  36. Id = 1,
  37. CreationDate = DateTime.Now,
  38. ExpiryDate = DateTime.Now.AddDays(5),
  39. UserId = 1,
  40. Invalidated = false,
  41. JwtId = "string",
  42. Used = false,
  43. Token = "refresh"
  44. },
  45. new RefreshToken
  46. {
  47. Id = 4,
  48. CreationDate = DateTime.Now,
  49. ExpiryDate = DateTime.Now.AddDays(5),
  50. UserId = 2,
  51. Invalidated = false,
  52. JwtId = "string",
  53. Used = false,
  54. Token = "refresh"
  55. },
  56. new RefreshToken
  57. {
  58. Id = 3,
  59. CreationDate = DateTime.Now,
  60. ExpiryDate = DateTime.Now.AddDays(5),
  61. UserId = 3,
  62. Invalidated = false,
  63. JwtId = "string",
  64. Used = false,
  65. Token = "refresh"
  66. }
  67. };
  68. _users = new List<User>
  69. {
  70. new User
  71. {
  72. Id = 1,
  73. PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==",
  74. FirstName = "User",
  75. LastName = "One",
  76. UserName = "user1",
  77. NormalizedUserName = "USER1",
  78. Email = "user1@dilig.net",
  79. NormalizedEmail = "USER1@DILIG.NET",
  80. EmailConfirmed = false,
  81. IsEnabled = true,
  82. AccessFailedCount = 0,
  83. SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  84. ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  85. },
  86. new User
  87. {
  88. Id = 2,
  89. PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==",
  90. FirstName = "User",
  91. LastName = "Two",
  92. UserName = "user2",
  93. NormalizedUserName = "USER2",
  94. Email = "user2@dilig.net",
  95. NormalizedEmail = "USER2@DILIG.NET",
  96. EmailConfirmed = false,
  97. IsEnabled = true,
  98. AccessFailedCount = 0,
  99. SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  100. ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  101. },
  102. new User
  103. {
  104. Id = 3,
  105. PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==",
  106. FirstName = "User",
  107. LastName = "Three",
  108. UserName = "user3",
  109. NormalizedUserName = "USER3",
  110. Email = "user3@dilig.net",
  111. NormalizedEmail = "USER3@DILIG.NET",
  112. EmailConfirmed = false,
  113. IsEnabled = false,
  114. AccessFailedCount = 0,
  115. SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  116. ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  117. },
  118. new User
  119. {
  120. Id = 4,
  121. PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==",
  122. FirstName = "User",
  123. LastName = "Four",
  124. UserName = "user4",
  125. NormalizedUserName = "USER4",
  126. Email = "user4@dilig.net",
  127. NormalizedEmail = "USER4@DILIG.NET",
  128. EmailConfirmed = false,
  129. IsEnabled = true,
  130. AccessFailedCount = 0,
  131. SecurityStamp = "ZYA3WYFOWDEQRWYKEXVKIBPI3C5XZZNM",
  132. ConcurrencyStamp = "9f3174d6-dd77-4549-ae51-ec81d630d7ff",
  133. },
  134. new User
  135. {
  136. Id = 5,
  137. PasswordHash = "AQAAAAEAACcQAAAAEK8x77a+af9qKiHc6Lq2OKLmzCjqhws/qn2g4ByHwAXoDp7/3aT38M47oTPZQ1rqyg==",
  138. FirstName = "User",
  139. LastName = "Four",
  140. UserName = "user5",
  141. NormalizedUserName = "USER5",
  142. Email = "user5@dilig.net",
  143. NormalizedEmail = "USER5@DILIG.NET",
  144. EmailConfirmed = false,
  145. IsEnabled = true,
  146. AccessFailedCount = 0,
  147. SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  148. ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX",
  149. }
  150. };
  151. // configure mapper
  152. var configuration = new MapperConfiguration(cfg => cfg.AddProfiles(
  153. new List<Profile>
  154. {
  155. new UserMappingProfile()
  156. }));
  157. _mapper = new Mapper(configuration);
  158. }
  159. [Fact]
  160. public async Task Authenticate_ShouldReturnError_IfInvalidUsername()
  161. {
  162. _mockUserManager.FindByNameAsync(Arg.Any<string>()).ReturnsNull();
  163. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  164. var frontEndSettings = Options.Create(new FrontEndSettings
  165. {
  166. BaseUrl = "some url"
  167. });
  168. var authSettings = Options.Create(new AuthorizationSettings { });
  169. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  170. var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  171. {
  172. Username = "Any",
  173. Password = "Any"
  174. });
  175. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  176. {
  177. IsError = true,
  178. ErrorMessage = "Username is not valid"
  179. });
  180. }
  181. [Fact]
  182. public async Task Authenticate_ShouldCall_CheckPasswordAsync()
  183. {
  184. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]);
  185. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  186. var frontEndSettings = Options.Create(new FrontEndSettings
  187. {
  188. BaseUrl = "some url"
  189. });
  190. var authSettings = Options.Create(new AuthorizationSettings { });
  191. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  192. await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  193. {
  194. Username = _users[1].Email,
  195. Password = "Any"
  196. });
  197. await _mockUserManager.Received(1).CheckPasswordAsync(_users[1], "Any");
  198. }
  199. [Fact]
  200. public async Task Authenticate_ShouldReturnError_IfUserIsDisabled()
  201. {
  202. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[2]);
  203. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  204. var frontEndSettings = Options.Create(new FrontEndSettings
  205. {
  206. BaseUrl = "some url"
  207. });
  208. var authSettings = Options.Create(new AuthorizationSettings { });
  209. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  210. var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  211. {
  212. Username = _users[2].Email,
  213. Password = "Any"
  214. });
  215. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  216. {
  217. IsError = true,
  218. ErrorMessage = $"User with email {_users[2].Email} has no permission to log in."
  219. });
  220. }
  221. [Fact]
  222. public async Task Authenticate_ShouldReturnError_IfInvalidPassword()
  223. {
  224. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]);
  225. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  226. var frontEndSettings = Options.Create(new FrontEndSettings
  227. {
  228. BaseUrl = "some url"
  229. });
  230. var authSettings = Options.Create(new AuthorizationSettings { });
  231. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  232. var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  233. {
  234. Username = _users[1].Email,
  235. Password = "Any"
  236. });
  237. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  238. {
  239. IsError = true,
  240. ErrorMessage = $"Password is not correct"
  241. });
  242. }
  243. [Fact]
  244. public async Task Authenticate_ShouldReturnError_IfUserIsLockedOut()
  245. {
  246. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[3]);
  247. _mockUserManager.CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(true);
  248. _mockUserManager.IsLockedOutAsync(Arg.Any<User>()).Returns(true);
  249. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  250. var frontEndSettings = Options.Create(new FrontEndSettings
  251. {
  252. BaseUrl = "some url"
  253. });
  254. var authSettings = Options.Create(new AuthorizationSettings {
  255. Secret = "S1231251WAS124AS"
  256. });
  257. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  258. var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  259. {
  260. Username = _users[3].Email,
  261. Password = "Nekasifra123!"
  262. });
  263. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  264. {
  265. IsError = true,
  266. ErrorMessage = "The account is locked out"
  267. });
  268. }
  269. [Fact]
  270. public async Task Authenticate_ShouldGenerateToken_IfCredsAreValid()
  271. {
  272. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]);
  273. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  274. var frontEndSettings = Options.Create(new FrontEndSettings
  275. {
  276. BaseUrl = "some url"
  277. });
  278. var authSettings = Options.Create(new AuthorizationSettings { });
  279. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  280. var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  281. {
  282. Username = _users[1].Email,
  283. Password = "Nekasifra123!"
  284. });
  285. Assert.IsType<ServiceResponseDTO<AuthenticateResponseDto>>(result);
  286. }
  287. [Fact]
  288. public async Task AuthenticateGoogle_ShouldReturnError_IfInvalidApiToken()
  289. {
  290. _httpClient.IsTokenValid(Arg.Any<string>()).Returns(false);
  291. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  292. var frontEndSettings = Options.Create(new FrontEndSettings
  293. {
  294. BaseUrl = "some url"
  295. });
  296. var authSettings = Options.Create(new AuthorizationSettings { });
  297. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  298. var result = await service.Authenticate(new GoogleApiModel
  299. {
  300. Token = "t",
  301. User = new GoogleApiTokenInfo
  302. {
  303. email = "something@dilig.net"
  304. }
  305. });
  306. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  307. {
  308. IsError = true,
  309. ErrorMessage = "Invalid Google Api Token"
  310. });
  311. }
  312. [Fact]
  313. public async Task AuthenticateGoogle_ShouldReturnError_IfUserDoesntExist()
  314. {
  315. _httpClient.IsTokenValid(Arg.Any<string>()).Returns(true);
  316. _mockUserManager.FindByNameAsync(Arg.Any<string>()).ReturnsNull();
  317. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  318. var frontEndSettings = Options.Create(new FrontEndSettings
  319. {
  320. BaseUrl = "some url"
  321. });
  322. var authSettings = Options.Create(new AuthorizationSettings { });
  323. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  324. var result = await service.Authenticate(new GoogleApiModel
  325. {
  326. Token = "t",
  327. User = new GoogleApiTokenInfo
  328. {
  329. email = _users[1].Email,
  330. }
  331. });
  332. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  333. {
  334. IsError = true,
  335. ErrorMessage = $"User with email {_users[1].Email} does not exist in database"
  336. });
  337. }
  338. [Fact]
  339. public async Task AuthenticateGoogle_ShouldReturnError_IfUserIsDisabled()
  340. {
  341. _httpClient.IsTokenValid(Arg.Any<string>()).Returns(true);
  342. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[2]);
  343. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  344. var frontEndSettings = Options.Create(new FrontEndSettings
  345. {
  346. BaseUrl = "some url"
  347. });
  348. var authSettings = Options.Create(new AuthorizationSettings { });
  349. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  350. var result = await service.Authenticate(new GoogleApiModel
  351. {
  352. Token = "token",
  353. User = new GoogleApiTokenInfo
  354. {
  355. email = _users[2].Email,
  356. }
  357. });
  358. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  359. {
  360. IsError = true,
  361. ErrorMessage = $"User with email {_users[2].Email} has no permission to log in."
  362. });
  363. }
  364. [Fact]
  365. public async Task AuthenticateGoogle_ShouldGenerateToken()
  366. {
  367. _httpClient.IsTokenValid(Arg.Any<string>()).Returns(true);
  368. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  369. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  370. var frontEndSettings = Options.Create(new FrontEndSettings
  371. {
  372. BaseUrl = "some url"
  373. });
  374. var authSettings = Options.Create(new AuthorizationSettings
  375. {
  376. Secret = "S1231251WAS124AS"
  377. });
  378. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  379. var result = await service.Authenticate(new GoogleApiModel
  380. {
  381. Token = "token",
  382. User = new GoogleApiTokenInfo
  383. {
  384. email = _users[1].Email
  385. }
  386. });
  387. Assert.IsType<ServiceResponseDTO<AuthenticateResponseDto>>(result);
  388. }
  389. [Fact]
  390. public async Task Register_ShouldReturnError_IfUserNotFound()
  391. {
  392. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull();
  393. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  394. var frontEndSettings = Options.Create(new FrontEndSettings
  395. {
  396. BaseUrl = "some url"
  397. });
  398. var authSettings = Options.Create(new AuthorizationSettings { });
  399. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  400. var result = await service.Register(new Contracts.DTOs.User.RegisterDTO
  401. {
  402. Token = "token",
  403. LinkedIn = "Link",
  404. Confirm = "Password123!",
  405. Email = _users[1].Email,
  406. Password = "Password123!",
  407. Phone = "123",
  408. Position = "Senior Dev"
  409. });
  410. result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto>
  411. {
  412. IsError = true,
  413. ErrorMessage = "User not invited."
  414. });
  415. }
  416. [Fact]
  417. public async Task Register_ShouldCreateUser_IfUserExists()
  418. {
  419. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  420. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  421. var frontEndSettings = Options.Create(new FrontEndSettings
  422. {
  423. BaseUrl = "some url"
  424. });
  425. var authSettings = Options.Create(new AuthorizationSettings { });
  426. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  427. _mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>()).Returns(IdentityResult.Success);
  428. var result = await service.Register(new Contracts.DTOs.User.RegisterDTO
  429. {
  430. Token = "token",
  431. LinkedIn = "Link",
  432. Confirm = "Password123!",
  433. Email = _users[1].Email,
  434. Password = "Password123!",
  435. Phone = "123",
  436. Position = "Senior Dev"
  437. });
  438. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  439. {
  440. Data = true,
  441. });
  442. }
  443. [Fact]
  444. public async Task Register_ShouldThrowError_IfUnsuccessfulReset()
  445. {
  446. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  447. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  448. var frontEndSettings = Options.Create(new FrontEndSettings
  449. {
  450. BaseUrl = "some url"
  451. });
  452. var authSettings = Options.Create(new AuthorizationSettings { });
  453. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  454. _mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>())
  455. .Returns(IdentityResult.Failed(
  456. new IdentityError[] {
  457. new IdentityError {
  458. Description= "Failed"
  459. }
  460. }
  461. ));
  462. var result = await service.Register(new Contracts.DTOs.User.RegisterDTO
  463. {
  464. Token = "token",
  465. LinkedIn = "Link",
  466. Confirm = "Password123!",
  467. Email = _users[1].Email,
  468. Password = "Password123!",
  469. Phone = "123",
  470. Position = "Senior Dev"
  471. });
  472. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  473. {
  474. IsError = true,
  475. ErrorMessage = "Failed"
  476. });
  477. }
  478. [Fact]
  479. public async Task PasswordResetAsync_ShouldReturnError_IfUserNotFound()
  480. {
  481. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull();
  482. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  483. var frontEndSettings = Options.Create(new FrontEndSettings
  484. {
  485. BaseUrl = "some url"
  486. });
  487. var authSettings = Options.Create(new AuthorizationSettings { });
  488. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  489. var result = await service.PasswordResetAsync(
  490. email: _users[1].Email,
  491. code: "code",
  492. password: "Password123!"
  493. );
  494. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  495. {
  496. IsError = true,
  497. ErrorMessage = "Email did not find."
  498. });
  499. }
  500. [Fact]
  501. public async Task PasswordResetAsync_ShouldResetToken_IfUserFound()
  502. {
  503. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  504. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  505. var frontEndSettings = Options.Create(new FrontEndSettings
  506. {
  507. BaseUrl = "some url"
  508. });
  509. _mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>())
  510. .Returns(IdentityResult.Success);
  511. var authSettings = Options.Create(new AuthorizationSettings { });
  512. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  513. var result = await service.PasswordResetAsync(
  514. email: _users[1].Email,
  515. code: "code",
  516. password: "Password123!"
  517. );
  518. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  519. { Data = true }
  520. );
  521. }
  522. [Fact]
  523. public async Task PasswordResetAsync_ShouldReturnError_IfUnsuccessfulReset()
  524. {
  525. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  526. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  527. var frontEndSettings = Options.Create(new FrontEndSettings
  528. {
  529. BaseUrl = "some url"
  530. });
  531. _mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>())
  532. .Returns(IdentityResult.Failed(
  533. new IdentityError[] {
  534. new IdentityError {
  535. Description= "Failed"
  536. }
  537. }
  538. ));
  539. var authSettings = Options.Create(new AuthorizationSettings { });
  540. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  541. var result = await service.PasswordResetAsync(
  542. email: _users[1].Email,
  543. code: "code",
  544. password: "Password123!"
  545. );
  546. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  547. {
  548. IsError = true,
  549. ErrorMessage = "Failed"
  550. });
  551. }
  552. [Fact]
  553. public async Task GetForgotPasswordUrlAsync_ShouldReturnError_IfUserNotFound()
  554. {
  555. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull();
  556. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  557. var frontEndSettings = Options.Create(new FrontEndSettings
  558. {
  559. BaseUrl = "some url"
  560. });
  561. var authSettings = Options.Create(new AuthorizationSettings { });
  562. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  563. var result = await service.GetForgotPasswordUrlAsync(_users[1].Email);
  564. result.Should().BeEquivalentTo(new ServiceResponseDTO<object>
  565. {
  566. IsError = true,
  567. ErrorMessage = "Email did not find."
  568. });
  569. }
  570. [Fact]
  571. public async Task GetForgotPasswordUrlAsync_ShouldReturnSuccess_IfUserIsFound()
  572. {
  573. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  574. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  575. var frontEndSettings = Options.Create(new FrontEndSettings
  576. {
  577. BaseUrl = "some url"
  578. });
  579. var authSettings = Options.Create(new AuthorizationSettings { });
  580. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  581. await service.GetForgotPasswordUrlAsync(_users[1].Email);
  582. await _emailer.ReceivedWithAnyArgs(1)
  583. .SendEmailAndWriteToDbAsync("mail", "reset", "url", true);
  584. }
  585. [Fact]
  586. public async Task GetForgotPasswordUrlAsync_ShouldCallEmailer_IfUserIsFound()
  587. {
  588. _mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]);
  589. var databaseContext = await Helpers<User>.GetDatabaseContext(_users);
  590. var frontEndSettings = Options.Create(new FrontEndSettings
  591. {
  592. BaseUrl = "some url"
  593. });
  594. var authSettings = Options.Create(new AuthorizationSettings { });
  595. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  596. var result = await service.GetForgotPasswordUrlAsync(_users[1].Email);
  597. result.Should().BeOfType(typeof(ServiceResponseDTO<object>));
  598. }
  599. [Fact]
  600. public async Task UpdateRefreshToken_ShouldUpdate()
  601. {
  602. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  603. var authSettings = Options.Create(new AuthorizationSettings { });
  604. var frontEndSettings = Options.Create(new FrontEndSettings
  605. {
  606. BaseUrl = "some url"
  607. });
  608. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  609. var first = await databaseContext.RefreshTokens.FindAsync(1);
  610. await service.UpdateRefreshToken(first);
  611. databaseContext.Entry(first).Should().NotBeNull();
  612. }
  613. [Fact]
  614. public async Task DeleteRefreshToken_ShouldReturnError_IfTokenDoesNotExist()
  615. {
  616. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  617. var authSettings = Options.Create(new AuthorizationSettings { });
  618. var frontEndSettings = Options.Create(new FrontEndSettings
  619. {
  620. BaseUrl = "some url"
  621. });
  622. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  623. var result = await service.DeleteRefreshToken(1000); // not existing token
  624. result.Should().BeEquivalentTo(new ServiceResponseDTO<string>
  625. {
  626. IsError = true,
  627. ErrorMessage = "There is no refresh token for user"
  628. });
  629. }
  630. [Fact]
  631. public async Task DeleteRefreshToken_ShouldSucceed_IfTokenExists()
  632. {
  633. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  634. var authSettings = Options.Create(new AuthorizationSettings { });
  635. var frontEndSettings = Options.Create(new FrontEndSettings
  636. {
  637. BaseUrl = "some url"
  638. });
  639. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  640. var result = await service.DeleteRefreshToken(1); // not existing token
  641. result.Should().BeEquivalentTo(new ServiceResponseDTO<string>
  642. {
  643. Data = null
  644. });
  645. }
  646. [Fact]
  647. public async Task GetRefreshTokenByUserId_ShouldReturnTokenOrNull()
  648. {
  649. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  650. var authSettings = Options.Create(new AuthorizationSettings { });
  651. var frontEndSettings = Options.Create(new FrontEndSettings
  652. {
  653. BaseUrl = "some url"
  654. });
  655. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  656. var result = await service.GetRefreshTokenByUserId(1);
  657. result.Should().BeEquivalentTo(_tokens[0]);
  658. }
  659. [Fact]
  660. public async Task RefreshTokenAsync_ShouldReturnError_IfValidatedTokenIsNull()
  661. {
  662. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  663. var authSettings = Options.Create(new AuthorizationSettings
  664. {
  665. Secret = "ThIs I5 0uR S3cReT n0W!"
  666. });
  667. var frontEndSettings = Options.Create(new FrontEndSettings
  668. {
  669. BaseUrl = "some url"
  670. });
  671. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  672. var result = await service.RefreshTokenAsync(new RefreshTokenRequestDto
  673. {
  674. RefreshToken = "",
  675. Token = ""
  676. });
  677. result.Should().BeEquivalentTo(new RefreshTokenResultDto
  678. {
  679. Error = "Invalid token"
  680. });
  681. }
  682. [Fact]
  683. public async Task Expirt_RefreshTokenAsync_ShouldReturnError_IfValidatedTokenIsNull()
  684. {
  685. _mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[4]);
  686. _mockUserManager.CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
  687. var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens);
  688. var authSettings = Options.Create(new AuthorizationSettings
  689. {
  690. Secret = "ThIs I5 0uR S3cReT n0W!"
  691. });
  692. var frontEndSettings = Options.Create(new FrontEndSettings
  693. {
  694. BaseUrl = "some url"
  695. });
  696. var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper);
  697. var result1 = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto
  698. {
  699. Username = _users[4].UserName,
  700. Password = "Nekasifra123!"
  701. });
  702. var result = await service.RefreshTokenAsync(new RefreshTokenRequestDto
  703. {
  704. RefreshToken = result1.Data.RefreshToken,
  705. Token = result1.Data.Token
  706. });
  707. result.Should().BeEquivalentTo(new RefreshTokenResultDto
  708. {
  709. Error = "This refresh token has expired"
  710. });
  711. }
  712. }
  713. }