After a successful authentication i get redirected to a access denied page.
WebSecurityContext
#Configuration
#EnableWebSecurity
public class WebSecurityContext extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN", "ROLE_CONTRIBUTOR","ROLE_ROOT")
.and()
.formLogin().loginPage("/admin/login")
.failureUrl("/admin/login/error")
.successHandler(new SuccessfulAuthHandler())
.loginProcessingUrl("/admin/login")
.defaultSuccessUrl("/admin")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/admin/login/logout");
}
#Bean(name = "passwordencoder")
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(10);
}
SuccessHandler
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
final HttpSession currentSession = request.getSession();
final User user = userService.findByUsername(authentication.getName());
final List<Object> jObj = new ArrayList<>();
final List<Institution> institutions = institutionService.findAllByUserID(user.getId());
for(Institution i : institutions){
Map<String, Object> m = new HashMap<>();
m.put("name", i.getName());
m.put("id", i.getId());
jObj.add(m);
}
currentSession.setAttribute("userInInstitution", jObj);
currentSession.setAttribute("currentUser", user);
String servlet = "";
if(user.getRole() == ConstantsCommon.USER_ROLE_ADMIN){
servlet = DashBoardController.URL;
currentSession.setAttribute("dashboardServlet", servlet);
}else{
servlet = DashBoardController.URL;
currentSession.setAttribute("dashboardServlet", servlet);
}
if(jObj.size() > 1){
currentSession.setAttribute("institution",institutions.get(0));
}else{
currentSession.setAttribute("institution",institutions.get(0));
}
RedirectStrategy r = new DefaultRedirectStrategy();
r.sendRedirect(request,response, servlet);
}
Login HTML
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="pr-wrap">
<div class="pass-reset">
<label>
Enter the email you signed up with</label>
<input type="email" placeholder="Email" />
<input type="submit" value="Submit" class="pass-reset-submit btn btn-success btn-sm" />
</div>
</div>
<div class="wrap">
<p class="form-title">Sign In</p>
<form class="login" name="loginForm" method='POST'>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<input type="text" name="username" placeholder="Username"/>
<input type="password" name="password" placeholder="Password"/>
<input type="submit" name="submit" value="Sign In" class="btn btn-success btn-sm" />
<div class="remember-forgot">
<div th:if="${error}" class="alert alert-danger notificationMsg" role="alert">
<span th:text="${error}"></span>
</div>
<div th:if="${msg}" class="alert alert-success notificationMsg" role="alert">
<span th:text="${msg}"></span>
</div>
<!--<div class=" forgot-pass-content">-->
<!--Forgot Password-->
<!--</div>-->
</div>
</form>
</div>
</div>
</div>
What am I doing wrong here ?????? The user im logging in with has the role "ROLE_ADMIN". One thing i have also noticed is that my success handler doesn't even get triggered which suggest that mu authentication isn't successful but that can't be right because the password and username are 100% correct.
Related
I have a C# Razor Pages project.
I created a Login view in the following structure:
- Pages
- Account
- Login.cshtml
This is the code for my Login view
#page "{handler?}"
#model HAL_WEB.Pages.LoginModel
#{
Layout = "_LayoutLogin";
}
<section class="section register min-vh-100 d-flex flex-column align-items-center justify-content-center py-4">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-4 col-md-6 d-flex flex-column align-items-center justify-content-center">
<div class="d-flex justify-content-center py-4">
<a href="index.html" class="logo d-flex align-items-center w-auto">
<img src="assets/img/teamtruetech_logo.png" alt="">
<span class="d-none d-lg-block">HAL Admin</span>
</a>
</div><!-- End Logo -->
<div class="card mb-3">
<div class="card-body">
<div class="pt-4 pb-2">
<h5 class="card-title text-center pb-0 fs-4">Login to Your Account</h5>
<p class="text-center small">Enter your username & password to login</p>
</div>
<form id="login-form" class="row g-3 needs-validation" novalidate>
<div class="col-12">
<label for="yourUsername" class="form-label">Username</label>
<div class="input-group has-validation">
<span class="input-group-text" id="inputGroupPrepend"></span>
<input type="text" name="username" class="form-control" id="yourUsername" required>
<div class="invalid-feedback">Please enter your username.</div>
</div>
</div>
<div class="col-12">
<label for="yourPassword" class="form-label">Password</label>
<input type="password" name="password" class="form-control" id="yourPassword" required>
<div class="invalid-feedback">Please enter your password!</div>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" value="true" id="rememberMe">
<label class="form-check-label" for="rememberMe">Remember me</label>
</div>
</div>
<div class="col-12">
<button class="btn btn-primary w-100" type="submit">Login</button>
</div>
#* <div class="col-12">
<p class="small mb-0">Don't have account? Create an account</p>
</div>*#
</form>
</div>
</div>
</div>
</div>
</div>
</section>
#section Scripts {
<script src="~/assets/js/loginpage.js"></script>
}
And this is the code behind:
using HAL_WEB.Data;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;
namespace HAL_WEB.Pages
{
public class LoginModel : PageModel
{
private readonly ApplicationDBContext _dbContext;
public LoginModel([FromServices] ApplicationDBContext dbContext)
{
_dbContext = dbContext;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPostLoginAsync(string username, string password)
{
// Check if the provided credentials are valid
if (IsValidCredentials(username, password))
{
// If the credentials are valid, log the user in
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, username) }, CookieAuthenticationDefaults.AuthenticationScheme)),
new AuthenticationProperties
{
IsPersistent = true, // Set this to true if you want the user to stay logged in after closing the browser
ExpiresUtc = DateTime.UtcNow.AddDays(7) // Set the expiration time for the cookie
});
// Redirect the user to the home page
return RedirectToPage("/Home");
}
else
{
// If the credentials are invalid, show an error message
ModelState.AddModelError(string.Empty, "Invalid username or password.");
return Page();
}
}
private bool IsValidCredentials(string username, string password)
{
// Replace this with your own validation logic
return username == "admin" && password == "password";
}
public IActionResult OnPostLoginTestAsync()
{
return new JsonResult(true);
}
}
In my Javascript file I tried to call the method OnPostLoginTestAsync or OnPostLoginAsync without success.
I'm getting a "Bad Request 400" error:
This is my Javascript Axios code for calling the method:
// Use Axios to send a POST request to the server with the form data
axios.post('/Account/Login?handler=login', {
username,
password,
})
.then((response) => {
// If the request is successful, redirect the page
window.location.href = '/home';
})
.catch((error) => {
// If there is an error, log it to the console
console.error(error);
});
Any clue what am I doing wrong? I'm going to /Account/Login?handler=login because the call is a Post and what I think is that the method OnPostLoginAsync should be executed.
UPDATE
I found something interesting, I created the following Get method:
public IActionResult OnGetTestAsync()
{
return new JsonResult(true);
}
And in my Javascript, I changed the Axios url to be:
axios.get('/Account/Login?handler=test')
.then(function (response) {
})
.catch(function (error) {
// Handle the error response
});
And I could get the method executed! But when I change the method name back to:
OnPostTestAsync
and my Axios to:
axios.post('/Account/Login?handler=test')
.then(function (response) {
})
.catch(function (error) {
// Handle the error response
});
It never gets executed and I get 400 Bad Request. Any clue?
I have an ASP.Net Core Razor web application without controllers.
I have a form in my cshtml page and on Post/Submit I am calling an external API, which returns a success message or an error message. I want to show this message in my page as a popup.
I tried multiple things but failed. Here is my code.
In my "Index.cshtml"
<div class="col-lg-4 col-md-6 footer-newsletter">
<h4>Our Newsletter</h4>
<p>Subscribe to our news letter</p>
<form action="" method="post">
<input type="email" asp-for="SubscriptionEmail" placeholder="Email Address"/>
<input type="submit" value="Subscribe" asp-page-handler="NewsSubscription" />
</form>
</div>
In my Index.cshtml.cs
[BindProperty]
public string SubscriptionEmail { get; set; }
public string ActionResultMessageText { get; set; }
public string ActionResultErrorMessageText { get; set; }
public async void OnPostNewsSubscription()
{
try
{
this.ActionResultMessageText = string.Empty;
this.ActionResultErrorMessageText = string.Empty;
using (HttpClient _httpClient = _httpClientFactory.CreateClient("PortalBasicHttpClient"))
{
if (!string.IsNullOrEmpty(SubscriptionEmail))
{
HttpRequestMessage _Request = new(HttpMethod.Post, _httpClient.BaseAddress + "Api/SaveSubscriptionEmail/" + SubscriptionEmail);
HttpResponseMessage _Response = await _httpClient.SendAsync(_Request);
if (_Response.IsSuccessStatusCode)
{
this.ActionResultMessageText = _Response.Content.ReadAsStringAsync().Result.ToString();
}
else
{
this.ActionResultMessageText = _Response.Content.ReadAsStringAsync().Result.ToString();
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
this.ActionResultMessageText = string.Empty;
this.ActionResultErrorMessageText = ex.Message;
}
}
My code behind is working fine, but not sure how to grace fully show this in the razor page using bootstrap.
looking forward for some guidance.
I tried using modal popup, but the text was not updated in the label I used in the modal popup and the pop-up disappeared with in few seconds, even though there was a "ok" button.
I also tried to use the java script method as mentioned in the following link https://www.aspsnippets.com/Articles/ASPNet-Core-Razor-Pages-Display-JavaScript-Alert-Message-Box.aspx
I will be great help if someone can help with a sample code.
Please debug your code and be sure the two properties actually contain the value you want.
The following working demo I just hard coded the two properties value for easy testing in the backend:
Index.cshtml
#page
#model IndexModel
<div class="col-lg-4 col-md-6 footer-newsletter">
<h4>Our Newsletter</h4>
<p>Subscribe to our news letter</p>
<form action="" method="post">
<input type="email" asp-for="SubscriptionEmail" placeholder="Email Address" />
<input type="submit" value="Subscribe" asp-page-handler="NewsSubscription" />
</form>
</div>
#if (Model.ActionResultMessageText == string.Empty)
{
<script type="text/javascript">
window.onload = function () {
alert("#Model.ActionResultErrorMessageText");
};
</script>
}
Index.cshtml.cs
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
[BindProperty]
public string SubscriptionEmail { get; set; }
public string ActionResultMessageText { get; set; }
public string ActionResultErrorMessageText { get; set; }
public void OnGet()
{
}
public async void OnPostNewsSubscription()
{
this.ActionResultMessageText = string.Empty;
this.ActionResultErrorMessageText = "error";
}
}
Result:
If you want to use Bootstrap modal popup, change your page like below:
#page
#model IndexModel
<div class="col-lg-4 col-md-6 footer-newsletter">
<h4>Our Newsletter</h4>
<p>Subscribe to our news letter</p>
<form action="" method="post">
<input type="email" asp-for="SubscriptionEmail" placeholder="Email Address" />
<input type="submit" value="Subscribe" asp-page-handler="NewsSubscription" />
</form>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#Model.ActionResultErrorMessageText
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
#if (Model.ActionResultMessageText == string.Empty)
{
<script type="text/javascript">
window.onload = function () {
$("#exampleModal").modal("show")
};
</script>
}
Result:
I want to show an error message when login failed.
This is my html markup:
<form class="modal-content animate" action="/Login/SignInTeacher" method="post">
#Html.AntiForgeryToken()
<div class="imgcontainer">
<span onclick="document.getElementById('id02').style.display='none'" class="close" title="Close Modal">×</span>
<img src="~/images/Login4.png" alt="Avatar" class="img-fluid" style="height: 300px;">
</div>
<div class="container">
<input type="text" class="form-control" name="Email" placeholder="Email Adresiniz" aria-label="Username" aria-describedby="basic-addon1" style="font-size: medium;">
<br>
<input type="password" class="form-control" name="Parola" placeholder="Şifreniz" aria-label="Username" aria-describedby="basic-addon1" style="font-size: medium;">
<br>
<button type="submit" class="btn btn-block btn-outline-success btn-lg">Login</button>
<br>
<label style="font-size: medium; margin-left: 0%;">
<input type="checkbox" checked="checked" name="remember"> Remember me
</label>
</div>
<div class="container" style="background-color:#f1f1f1">
<button type="button" onclick="document.getElementById('id02').style.display='none'" class="btn btn-lg btn-danger">Cancel</button>
<span class="psw">Forgot password?</span>
</div>
</form>
This is my controller code
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SignInTeacher(Teacher t)
{
SHA1 sha = new SHA1CryptoServiceProvider();
string willbeEncrypted = s.Parola;
string encrypted = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(willbeEncrypted)));
var info = c.Teachers.FirstOrDefault(x => x.Email == s.Email && x.Parola == encrypted);
if (info != null)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name,s.Email)
};
var userIdentity = new ClaimsIdentity(claims, "Login");
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(userIdentity);
await HttpContext.SignInAsync(claimsPrincipal);
var value = from deger in c.Teachers
where deger.Email == s.Email
select deger.Email;
var nameuser = value;
return RedirectToAction("Main", "Home", new { user = nameuser });
}
return RedirectToAction("Index", "Home");
}
When user logs in successfully, the main page opens; when login fails, the main page does not open return same page (refresh) but I can't show the error message instead of page refresh like this "Username or password is wrong".
I tried it with viewbag but that did not work because this command return RedirectToAction("Index", "Home"); prevent the viewbag message.
when login failed main page does not open return same page(refresh) but I cant achieve show the error message instead of page refresh like this "Username or password is wronng".
To achieve your requirement, you can try to pass error message through TempData, like below.
TempData["ErrorMes"] = "Username or password is wronng";
return RedirectToAction("Index", "Home");
Display error message in Index page
<span class="text-danger">#TempData["ErrorMes"]</span>
I recommend to use ModelState.AddModelError like below, it'll return to the same login view with model error and model state will be invalid
Example :
if(isLoginSuccess)
{
return RedirectToAction("Main", "Home");
}else
{
ModelState.AddModelError("InvalidLogin", "Invalid Login Attempt");
return View(loginViewModel);
}
If I submit the page the first save goes without a problem
Than I assigned all values to the other entity which I want to write to create there a new record.
Why do I get an System Null Reference. I have in all fields the values which I want?
[
=== here is my c# Code ===========
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WorkCollaboration.Data;
using WorkCollaboration.Models;
namespace WorkCollaboration.Pages.TimeReports
{
public class CreateModel : PageModel
{
private readonly WorkCollaboration.Data.WorkCollaborationContext _context;
public CreateModel(WorkCollaboration.Data.WorkCollaborationContext context)
{
_context = context;
}
public IActionResult OnGet()
{
CusContactDropDownDisp = _context.CusContactDropDown.ToList(); // Added for DropDown
SupContactDropDownDisp = _context.SupContactDropDown.ToList(); // Added for DropDown
return Page();
}
[BindProperty]
public TimeReport TimeReport { get; set; }
public IEnumerable<Models.CusContactDropDown> CusContactDropDownDisp { get; set; }
public IEnumerable<Models.SupContactDropDown> SupContactDropDownDisp { get; set; }
public Models.PointsforSupContact PointsforSupContact { get; set; }
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
TimeReport.TimeReportSupContactPointValue = (TimeReport.TimeReportHours * 10);
_context.TimeReport.Add(TimeReport);
await _context.SaveChangesAsync();
//============================================
// Adding new Point Record to Supplier Contact
//============================================
PointsforSupContact.PointsId = TimeReport.TimeReportId;
PointsforSupContact.PointsSupContactId = TimeReport.TimeReportSupplierTalentContactId;
PointsforSupContact.PointsInternalUserId = 1; // User 1 Christof Oberholzer must be entered in Contacts and User
PointsforSupContact.PointsDate = TimeReport.TimeReportDate;
PointsforSupContact.PointsTotal = TimeReport.TimeReportSupContactPointValue;
PointsforSupContact.PointsText = TimeReport.TimeReportText;
PointsforSupContact.PointsTitle = "TimeReporting Points";
_context.PointsforSupContact.Add(PointsforSupContact);
await _context.SaveChangesAsync();
return RedirectToPage("/TimeReportOverview/Index");
}
}
}
==== My Page ======
#page
#using Microsoft.AspNetCore.Localization
#using Microsoft.AspNetCore.Mvc.Localization
#model WorkCollaboration.Pages.TimeReports.CreateModel
#{
ViewData["Title"] = "Create";
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
}
#inject IViewLocalizer Localizer
<h1>Create</h1>
<h4>TimeReport</h4>
<p>
<a asp-page="/TimeReportOverview/Index">Back to Index</a>
</p>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="TimeReport.TimeReportSupContactPointValue" value="0"/>
<div class="form-group">
<label asp-for="TimeReport.TimeReportId" class="control-label"></label>
<input asp-for="TimeReport.TimeReportId" value='#ViewData["RandomId"]' readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportCustomerNeedContactId" class="control-label"></label>
</div>
<select id="CusContactId" asp-for="CusContactDropDownDisp" asp-items="#(new SelectList(Model.CusContactDropDownDisp,"CusContactId","CusFullName"))">
<option value="" selected disabled>--Choose Customer--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportCustomerNeedContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportCustomerNeedContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportSupplierTalentContactId" class="control-label"></label>
</div>
<select id="SupContactId" asp-for="SupContactDropDownDisp" asp-items="#(new SelectList(Model.SupContactDropDownDisp,"SupContactId","SupFullName"))">
<option value="" selected disabled>--Choose Supplier--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportSupplierTalentContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportSupplierTalentContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportDate" class="control-label"></label>
<input type="datetime-local" asp-for="TimeReport.TimeReportDate" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportHours" class="control-label"></label>
<input asp-for="TimeReport.TimeReportHours" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportHours" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportText" class="control-label"></label>
<input asp-for="TimeReport.TimeReportText" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportText" class="text-danger"></span>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TimeReport.TimeReportState, htmlAttributes: new { #class = "form-group" })
<div class="form-group">
#Html.DropDownListFor(model => model.TimeReport.TimeReportState, new List<SelectListItem>
{
new SelectListItem {Text = "Gebucht", Value = "Reported", Selected = true },
new SelectListItem {Text = "Kontrolliert", Value = "Controlled" },
new SelectListItem {Text = "Verrechnet / Noch nicht bezahlt", Value = "Invoiced / Not yet payed" },
new SelectListItem {Text = "Verrechnet / Bezahlt", Value = "Invoiced / Payed" },
}, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TimeReport.TimeReportState, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
Back to List
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
$("#CusContactId").on("change", function () {
$("#TimeReport_TimeReportCustomerNeedContactId").val($("#CusContactId").val());
});
$("#SupContactId").on("change", function () {
$("#TimeReport_TimeReportSupplierTalentContactId").val($("#SupContactId").val());
});
</script>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Thank you for your help
First In your view:
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
GetHashCodemethod make the Guid to int,please make sure it matches the type in your model.
Then the right way to add new PointsforSupContact is to create a new PointsforSupContact,so you need to delete the code:
public Models.PointsforSupContact PointsforSupContact { get; set; }
and change you code to:
//...
await _context.SaveChangesAsync();
//add this line
var PointsforSupContact=new PointsforSupContact();
PointsforSupContact.PointsId = TimeReport.TimeReportId;
//...
EDIT: So After many failed attempts to figure out why this is not working I decided to create a project and choose to have user login implemented from there so it will configure everything for me.
after that I just scraped the automated login/register code and replaced it with my own. everything works amazingly well. I am pretty sure in my original version I missed some needed parameter
I am trying to make a simple login function. but I cant seem to get it to work and it drives me crazy ..
so I do my shared folder under _layout.cshtml I have added this
#inject SignInManager<IdentityUser> signInManager;
and then just a little later inside my navbar I added this elements
<ul class="navbar-nav ml-auto">
#if (signInManager.IsSignedIn(User)) {
<li class="nav-item">
<form method="post" asp-controller="User" asp-action="Logout">
<button type="submit" class="nav-link btn btn-link py-0" style="width:auto">
Logout #User.Identity.Name
</button>
</form>
</li>
}
else {
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="User" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="User" asp-action="Login">Login</a>
</li>
}
</ul>
and in my controller I added this I called this controller UserController.cs
If I enter wrong login info . like wrong password or username it will tell me I that. so the connection with the database is no issue. but when I am send in my "Home" Index I am not logged it. as if it does not create a session I am not sure
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(Login model)
{
if (ModelState.IsValid)
{
var result = await signInManager.PasswordSignInAsync(model.UserName,model.Password,
model.RememberMe,false);
if (result.Succeeded)
{
//creates a temponary sign in session cookie. that cookie is going to be lost after the browser is closed
return RedirectToAction("index", "home");
}
//if succeeded = false then ew llop through the error list
ModelState.AddModelError(string.Empty,"Invalid Login");
}
return View(model);
}
Here is the whole working demo like below:
View(Login.cshtml):
#using Microsoft.AspNetCore.Identity
#model LoginViewModel
#inject SignInManager<IdentityUser> SignInManager
#{
ViewData["Title"] = "Log in";
}
<h1>#ViewData["Title"].</h1>
<div class="row">
<div class="col-md-8">
<section>
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<h4>Use a local account to log in.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Password" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<label asp-for="RememberMe">
<input asp-for="RememberMe" />
#Html.DisplayNameFor(m => m.RememberMe)
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Log in</button>
</div>
</div>
<p>
<a asp-action="Register" asp-route-returnurl="#ViewData["ReturnUrl"]">Register as a new user?</a>
</p>
<p>
<a asp-action="ForgotPassword">Forgot your password?</a>
</p>
</form>
</section>
</div>
<div class="col-md-4">
<section>
<h4>Use another service to log in.</h4>
<hr />
#{
var schemes = await SignInManager.GetExternalAuthenticationSchemesAsync();
var loginProviders = schemes.ToList();
if (loginProviders.Count == 0)
{
<div>
<p>
There are no external authentication services configured. See this article
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<div>
<p>
#foreach (var provider in loginProviders)
{
<button type="submit" class="btn btn-default" name="provider" value="#provider.Name" title="Log in using your #provider.Name account">#provider.Name</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>
#section Scripts {
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Controller:
[Authorize]
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public IActionResult Login()
{
return View();
}
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
}
DbContext:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options) { }
}
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentityCore<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Result: