I have actions in different controllers which are decorated with [Authorize(Roles = "admin")]
and they are working fine.But the problem is that they always redirect to login page even if the user is loged in.for example following actions redirect to login page even if the user is loged in
[Authorize(Roles = "admin")]
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
VAT vat = db.VAT.Find(id);
db.VAT.Remove(vat);
db.SaveChanges();
return RedirectToAction("Index");
}
Can I redirect to other page if user is loged in or stop redirecting the page
Debug your application and check roles assigned to user for which they are redirecting if they are not having admin roles then it will redirect to the login page.
Another thing you can do is that you can redirect to separate page saying "You don't have rights to view this page" or something like this.
Also following question answer might help you.
Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?
How to redirect [Authorize] to loginUrl only when Roles are not used?
Possibly the answer you're looking for.
Related
When I decorate a method with an Authorize roles attribute it returns false everytime. I'm trying to limit access to an admin page for users in the "Admin" role only.
I have verified that the user im currently logged in as is in fact in the "Admin" role.
I have tried to use a custom authorization attribute. Same result. I can add the code if needed.
I have found that the authorization attribute works for Users but not for Roles.
I believe this problem is somehow tied into the fact that the following does not work in my application:
User.IsInRole("Admin").
However, this statement does work:
userManager.IsInRole(user.Id, "Admin")
Here is my code:
public class AdminController : Controller
{
//[AuthLog(Roles = "Admin")] //Custom authorization attribute
[Authorize(Roles = "Admin")]
public ActionResult Users()
{
return View();
}
}
Maybe this can help with debugging:
Microsoft.AspNet.Identity.Core: V.2.1.0
Microsoft.AspNet.Identity.EntityFramework: V.2.1.0
I am open to suggestions on anything else I can post from my project in order to debug easier. I have scoured the stack for 2 weeks now.
Update 1: How user is logged in
// POST: /account/login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountLoginModel viewModel)
{
// Ensure we have a valid viewModel to work with
if (!ModelState.IsValid)
return View(viewModel);
// Verify if a user exists with the provided identity information
var user = await _manager.FindByEmailAsync(viewModel.Email);
// If a user was found
if (user != null)
{
// Then create an identity for it and sign it in
await SignInAsync(user, viewModel.RememberMe);
// If the user came from a specific page, redirect back to it
return RedirectToLocal(viewModel.ReturnUrl);
}
// No existing user was found that matched the given criteria
ModelState.AddModelError("", "Invalid username or password.");
// If we got this far, something failed, redisplay form
return View(viewModel);
}
private async Task SignInAsync(IdentityUser user, bool isPersistent)
{
// Clear any lingering authencation data
FormsAuthentication.SignOut();
// Create a claims based identity for the current user
var identity = await _manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Write the authentication cookie
FormsAuthentication.SetAuthCookie(identity.Name, isPersistent);
}
The
FormsAuthentication.SetAuthCookie(identity.Name, isPersistent);
unfortunately doesn't store any roles with the identity. Thus, when the identity is recreated from the cookie, you have no roles. To verify try
this.User.IsInRole("Admin")
and you'll get false, even though the userManager tells you otherwise.
There are multiple workarounds.
You could for example switch to any other identity persistor, like the SessionAuthenticationModule which could store your username and roles in the cookie. You could follow my tutorial on that.
Another approach would be to have an explicit role manager and use its feature that automatically causes your roles to be stored in another cookie, separate from the forms authentication cookie. This involves configuring the role provider and writing your own role provider that would be an adapter over the user manager.
Finally, you could forget forms authentication and use Identity's native way of issuing cookies, which would involve calling SignInAsync on the authentication manager.
While login into the mvc application I have the following url as
http://localhost:51495/Account/Login/ClientA
Where ClientA is the name of the client.
My issue is after logoff I am not getting the exact URL which was shown at time of login. However, I am able to log off and return to login page successfully.
Below url is displayed after logoff
http://localhost:51495/
my logoff code
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LogOff()
{
await _signInManager.SignOutAsync();
_logger.LogInformation(4, "User logged out.");
return RedirectToAction(nameof(this.Login), "Account");
}
So what I need to do to get the same url which is shown at the time of login?
I am struggling over this issue since yesterday.I am working on a web application which includes email service.Email includes 'link' to a certain page of that application.
Now:I have 2 scenarios:
1) If the user is logged in(in the application) already and he hit
the url he got in his email,the link will open perfectly.
2) If the user is not logged in(in the application) then the url
will not open and will redirect itself to the login page with the
functionality added in the BaseController.
*
Now what I want is when the user logs in after hitting the url and on
successfully login the user gets redirect to the link provided in the
Email.
*
for eg: If the user gets an email to the detail page of an employee,So on successfully login the user gets redirect to the Detail page of the employee.
Something like appending the redirecturl to the login page.
I think rewriting url is what I should be doing.
But I dont know how can I use that in this case.Help me out.
The default project template that comes with ASP.NET MVC 5 behaves exactly as you describe.
If you want to redirect to a custom login URL, reconfigure the LoginPath property of the CookieAuthenticationOptions object
LoginPath = new PathString("/Account/Login")
In the default template this is done in the Startup.Auth.cs class.
NOTE: If you are using an old version of ASP.NET MVC, the default project template behaved in the same way. But previously this was implemented using Forms Authentication, so in order to redirect to a custom login URL you would then have to set the loginUrl attribute of the <forms> tag in the Web.config file
By default if a user tries to access the authorized page when he is not authorized the automatically gets redirected to the log in page or the page which is configured in web.config file for the element. And you can see the query string returnUrl having the url that was tried to access initially get appended to the log in url.
To access the return url, include a new parameter as returnUrl and maintain the return url in a hidden field by model data to access on post back for redirection.
If the user is authenticated then on post back then redirect the user to the specified page what he intended to go for.
I don't remember exactly but few month ago I implemented similar functionality and i had to save returnUrl explicitly (due to MVC bug or something) - Refer this link
AccountController.cs - Snapshot
[HttpGet]
[AllowAnonymous]
public ActionResult Login(string returnUrl, string userName)
{
// You login method logic....
// Add this line to save the returnUrl value
ViewBag.ReturnUrl = returnUrl;
}
Login.cshtml - Snapshot
#using (Html.BeginForm("Login", "Account", FormMethod.Post ,new {ReturnUrl = ViewBag.ReturnUrl}))
{
<input type="hidden" name="ReturnUrl" value="#Request.QueryString["ReturnUrl"]" />
// .....
}
See if this helps in your case.
I have 3 roles: Registered Users, Approved Users, and Admins.
Access to the site is only available to Approved users and Admins.
To restrict anonymous access I've added a filter in FilterConfig as follows:
filters.Add(new System.Web.Mvc.AuthorizeAttribute());
Now, for registered users I want them to redirect to a landing page saying:
Please contact one of the administrators to approve you.
I'm not really sure what's the correct way to do that.
I can setup authorize attribute on each of the controllers, but I'm not sure if that's a good way.
Also, I'm not sure where I should specify default redirect action based on the role.
I know that I can specify default redirect action in RouteConfig.cs but not sure where to specify a role.
StanK is right that having [Authorize] attribute will redirect all users who are not logged-in to the login page. That's half of your dillema.
From there you need to alter your logon method to check if a newly logged-in user has the right role (e.g. ConfirmedUser). This is tricky because User.IsInRole("ConfirmedUser") will always be false in your logon method. This is because the User object is populated by the http object, which will not be re-populated until the next re-cycle. Luckily, you can use the Roles.IsUserInRole(userName, "ConfirmedUser") to check if the user has the right role.
So, within your logon method, after authenticating user, log the user out and re-direct them to an [AllowAnonymous] method which informs them that they are not yet confirmed.
if (Roles.IsUserInRole(userName, "ConfirmedUser")
{
FormsAuthentication.SignOut();
return RedirectToAction("WarningMsg", "Home");
}
You should be able to use the [Authorize] attributes for this.
Restricted pages will have their controller or action decorated with [Authorize(Roles="Approved User,Admin")], the 'landing page' for registered users would be [Authorize(Roles="Registered User,Approved User,Admin")] and the Logon action would have [AllowAnonymous].
If the user is not authorised, they would be re-directed to Account/Login. You would need to build some logic in this action that redirects "Registered Users" who are already logged in to your landing page. Others should just see the standard login page.
EDIT
The logic to redirect "Registered Users" from the login page to the landing page would look something like this
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
if (User.Identity.IsAuthenticated && Roles.IsUserInRole("Registered User"))
return RedirectToAction("LandingPage");
ViewBag.ReturnUrl = returnUrl;
return View();
}
I have an Asp.Net MVC project with the typical forms authentication that redirects the user to a page upon successful login. If there is a ReturnUrl in the querystring it will redirect the user to the ReturnUrl.
Problem comes when a logged in user sits on a page long enough for their login to time out and then submits the form causing a post to the server. Since the user is now no longer authenticated it'll force the user to log in again. However the ReturnUrl would point to an action that only accepts the POST method and would throw an exception after being redirected.
Is there a work around for this?
You have to create an identical GET action and redirect it back to the form they were filling out. The problem is that the redirect to the ReturnUrl is doing a GET, not a POST, hence the error.
Example:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult SomeFormAction()
{
//redirect them back to the original form GET here
RedirectToAction(stuffhere);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SomeFormAction(FormCollection collection)
{
//this is your original POST
}