I have a MVC and a Web API projects within the same solution, on the MVC project I have a very small Admin area protected with a login and password (just for one user). On this area I get the data on clinet side using API calls.
This is my Login function:
public ActionResult SubmitLogin(string UserName, string Password)
{
if (ModelState.IsValid)
{
if (UserName == "xxxxx" && Password == "yyyyy")
{
FormsAuthentication.SetAuthCookie(UserName, true);
return RedirectToAction("Index", #"Admin/Users");
}
}
var errors = (from value in ModelState.Values
from error in value.Errors
select error.ErrorMessage).ToList();
if (errors.Count == 0)
{
errors.Add("UserName or Password are incorrect");
}
ViewBag.Message = errors;
return View("Index");
}
The Login form works fine, the issue is with the API calls, my API controller is [Authorize] but when I make a request:
self.getUsers = function (callback) {
$.get("../MySite.API/Users/GetUsers/", callback);
}
I get a 401 error.
I understand I have to somehow send the AuthCookie with the AJAX request but I'm not sure how.
Any help would be appreciated.
Related
I'm developing an application in Angular and .Net, it consists of creating projects -like Asana- each project has a creator, so there I made the connection, I related the table of users and projects to create the foreign key (userCreationId).
It's a POST request, this is my service:
public string ObtenerUsuarioId()
{
if (httpContext.User.Identity.IsAuthenticated)
{
var idClaim = httpContext.User.Claims
.Where(x => x.Type == ClaimTypes.NameIdentifier).Single();
return idClaim.Value;
}
else
{
throw new Exception("El usuario no está autenticado");
}
}
And the controller:
public async Task<IActionResult> Post([FromBody] ProyectoCreacionDTO proyectoCreacionDTO)
{
var proyecto = mapper.Map<Proyecto>(proyectoCreacionDTO);
var usuarioId = servicioUsuarios.ObtenerUsuarioId();
proyecto.UsuarioCreacionId = usuarioId;
context.Add(proyecto);
await context.SaveChangesAsync();
return Ok(proyecto);
}
But the request in Angular does not bring me the claims, and it falls in the else of my service in .net.
It doesn't read the email and the id.
error : "System.Exception: User isn't authenticated \r\n.
Which is the else of my service.
I tried the request on POSTMAN and it works:
It does read the email!
And I get the answer I was expecting:
A successful answer
But then again when I tried this in Angular it doesn't work, and I'm saving the token in LocalStorage
login(email:string, password:string):Observable<Login>{
return this.http.post<Login>(`${this.url}/login`, {email, password})
.pipe(
tap(resp => {
this.localStorage.getToken(resp.token)
})
)
crearProyecto(proyecto:Proyecto):Observable<Proyecto>{
return this.http.post<Proyecto>(`${this.url}/agregar`, proyecto)
The token is actually saved, I can protect routes with AuthGuards, so I dont know why when I send the request from Angular it doesn't work
Here is the token
I even have the Cookie that Identity generates:
The cookie
I have generated the WebApi, it contain method to login using login and password.
I cannot access the query string.
This link i already tried.but not get a result.it showing error.
http://localhost:58940/api/Login?loginName=AAA&password=123
Api controller
[HttpGet]
public IHttpActionResult GetLoginId(string loginName, string password)
{
LoginService loginSvc = new LoginService();
var res = loginSvc.GetLoginId(loginName,password);
if (res != null)
{
return Ok(res);
}
return NotFound();
}
In debug procees (debugger) controller code only executes, but not go to service,unitofwork,repository files in visual studio.
I am using Angular with asp.net Api 2 but post method is not working with Angular while it is working fine with Postman and i am using HttpInterceptor for user token.
User Service
saveUser(user: Users) {
const body: Users = {
userName: user.userName,
userPassword: user.userPassword,
userEmail: user.userEmail,
userFullname: user.userFullname,
userFirstname:user.userFullname,
userLastname:user.userFullname,
userType:user.userType,
userPhone :user.userPhone,
userBio :user.userBio
}
return this.http.post(this.rootUrl + '/api/Users/saveUser', body);
}
Request Screenshot
Error Screenshot
Api code
[Route("api/Users/saveUsers")]
[ResponseType(typeof(User))]
public IHttpActionResult PostUser([FromBody] User user)
{
db.Users.Add(user);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = user.UserID }, user);
}
I see that your API url when you making request is wrong
localhost:57286//api/Users/saveUsers
So you should change your code to
return this.http.post(this.rootUrl + 'api/Users/saveUsers', body);
And in your controller you should have HttpPost like this
If you are using ASP.Net you have to change to this
[HttpPost)]
[Route("api/Users/saveUsers")]
[ResponseType(typeof(User))]
And in ASP.Net Core
[HttpPost("api/Users/saveUsers")]
[ResponseType(typeof(User))]
So you can remove Route and replace with HttpPost
Please let me know if you still have problem
I have a login controller with a post action which redirects to home page after successful login. I am using following code for redirection, which works well in Chrome and Firefox. but doesn't redirect in IE and EDGE, and response cookie not set
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToRoute("default", new { controller = "", action = "" });
}
}
My Login action
public IActionResult Login(string userName, string password)
{
try
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new InvalidOperationException("Username/Password can not be empty");
var session = CreateSession(userName, password);
var returnUrl = Request.Query["returnUrl"];
return RedirectToLocal(returnUrl);
}
catch (Exception ex)
{
ModelState.AddModelError("Login", ex.Message);
}
return View();
}
I am using my own session management for which I set session cookies like following
CookieOptions option = new CookieOptions();
option.Path = AppPath;
option.Domain = AppHost;
httpContextAccessor.HttpContext.Response.Cookies.Append(AppSessionToken, "SomeSessionId", option);
After searching a lot for exact answer, I found that Internet Explorer (all versions) doesn't allow you to specify a domain of localhost, a local IP address or machine name. When you do, Internet Explorer simply ignores the cookie.
So I removed following line
option.Domain = AppHost;
from my codes and everything start working as expected on both IE and EDGE.
Since you didn't post your route mapping from Startup.cs, I am not sure why it didn't work for you. Maybe you shouldn't override the controller and action parameter by passing new { controller = "", action = "" } into the RedirectToRoute() method?
Instead, have you tried just calling the method with the route name, like
return RedirectToRoute("default");
Or, you can use RedirectToAction()
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
// action, controller and route values
return RedirectToAction("index", "home", new { area = "" });
when I was writing ASP.NET applications I used the Forms Authentication with my custom login page, like so:
Once login is a success I checked him as authenticated:
FormsAuthentication.RedirectFromLoginPage(userId.ToString(), true);
In order to check if a user is logged in, I had a class that inherited from a base page and all pages inherited from it, which contained a method that returned a bool after checking if the user is authenticated, with the following command:
return HttpContext.Current.User.Identity.IsAuthenticated;
Now, I'm doing an ASP.NET MVC application, and was wondering what is the best was to do that on MVC?
Thanks
ok MVC is very simple and similar
for your question you can use like .......
in your controller
public ActionResult LogOn()
{
return View();
}
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var userInfo = new UserInfo()
{
UserName = model.UserName,
Password = model.Password,
};
var service = new CSVService();
if(service.ValidateUser(userInfo))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return Redirect("~/");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The best way to authenticate website / web-application is using the Membership which is provided by Microsoft built in for Easy-ness .
From this you can do following things(features)
it maintains Log-in status (you don't have to bother about Authentication).
It allows to provide Roles & Users and Assigning permission who can see which page
(Page Restriction)
It provides built-in Stored Procedures and UI tools like Log-in, Log-out,user,Password Recovery, Etc elements. & Highly secure (Hack-Proof)
for more info:
Walk through Membership (MSDN)