Advertisement
Guest User

Untitled

a guest
Sep 24th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.55 KB | None | 0 0
  1. using Feedbk.Core;
  2. using Feedbk.Core.Data;
  3. using Feedbk.Core.Diagnostics;
  4. using Feedbk.Core.Entities;
  5. using Feedbk.Core.Security;
  6. using Feedbk.Services.Email;
  7. using System;
  8. using System.Web.Mvc;
  9. using System.Linq;
  10.  
  11. namespace Feedbk.Services.Authentication
  12. {
  13. public class AuthenticationService : IAuthenticationService
  14. {
  15. #region Fields
  16.  
  17. private IDiagnosticsSource Trace;
  18.  
  19. private readonly IAccountRepository _accountRepository;
  20. private readonly IEmailService _emailService;
  21.  
  22. #endregion
  23.  
  24. #region Ctor
  25.  
  26. /// <summary>
  27. /// Authentication Service constructor.
  28. /// </summary>
  29. /// <param name="logger">IDiagnosticsSource</param>
  30. /// <param name="accountRepo">Account Repository</param>
  31. public AuthenticationService(IDiagnosticsSource diagnosticsSource, IAccountRepository accountRepo, IEmailService emailService)
  32. {
  33. Trace = diagnosticsSource;
  34. Trace.Verbose("AuthenticationService init");
  35.  
  36. this._accountRepository = accountRepo;
  37. this._emailService = emailService;
  38. }
  39.  
  40. #endregion
  41.  
  42. #region Methods
  43.  
  44. /// <summary>
  45. /// Checks if user exists.
  46. /// </summary>
  47. /// <param name="email">Email address</param>
  48. /// <returns>True if exists. False if doesn't exist.</returns>
  49. public bool UserExists(string email)
  50. {
  51. Trace.Verbose("UserExists(email: {0})", email);
  52.  
  53. if (String.IsNullOrWhiteSpace(email))
  54. return false;
  55.  
  56. if (GetUserByEmail(email) == null)
  57. {
  58. return false;
  59. }
  60. else
  61. {
  62. return true;
  63. }
  64. }
  65.  
  66. /// <summary>
  67. /// Creates new Account.
  68. /// </summary>
  69. /// <param name="accountType">Account type.</param>
  70. /// <param name="createdBy">Email address of the user creating the account.</param>
  71. /// <returns></returns>
  72. public Account CreateAccount(AccountType accountType, string createdBy)
  73. {
  74. Trace.Verbose("CreateAccount(account type: {0}, created by: {1})", accountType.ToString(), createdBy);
  75.  
  76. Ensure.Argument.NotNull(accountType);
  77. Ensure.Argument.NotNullOrEmpty(createdBy);
  78.  
  79. var account = new Account()
  80. {
  81. Type = accountType,
  82. DateCreated = DateTime.Now,
  83. CreatedBy = createdBy,
  84. };
  85.  
  86. _accountRepository.CreateAccount(account);
  87.  
  88. Trace.Information("CreateAccount() => Success. Account id: {0}", account.Id);
  89.  
  90. return account;
  91. }
  92.  
  93. /// <summary>
  94. /// Creates new User object.
  95. /// </summary>
  96. /// <param name="email">Email address.</param>
  97. /// <param name="password">Password.</param>
  98. /// <returns>User</returns>
  99. public User CreateUser(string email, string password, int accountId, int roleId)
  100. {
  101. Trace.Information("CreateUser(email: {0}, account id: {1}, role: {2})", email, accountId, roleId);
  102.  
  103. var user = new User()
  104. {
  105. AccountId = accountId,
  106. DateCreated = DateTime.Now,
  107. Email = email.ToLower(),
  108. RoleId = roleId,
  109. IsVerified = false,
  110. FailedLoginCount = 0
  111. };
  112.  
  113. // Hash user's password
  114. UpdatePasswordAndSalt(user, password);
  115.  
  116. // Email verification token
  117. SetEmailVerificationKey(user, user.Email);
  118.  
  119. // Save
  120. _accountRepository.CreateUser(user);
  121.  
  122. Trace.Information(String.Format("CreateUser() => Success. User id: {0}", user.Id));
  123.  
  124. return user;
  125. }
  126.  
  127. /// <summary>
  128. /// Authenticates user with credentials provided.
  129. /// </summary>
  130. /// <param name="email">Email address.</param>
  131. /// <param name="password">Password.</param>
  132. /// <returns>User</returns>
  133. public User Authenticate(string email, string password)
  134. {
  135. Trace.Verbose("Authenticate(email: {0})", email);
  136.  
  137. var user = GetUserByEmail(email);
  138.  
  139. if (user == null)
  140. return null;
  141.  
  142. if (ValidatePassword(user, password))
  143. {
  144. user.FailedLoginCount = 0;
  145. user.DateLastLoggedIn = DateTime.Now;
  146. _accountRepository.UpdateUser(user);
  147.  
  148. Trace.Information("User authentication successful. User: {0}", user.Email);
  149.  
  150. return user;
  151. }
  152. else
  153. {
  154. user.FailedLoginCount = user.FailedLoginCount + 1;
  155. user.LastFailedLogin = DateTime.Now;
  156. _accountRepository.UpdateUser(user);
  157. }
  158. return null;
  159. }
  160.  
  161. /// <summary>
  162. /// Checks the email verification token and activates the user if correct.
  163. /// </summary>
  164. /// <param name="user">User</param>
  165. /// <param name="vCode">Verification token.</param>
  166. /// <returns>True if activated successfully. False otherwise.</returns>
  167. public bool ActivateUser(string email, string vCode)
  168. {
  169. Trace.Verbose("ActivateUser(email: {0})", email);
  170.  
  171. var user = GetUserByEmail(email);
  172.  
  173. if (VerifyEmailKey(user, vCode, false))
  174. {
  175. user.IsVerified = true;
  176.  
  177. RemoveEmailVerificationKey(user);
  178. _accountRepository.UpdateUser(user);
  179.  
  180. Trace.Information("User account has been activated. User: {0}", user.Email);
  181.  
  182. return true;
  183. }
  184.  
  185. Trace.Warning("User account activation failed. Verification key is incorrect.");
  186.  
  187. return false;
  188. }
  189.  
  190. /// <summary>
  191. /// Get account by id.
  192. /// </summary>
  193. /// <param name="id">Id</param>
  194. /// <returns>Account</returns>
  195. public Account GetAccountById(int id)
  196. {
  197. var account = _accountRepository.Accounts.Where(a => a.Id == id).FirstOrDefault();
  198.  
  199. if (account != null)
  200. {
  201. Trace.Verbose("GetAccountById(id: {0}) => Account found.", id);
  202.  
  203. return account;
  204. }
  205. else
  206. {
  207. Trace.Verbose("GetAccountById(id: {0}) => Account not found.", id);
  208.  
  209. return null;
  210. }
  211. }
  212.  
  213. /// <summary>
  214. /// Get user.
  215. /// </summary>
  216. /// <param name="email">Email address</param>
  217. /// <returns>User</returns>
  218. public User GetUserByEmail(string email)
  219. {
  220. email = email.ToLower();
  221.  
  222. var user = _accountRepository.Users.Where(u => u.Email == email.ToLower()).FirstOrDefault();
  223.  
  224. if (user != null)
  225. {
  226. Trace.Verbose("GetUserByEmail(email: {0}) => User found: {1}", email, user.Id);
  227.  
  228. return user;
  229. }
  230. else
  231. {
  232. Trace.Verbose("GetUserByEmail(email: {0}) => User not found.", email);
  233.  
  234. return null;
  235. }
  236. }
  237.  
  238. /// <summary>
  239. /// Checks if password provided matches the user password.
  240. /// </summary>
  241. /// <param name="user">User</param>
  242. /// <param name="password">Password</param>
  243. /// <returns>True if passwords match. False otherwise.</returns>
  244. private bool ValidatePassword(User user, string password)
  245. {
  246. Trace.Verbose("ValidatePassword(user: {0})", user.Email);
  247.  
  248. var passwordSalt = user.PasswordSalt;
  249. var hashedPassword = PasswordHelper.GenerateSaltedHash(password, passwordSalt);
  250.  
  251. return (user.Password == hashedPassword);
  252. }
  253.  
  254. /// <summary>
  255. /// Generates new salt and hashes the password with it. Updates both properties on user object.
  256. /// </summary>
  257. /// <param name="user">User</param>
  258. /// <param name="password">Password</param>
  259. private void UpdatePasswordAndSalt(User user, string password)
  260. {
  261. Trace.Verbose("UpdatePasswordAndSalt(user: {0})", user.Email);
  262.  
  263. var passwordSalt = PasswordHelper.GenerateSalt();
  264. var hashedPassword = PasswordHelper.GenerateSaltedHash(password, passwordSalt);
  265.  
  266. user.PasswordSalt = passwordSalt;
  267. user.Password = hashedPassword;
  268. }
  269.  
  270. /// <summary>
  271. /// Creates new email request data.
  272. /// </summary>
  273. /// <param name="user">User</param>
  274. /// <param name="email">Email address</param>
  275. public void SetEmailVerificationKey(User user, string email = null)
  276. {
  277. Trace.Verbose("SetEmailVerificationKey(user: {0}, email: {1})", user.Email, email);
  278.  
  279. user.NewEmail = email;
  280. user.EmailVerificationKey = HashingHelper.GenerateHash(Constants.VerificationHashSize);
  281. user.EmailVerificationKeySent = DateTime.Now;
  282.  
  283. _accountRepository.UpdateUser(user);
  284. }
  285.  
  286. /// <summary>
  287. /// Removes all data related to new email request.
  288. /// </summary>
  289. /// <param name="user">User to remove the data from.</param>
  290. public void RemoveEmailVerificationKey(User user)
  291. {
  292. Trace.Verbose("RemoveEmailVerificationKey(user: {0})", user.Email);
  293.  
  294. user.NewEmail = null;
  295. user.EmailVerificationKey = null;
  296. user.EmailVerificationKeySent = null;
  297. }
  298.  
  299. /// <summary>
  300. /// Creates new password reset key for the user.
  301. /// </summary>
  302. /// <param name="user">User</param>
  303. public void SetPasswordResetKey(User user)
  304. {
  305. Trace.Verbose("SetPasswordResetKey(user: {0})", user.Email);
  306.  
  307. user.PasswordResetKey = HashingHelper.GenerateHash(Constants.VerificationHashSize);
  308. user.PasswordResetKeySent = DateTime.Now;
  309.  
  310. _accountRepository.UpdateUser(user);
  311. }
  312.  
  313. /// <summary>
  314. /// Removes all data related to password reset.
  315. /// </summary>
  316. /// <param name="user">User to remove the data from.</param>
  317. public void RemovePasswordResetKey(User user)
  318. {
  319. Trace.Verbose("RemovePasswordResetKey(user: {0})", user.Email);
  320.  
  321. user.PasswordResetKey = null;
  322. user.PasswordResetKeySent = null;
  323. }
  324.  
  325. /// <summary>
  326. /// Completes email change procedure.
  327. /// </summary>
  328. /// <param name="email">Email address.</param>
  329. /// <param name="vCode">Verification code.</param>
  330. public void UpdateEmail(string email, string vCode)
  331. {
  332. Ensure.Argument.NotNullOrEmpty(email);
  333. Ensure.Argument.NotNullOrEmpty(vCode);
  334.  
  335. var user = GetUserByEmail(email);
  336.  
  337. if (user == null)
  338. return;
  339.  
  340. if (VerifyEmailKey(user, vCode))
  341. {
  342. user.Email = user.NewEmail;
  343. RemoveEmailVerificationKey(user);
  344. }
  345.  
  346. _accountRepository.UpdateUser(user);
  347.  
  348. Trace.Information("User email address changed from: {0} to: {1}.", email, user.Email);
  349. }
  350.  
  351. /// <summary>
  352. /// Updates user's password.
  353. /// </summary>
  354. /// <param name="email">Email address.</param>
  355. /// <param name="password">New password.</param>
  356. public void UpdatePassword(string email, string password)
  357. {
  358. Trace.Verbose("UpdatePassword(user: {0})", email);
  359.  
  360. Ensure.Argument.NotNullOrEmpty(email);
  361. Ensure.Argument.NotNullOrEmpty(password);
  362.  
  363. var user = GetUserByEmail(email);
  364.  
  365. if (user == null)
  366. return;
  367.  
  368. UpdatePasswordAndSalt(user, password);
  369. RemovePasswordResetKey(user);
  370.  
  371. _accountRepository.UpdateUser(user);
  372.  
  373. Trace.Information("User password changed. User: {0}", email);
  374. }
  375.  
  376. /// <summary>
  377. /// Resets user's password with verification code.
  378. /// </summary>
  379. /// <param name="email">Email address.</param>
  380. /// <param name="password">Password.</param>
  381. /// <param name="vCode">Verification code.</param>
  382. public void ResetPassword(string email, string password, string vCode)
  383. {
  384. Trace.Verbose("ResetPassword(email: {0})", email);
  385.  
  386. Ensure.Argument.NotNullOrEmpty(email);
  387. Ensure.Argument.NotNullOrEmpty(vCode);
  388. Ensure.Argument.NotNullOrEmpty(password);
  389.  
  390. var user = GetUserByEmail(email);
  391.  
  392. if (user == null || !user.IsVerified)
  393. return;
  394.  
  395. if (VerifyPasswordResetKey(user, vCode))
  396. {
  397. UpdatePasswordAndSalt(user, password);
  398. RemovePasswordResetKey(user);
  399.  
  400. _accountRepository.UpdateUser(user);
  401.  
  402. Trace.Information("User password reset has been successful. User: {0}", email);
  403. }
  404. }
  405.  
  406. /// <summary>
  407. /// Checks if the password verification code is valid and not expired (optional).
  408. /// </summary>
  409. /// <param name="user">User.</param>
  410. /// <param name="vCode">Verification code.</param>
  411. /// <param name="checkDate">Check date.</param>
  412. /// <returns>True if valid. False otherwise.</returns>
  413. public bool VerifyPasswordResetKey(User user, string vCode, bool checkDate = true)
  414. {
  415. Trace.Verbose("VerifyPasswordKey(user: {0})", user.Email);
  416.  
  417. if (checkDate)
  418. {
  419. return (user.PasswordResetKey == vCode && user.PasswordResetKeySent > DateTime.Now.AddHours(Constants.HashExpiryTimeInHours * -1));
  420. }
  421. else
  422. {
  423. return (user.PasswordResetKey == vCode);
  424. }
  425. }
  426.  
  427. /// <summary>
  428. /// Checks if the email verification code is valid and not expired (optional).
  429. /// </summary>
  430. /// <param name="user">User.</param>
  431. /// <param name="vCode">Verification code.</param>
  432. /// <param name="checkDate">Check date.</param>
  433. /// <returns>True if valid. False otherwise.</returns>
  434. public bool VerifyEmailKey(User user, string vCode, bool checkDate = true)
  435. {
  436. Trace.Verbose("VerifyEmailKey(user: {0})", user.Email);
  437.  
  438. if (checkDate)
  439. {
  440. return (user.EmailVerificationKey == vCode && user.EmailVerificationKeySent > DateTime.Now.AddHours(Constants.HashExpiryTimeInHours * -1));
  441. }
  442. else
  443. {
  444. return (user.EmailVerificationKey == vCode);
  445. }
  446. }
  447.  
  448. #endregion
  449. }
  450. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement