public async Task <IActionResult> Login(BasicLoginViewModel model) { if (HttpContext.User.Identity.IsAuthenticated == false) { var api = RestService.For <IHealthyGamerPortalAccountApi>(new HttpClient(new Helpers.AuthenticatedHttpClientHandler()) { BaseAddress = new Uri(BaseUrl) }); var response = await api.IsBasicAccount(new EncryptedMessage() { Length = model.Email.Length, Text = Rfc7905.EncryptText(model.Email) }); if (response.Result == AccountType.Discord) { return(Oauth(Url.Action("Oauth", "Account"))); } else { // Response.StatusCode = 403; //prevents browsers from trying to remember a password when the login failed. return(RedirectToAction("BasicLogin", "Account", model)); } } return(RedirectToAction("Index", "Home")); }
/// <summary> /// Retrieves <see cref="ApplicationUser"/> from DB and perform password check for basic login. /// </summary> /// <returns><see cref="BasicAuthenticationResult"/></returns> public async Task <BasicAuthenticationResult> Authenticate(EncryptedBasicLoginModel model) { var user = await _healthyGamerPortalDbContext.ApplicationUsers.FirstOrDefaultAsync( X => X.Email == Rfc7905.DecryptText(model.Email.Length, model.Email.Text)); // check if user exists if (user == null) { return(null); } // check if password is correct if (!VerifyPasswordHash(Convert.FromBase64String(user.Salt), Encoding.UTF8.GetBytes(Rfc7905.DecryptText(model.Password.Length, model.Password.Text)), Convert.FromBase64String(user.Password))) { return(null); } //Retrieve roles from DB BasicAuthenticationResult result = new BasicAuthenticationResult { Name = user.Email, Roles = new string[] { "Sad", "NotSad" } }; // authentication successful return(result); }
/// <summary> /// Scout every request for basic login path and initiate authentication. /// </summary> public async Task InvokeAsync(HttpContext httpContext) { HttpRequest request = httpContext.Request; HttpResponse response = httpContext.Response; // If the request path doesn't match, skip if (request.Path.Equals(_options.Path, StringComparison.Ordinal)) { // Slow connection can cause collision between concurring tasks, delay until finished while (!_antiforgery.ValidateRequestAsync(httpContext).IsCompleted) { //wait a bit please :D } // Request must be POST with matching antiforgery token if (!request.Method.Equals("POST") || !_antiforgery.ValidateRequestAsync(httpContext).IsCompletedSuccessfully) { response.StatusCode = 400; } if (!httpContext.User.Identity.IsAuthenticated) { EncryptedBasicLoginModel model = new EncryptedBasicLoginModel { Email = new EncryptedMessage() { Text = Rfc7905.EncryptText(request.Form["Email"]), Length = Encoding.UTF8.GetBytes(request.Form["Email"]).Length }, Password = new EncryptedMessage() { Text = Rfc7905.EncryptText(request.Form["Password"]), Length = Encoding.UTF8.GetBytes(request.Form["Password"]).Length } }; _httpContext = httpContext; if (await Authenticate(model)) { response.Redirect("/"); } else { response.Redirect("/Account/Oauth"); } return; } } await _next(httpContext); }
/// <summary> /// Retrieves account type from ApplicationUser based on matching username. /// </summary> /// <returns><see cref="AccountType"/></returns> public async Task <AccountType> IsBasicAccount(EncryptedMessage encryptedMessage) { // check password == Azure var result = await _healthyGamerPortalDbContext.ApplicationUsers.FirstOrDefaultAsync(I => I.Email == Rfc7905.DecryptText(encryptedMessage.Length, encryptedMessage.Text) && I.Password == "Discord"); if (result != null) { return(AccountType.Discord); } return(AccountType.Basic); }